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.objectmapping; 018 019import io.leangen.geantyref.TypeToken; 020import org.spongepowered.configurate.ConfigurationNode; 021import org.spongepowered.configurate.objectmapping.meta.Constraint; 022import org.spongepowered.configurate.objectmapping.meta.NodeResolver; 023import org.spongepowered.configurate.objectmapping.meta.Processor; 024import org.spongepowered.configurate.serialize.SerializationException; 025import org.spongepowered.configurate.serialize.TypeSerializer; 026import org.spongepowered.configurate.serialize.TypeSerializerCollection; 027import org.spongepowered.configurate.util.NamingScheme; 028 029import java.lang.annotation.Annotation; 030import java.lang.reflect.Type; 031import java.util.List; 032 033/** 034 * A mapper that converts between configuration nodes and Java objects. 035 * 036 * <p>Object mappers are created through a {@link Factory}, either the default 037 * one or one created with additional options. See that class's 038 * documentation for details.</p> 039 * 040 * <p>The object mapper can be accessed directly, through its {@link #factory()}, 041 * or through a {@link ConfigurationNode}'s 042 * {@link ConfigurationNode#get(TypeToken)} method. To use a custom factory 043 * instance through a node, a custom TypeSerializer has to be registered to the 044 * {@link TypeSerializerCollection} used 045 * by the node.</p> 046 * 047 * @param <V> mapped type 048 * @since 4.0.0 049 */ 050public interface ObjectMapper<V> { 051 052 /** 053 * Get the default object mapper factory instance. 054 * 055 * <p>This factory has the following characteristics:</p> 056 * <ul> 057 * <li>can resolve fields in empty-constructor objects and Records</li> 058 * <li>will try to resolve any field in objects</li> 059 * <li>supports {@link org.spongepowered.configurate.objectmapping.meta.NodeKey} and 060 * {@link org.spongepowered.configurate.objectmapping.meta.Setting} annotations 061 * for customizing node resolution</li> 062 * <li>uses the {@link org.spongepowered.configurate.util.NamingSchemes#LOWER_CASE_DASHED} 063 * naming scheme for other nodes</li> 064 * <li>supports unlocalized {@link org.spongepowered.configurate.objectmapping.meta.Matches}, 065 * and {@link org.spongepowered.configurate.objectmapping.meta.Required} 066 * constraints</li> 067 * <li>processes {@link org.spongepowered.configurate.objectmapping.meta.Comment} 068 * annotations</li> 069 * </ul> 070 * 071 * @return default factory 072 * @since 4.0.0 073 */ 074 static Factory factory() { 075 return ObjectMapperFactoryImpl.INSTANCE; 076 } 077 078 /** 079 * Create an empty builder. 080 * 081 * <p>This applies none of the standard formats, processors, constraints or 082 * resolvers. Unless you want to do something particularly specialized, 083 * you should probably be using {@link #factoryBuilder()}.</p> 084 * 085 * @return new empty builder 086 * @since 4.0.0 087 */ 088 static Factory.Builder emptyFactoryBuilder() { 089 return new ObjectMapperFactoryImpl.Builder(); 090 } 091 092 /** 093 * Create a builder populated with default settings. 094 * 095 * <p>This builder is prepared to allow overriding any of the default 096 * object mapper features.</p> 097 * 098 * @return new builder 099 * @see #factory() for a description of the default settings 100 * @since 4.0.0 101 */ 102 static Factory.Builder factoryBuilder() { 103 return ObjectMapperFactoryImpl.defaultBuilder(); 104 } 105 106 /** 107 * Create a new object instance. 108 * 109 * @param source object source 110 * @return new instance 111 * @throws SerializationException if any invalid data is present. Loading is 112 * done in stages, so any deserialization errors will occur before 113 * anything is written to objects. 114 * @since 4.0.0 115 */ 116 V load(ConfigurationNode source) throws SerializationException; 117 118 /** 119 * Write data from the provided object to the target. 120 * 121 * @param value value type 122 * @param target destination 123 * @throws SerializationException if unable to fully save 124 * @since 4.0.0 125 */ 126 void save(V value, ConfigurationNode target) throws SerializationException; 127 128 /** 129 * Get the parameters that will be handled by this mapper. 130 * 131 * @return immutable list of fields 132 * @since 4.0.0 133 */ 134 List<? extends FieldData<?, V>> fields(); 135 136 /** 137 * The generic type of object that this mapper instance handles. 138 * 139 * @return object type 140 * @since 4.0.0 141 */ 142 Type mappedType(); 143 144 /** 145 * Get whether or not this mapper is capable of creating new instances of 146 * its mapped type. 147 * 148 * <p>If this returns {@code false}, {@link #load(ConfigurationNode)} will 149 * always fail.</p> 150 * 151 * @return if the mapped type can be instantiated. 152 * @since 4.0.0 153 */ 154 boolean canCreateInstances(); 155 156 /** 157 * An object mapper capable of loading data into an existing object. 158 * 159 * @param <V> value type 160 * @since 4.0.0 161 */ 162 interface Mutable<V> extends ObjectMapper<V> { 163 164 /** 165 * Load data from {@code node} into an existing instance. 166 * 167 * @param value existing instance 168 * @param node node to load from 169 * @throws SerializationException if unable to deserialize data 170 * @since 4.0.0 171 */ 172 void load(V value, ConfigurationNode node) throws SerializationException; 173 174 } 175 176 /** 177 * Provider for object mappers. 178 * 179 * @since 4.0.0 180 */ 181 interface Factory { 182 183 /** 184 * Get an object mapper for the provided type. 185 * 186 * <p>The provided type cannot be a <em>raw type</em>.</p> 187 * 188 * @param type token holding the mapped type 189 * @param <V> mapped type 190 * @return a mapper for the provided type 191 * @throws SerializationException if the type does not correspond to a 192 * mappable object 193 * @since 4.0.0 194 */ 195 @SuppressWarnings("unchecked") 196 default <V> ObjectMapper<V> get(TypeToken<V> type) throws SerializationException { 197 return (ObjectMapper<V>) get(type.getType()); 198 } 199 200 /** 201 * Get an object mapper for the unparameterized type {@code clazz}. 202 * 203 * <p>The provided type cannot be a <em>raw type</em>.</p> 204 * 205 * @param clazz class of the mapped type 206 * @param <V> mapped type 207 * @return a mapper for the provided type 208 * @throws SerializationException if the type does not correspond to a 209 * mappable object 210 * @since 4.0.0 211 */ 212 @SuppressWarnings("unchecked") 213 default <V> ObjectMapper<V> get(Class<V> clazz) throws SerializationException { 214 return (ObjectMapper<V>) get((Type) clazz); 215 } 216 217 /** 218 * Get the object mapper for the provided type. 219 * 220 * <p>The provided type cannot be a <em>raw type</em>.</p> 221 * 222 * @param type object type. 223 * @return a mapper for the provided type 224 * @throws SerializationException if the type does not correspond to a 225 * mappable object 226 * @since 4.0.0 227 */ 228 ObjectMapper<?> get(Type type) throws SerializationException; 229 230 /** 231 * Creates a {@link TypeSerializer} that uses this factory. 232 * 233 * <p>The serializer will accept any object type that could otherwise be 234 * handled by this factory. To match a standard configuration, 235 * register this serializer with {@link TypeSerializerCollection.Builder#registerAnnotatedObjects(Factory)} 236 * to enforce the presence of {@link ConfigSerializable} annotations.</p> 237 * 238 * @return a type serializer 239 * @since 4.0.0 240 */ 241 TypeSerializer<Object> asTypeSerializer(); 242 243 /** 244 * A builder for a configured factory producing object mappers. 245 * 246 * <p>In general, with multiple applicable resolvers, the one registered 247 * last will take priority.</p> 248 * 249 * @since 4.0.0 250 */ 251 interface Builder { 252 253 /** 254 * Set the naming scheme to use as a default for field names. 255 * 256 * <p>This can be overridden by other 257 * {@link NodeResolver NodeResolvers} for specific nodes.</p> 258 * 259 * @param scheme naming scheme 260 * @return this builder 261 * @since 4.0.0 262 */ 263 Builder defaultNamingScheme(NamingScheme scheme); 264 265 /** 266 * Add a resolver that will locate a node for a field. 267 * 268 * @param resolver the resolver 269 * @return this builder 270 * @since 4.0.0 271 */ 272 Builder addNodeResolver(NodeResolver.Factory resolver); 273 274 /** 275 * Add a discoverer for a type of object. 276 * 277 * <p>Field discoverers will be tried in order until one can 278 * produce the appropriate metadata.</p> 279 * 280 * @param discoverer field discoverer 281 * @return this builder 282 * @since 4.0.0 283 */ 284 Builder addDiscoverer(FieldDiscoverer<?> discoverer); 285 286 /** 287 * Register a {@link Processor} that will process fields after write. 288 * 289 * <p>Processors registered without a specific data type should be 290 * able to operate on any value type.</p> 291 * 292 * @param definition annotation providing data 293 * @param factory factory for callback function 294 * @param <A> annotation type 295 * @return this builder 296 * @since 4.0.0 297 */ 298 default <A extends Annotation> Builder addProcessor(Class<A> definition, Processor.Factory<A, Object> factory) { 299 return addProcessor(definition, Object.class, factory); 300 } 301 302 /** 303 * Register a {@link Processor} that will process fields after write. 304 * 305 * <p>All value types will be tested against types normalized to 306 * their boxed variants.</p> 307 * 308 * @param definition annotation providing data 309 * @param valueType value types the processor will handle 310 * @param factory factory for callback function 311 * @param <A> annotation type 312 * @param <T> data type 313 * @return this builder 314 * @since 4.0.0 315 */ 316 <A extends Annotation, T> Builder addProcessor(Class<A> definition, Class<T> valueType, Processor.Factory<A, T> factory); 317 318 /** 319 * Register a {@link Constraint} that will be used to validate fields. 320 * 321 * <p>Constraints registered without a specific data type will be 322 * able to operate on any value type.</p> 323 * 324 * @param definition annotations providing data 325 * @param factory factory for callback function 326 * @param <A> annotation type 327 * @return this builder 328 * @since 4.0.0 329 */ 330 default <A extends Annotation> Builder addConstraint(Class<A> definition, Constraint.Factory<A, Object> factory) { 331 return addConstraint(definition, Object.class, factory); 332 } 333 334 /** 335 * Register a {@link Constraint} that will be used to validate fields. 336 * 337 * <p>All value types will be tested against types normalized to 338 * their boxed variants.</p> 339 * 340 * @param definition annotations providing data 341 * @param valueType value types the processor will handle 342 * @param factory factory for callback function 343 * @param <A> annotation type 344 * @param <T> data type 345 * @return this builder 346 * @since 4.0.0 347 */ 348 <A extends Annotation, T> Builder addConstraint(Class<A> definition, Class<T> valueType, Constraint.Factory<A, T> factory); 349 350 /** 351 * Create a new factory using the current configuration. 352 * 353 * @return new factory instance 354 * @since 4.0.0 355 */ 356 Factory build(); 357 358 } 359 360 } 361 362}