001/* 002 * Configurate 003 * Copyright (C) zml and Configurate contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.spongepowered.configurate; 018 019import io.leangen.geantyref.TypeToken; 020import org.checkerframework.checker.nullness.qual.Nullable; 021import org.spongepowered.configurate.serialize.SerializationException; 022import org.spongepowered.configurate.serialize.TypeSerializer; 023import org.spongepowered.configurate.util.CheckedConsumer; 024 025import java.lang.reflect.Type; 026import java.util.List; 027import java.util.Map; 028import java.util.stream.Collector; 029 030/** 031 * Intermediate node type to reduce need for casting. 032 * 033 * <p>Any methods that return {@link ConfigurationNode} in 034 * {@link ConfigurationNode} should be overridden to return the {@link N} 035 * self-type instead.</p> 036 * 037 * @param <N> self type 038 * @since 4.0.0 039 */ 040public interface ScopedConfigurationNode<N extends ScopedConfigurationNode<N>> extends ConfigurationNode { 041 042 /** 043 * Get a correctly typed instance of this node. 044 * 045 * @return the node type 046 * @since 4.0.0 047 */ 048 N self(); 049 050 /** 051 * {@inheritDoc} 052 */ 053 @Override 054 N appendListNode(); 055 056 /** 057 * {@inheritDoc} 058 */ 059 @Override 060 N copy(); 061 062 /** 063 * {@inheritDoc} 064 */ 065 @Override 066 N node(Object... path); 067 068 /** 069 * {@inheritDoc} 070 */ 071 @Override 072 N node(Iterable<?> path); 073 074 /** 075 * {@inheritDoc} 076 */ 077 @Override 078 @Nullable N parent(); 079 080 /** 081 * {@inheritDoc} 082 */ 083 @Override 084 N from(ConfigurationNode other); 085 086 /** 087 * {@inheritDoc} 088 */ 089 @Override 090 N mergeFrom(ConfigurationNode other); 091 092 /** 093 * {@inheritDoc} 094 */ 095 @Override 096 N set(@Nullable Object value) throws SerializationException; 097 098 /** 099 * {@inheritDoc} 100 */ 101 @Override 102 @SuppressWarnings({"unchecked", "rawtypes"}) // for TypeSerializer.serialize 103 default N set(Type type, @Nullable Object value) throws SerializationException { 104 if (value == null) { 105 return set(null); 106 } 107 108 final @Nullable TypeSerializer<?> serial = options().serializers().get(type); 109 if (serial != null) { 110 ((TypeSerializer) serial).serialize(type, value, self()); 111 } else if (options().acceptsType(value.getClass())) { 112 raw(value); // Just write if no applicable serializer exists? 113 } else { 114 throw new SerializationException("No serializer available for type " + type); 115 } 116 return self(); 117 } 118 119 @Override 120 default <V> N set(Class<V> type, @Nullable V value) throws SerializationException { 121 return set((Type) type, value); 122 } 123 124 @Override 125 default <V> N set(TypeToken<V> type, @Nullable V value) throws SerializationException { 126 return set(type.getType(), value); 127 } 128 129 @Override 130 default <V> N setList(Class<V> elementType, @Nullable List<V> items) throws SerializationException { 131 ConfigurationNode.super.setList(elementType, items); 132 return self(); 133 } 134 135 @Override 136 default <V> N setList(TypeToken<V> elementType, @Nullable List<V> items) throws SerializationException { 137 ConfigurationNode.super.setList(elementType, items); 138 return self(); 139 } 140 141 /** 142 * {@inheritDoc} 143 */ 144 @Override 145 N raw(@Nullable Object value); 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 List<N> childrenList(); 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 Map<Object, N> childrenMap(); 158 159 /** 160 * {@inheritDoc} 161 */ 162 @SuppressWarnings({"unchecked", "rawtypes"}) 163 @Override 164 default <V> Collector<Map.Entry<?, V>, N, N> toMapCollector(final TypeToken<V> valueType) { 165 return (Collector) ConfigurationNode.super.toMapCollector(valueType); 166 } 167 168 /** 169 * {@inheritDoc} 170 */ 171 @SuppressWarnings({"unchecked", "rawtypes"}) 172 @Override 173 default <V> Collector<Map.Entry<?, V>, N, N> toMapCollector(final Class<V> valueType) { 174 return (Collector) ConfigurationNode.super.toMapCollector(valueType); 175 } 176 177 /** 178 * {@inheritDoc} 179 */ 180 @SuppressWarnings({"unchecked", "rawtypes"}) 181 @Override 182 default <V> Collector<V, N, N> toListCollector(final TypeToken<V> valueType) { 183 return (Collector) ConfigurationNode.super.toListCollector(valueType); 184 } 185 186 /** 187 * {@inheritDoc} 188 */ 189 @SuppressWarnings({"unchecked", "rawtypes"}) 190 @Override 191 default <V> Collector<V, N, N> toListCollector(final Class<V> valueType) { 192 return (Collector) ConfigurationNode.super.toListCollector(valueType); 193 } 194 195 /** 196 * Execute an action on this node. This allows performing multiple 197 * operations on a single node without having to clutter up the surrounding 198 * scope. 199 * 200 * @param <E> thrown type 201 * @param action the action to perform on this node 202 * @return this node 203 * @since 4.0.0 204 */ 205 default <E extends Exception> N act(CheckedConsumer<? super N, E> action) throws E { 206 action.accept(self()); 207 return self(); 208 } 209 210 @Override 211 <V> N hint(RepresentationHint<V> hint, @Nullable V value); 212 213}