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.serialize;
018
019import org.checkerframework.checker.nullness.qual.Nullable;
020import org.spongepowered.configurate.ConfigurationNode;
021import org.spongepowered.configurate.ConfigurationOptions;
022import org.spongepowered.configurate.util.CheckedFunction;
023
024import java.lang.reflect.Type;
025import java.util.function.BiFunction;
026import java.util.function.Predicate;
027
028/**
029 * Represents an object which can serialize and deserialize objects of a
030 * given type.
031 *
032 * @param <T> the type
033 * @since 4.0.0
034 */
035public interface TypeSerializer<T> {
036
037    /**
038     * Given the provided functions, create a new serializer for a scalar value.
039     *
040     * <p>The returned serializer must fulfill all the requirements of a {@link ScalarSerializer}
041     *
042     * @param type the type of value returned by the serializer
043     * @param serializer the serialization function, implementing {@link ScalarSerializer#serialize(Object, Predicate)}
044     * @param deserializer the deserialization function, implementing {@link ScalarSerializer#deserialize(Type, Object)}
045     * @param <T> the type of value to deserialize
046     * @return a new and unregistered type serializer
047     * @since 4.0.0
048     */
049    static <T> ScalarSerializer<T> of(Type type, BiFunction<T, Predicate<Class<?>>, Object> serializer,
050                                      CheckedFunction<Object, T, SerializationException> deserializer) {
051        return new FunctionScalarSerializer<>(type, deserializer, serializer);
052    }
053
054    /**
055     * Given the provided functions, create a new serializer for a scalar value.
056     *
057     * <p>The returned serializer must fulfill all the requirements of
058     * a {@link ScalarSerializer}
059     *
060     * @param type the type of value. Must not be a parameterized type
061     * @param serializer the serialization function, implementing {@link ScalarSerializer#serialize(Object, Predicate)}
062     * @param deserializer the deserialization function, implementing {@link ScalarSerializer#deserialize(Type, Object)}
063     * @param <T> the type of value to deserialize
064     * @return a new and unregistered type serializer
065     * @see #of(Type, BiFunction, CheckedFunction) for the version of this
066     *      function that takes a parameterized type
067     * @since 4.0.0
068     */
069    static <T> ScalarSerializer<T> of(Class<T> type,
070            BiFunction<T, Predicate<Class<?>>, Object> serializer, CheckedFunction<Object, T, SerializationException> deserializer) {
071        if (type.getTypeParameters().length > 0) {
072            throw new IllegalArgumentException("Parameterized types must be specified using TypeTokens, not raw classes");
073        }
074
075        return new FunctionScalarSerializer<T>(type, deserializer, serializer);
076    }
077
078    /**
079     * Deserialize an object (of the correct type) from the given configuration
080     * node.
081     *
082     * @param type the type of return value required
083     * @param node the node containing serialized data
084     * @return an object
085     * @throws SerializationException if the presented data is invalid
086     * @since 4.0.0
087     */
088    T deserialize(Type type, ConfigurationNode node) throws SerializationException;
089
090    /**
091     * Serialize an object to the given configuration node.
092     *
093     * @param type the type of the input object
094     * @param obj the object to be serialized
095     * @param node the node to write to
096     * @throws SerializationException if the object cannot be serialized
097     * @since 4.0.0
098     */
099    void serialize(Type type, @Nullable T obj, ConfigurationNode node) throws SerializationException;
100
101    /**
102     * Create an empty value of the appropriate type.
103     *
104     * <p>This method is for the most part designed to create empty collection
105     * types, though it may be useful for scalars in limited cases.</p>
106     *
107     * @param specificType specific subtype to create an empty value of
108     * @param options options used from the loading node
109     * @return new empty value
110     * @since 4.0.0
111     */
112    default @Nullable T emptyValue(final Type specificType, ConfigurationOptions options) {
113        return null;
114    }
115
116}