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}