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 io.leangen.geantyref.GenericTypeReflector; 020import org.checkerframework.checker.nullness.qual.Nullable; 021import org.spongepowered.configurate.ConfigurationNode; 022import org.spongepowered.configurate.ConfigurationOptions; 023import org.spongepowered.configurate.util.CheckedFunction; 024 025import java.lang.reflect.AnnotatedType; 026import java.lang.reflect.Type; 027import java.util.function.BiFunction; 028import java.util.function.Predicate; 029 030/** 031 * Represents an object which can serialize and deserialize objects of a 032 * given type. 033 * 034 * <p>The type serializer interface has methods both for working with 035 * annotated types, and discarding annotated type information. If annotation 036 * information is desired, the {@link Annotated} interface overrides the 037 * standard TypeSerializer interface to prefer annotated type information.</p> 038 * 039 * @param <T> the type 040 * @since 4.0.0 041 */ 042public interface TypeSerializer<T> { 043 044 /** 045 * Given the provided functions, create a new serializer for a scalar value. 046 * 047 * <p>The returned serializer must fulfill all the requirements of a {@link ScalarSerializer} 048 * 049 * @param type the type of value returned by the serializer 050 * @param serializer the serialization function, implementing {@link ScalarSerializer#serialize(Object, Predicate)} 051 * @param deserializer the deserialization function, implementing {@link ScalarSerializer#deserialize(Type, Object)} 052 * @param <T> the type of value to deserialize 053 * @return a new and unregistered type serializer 054 * @since 4.0.0 055 */ 056 static <T> ScalarSerializer<T> of(final Type type, final BiFunction<T, Predicate<Class<?>>, Object> serializer, 057 final CheckedFunction<Object, T, SerializationException> deserializer) { 058 return new FunctionScalarSerializer<>(type, deserializer, serializer); 059 } 060 061 /** 062 * Given the provided functions, create a new serializer for a scalar value. 063 * 064 * <p>The returned serializer must fulfill all the requirements of 065 * a {@link ScalarSerializer} 066 * 067 * @param type the type of value. Must not be a parameterized type 068 * @param serializer the serialization function, implementing {@link ScalarSerializer#serialize(Object, Predicate)} 069 * @param deserializer the deserialization function, implementing {@link ScalarSerializer#deserialize(Type, Object)} 070 * @param <T> the type of value to deserialize 071 * @return a new and unregistered type serializer 072 * @see #of(Type, BiFunction, CheckedFunction) for the version of this 073 * function that takes a parameterized type 074 * @since 4.0.0 075 */ 076 static <T> ScalarSerializer<T> of(final Class<T> type, 077 final BiFunction<T, Predicate<Class<?>>, Object> serializer, final CheckedFunction<Object, T, SerializationException> deserializer) { 078 if (type.getTypeParameters().length > 0) { 079 throw new IllegalArgumentException("Parameterized types must be specified using TypeTokens, not raw classes"); 080 } 081 082 return new FunctionScalarSerializer<T>(type, deserializer, serializer); 083 } 084 085 /** 086 * Deserialize an object (of the correct type) from the given 087 * configuration node. 088 * 089 * @param type the annotated type of return value required 090 * @param node the node containing serialized data 091 * @return an object 092 * @throws SerializationException if the presented data is invalid 093 * @since 4.2.0 094 */ 095 default T deserialize(final AnnotatedType type, final ConfigurationNode node) throws SerializationException { 096 return this.deserialize(type.getType(), node); 097 } 098 099 /** 100 * Deserialize an object (of the correct type) from the given configuration 101 * node. 102 * 103 * @param type the type of return value required 104 * @param node the node containing serialized data 105 * @return an object 106 * @throws SerializationException if the presented data is invalid 107 * @since 4.0.0 108 */ 109 T deserialize(Type type, ConfigurationNode node) throws SerializationException; 110 111 /** 112 * Serialize an object to the given configuration node. 113 * 114 * @param type the annotated type of the input object 115 * @param obj the object to be serialized 116 * @param node the node to write to 117 * @throws SerializationException if the object cannot be serialized 118 * @since 4.2.0 119 */ 120 default void serialize(final AnnotatedType type, final @Nullable T obj, final ConfigurationNode node) throws SerializationException { 121 this.serialize(type.getType(), obj, node); 122 } 123 124 /** 125 * Serialize an object to the given configuration node. 126 * 127 * @param type the type of the input object 128 * @param obj the object to be serialized 129 * @param node the node to write to 130 * @throws SerializationException if the object cannot be serialized 131 * @since 4.0.0 132 */ 133 void serialize(Type type, @Nullable T obj, ConfigurationNode node) throws SerializationException; 134 135 /** 136 * Create an empty value of the appropriate type. 137 * 138 * <p>This method is for the most part designed to create empty collection 139 * types, though it may be useful for scalars in limited cases.</p> 140 * 141 * @param specificType specific subtype to create an empty value of 142 * @param options options used from the loading node 143 * @return new empty value 144 * @since 4.0.0 145 */ 146 default @Nullable T emptyValue(final Type specificType, final ConfigurationOptions options) { 147 return null; 148 } 149 150 /** 151 * Create an empty value of the appropriate type. 152 * 153 * <p>This method is for the most part designed to create empty 154 * collection types, though it may be useful for scalars 155 * in limited cases.</p> 156 * 157 * @param specificType specific annotated subtype to create an empty 158 * value of 159 * @param options options used from the loading node 160 * @return new empty value 161 * @since 4.2.0 162 */ 163 default @Nullable T emptyValue(final AnnotatedType specificType, final ConfigurationOptions options) { 164 return this.emptyValue(specificType.getType(), options); 165 } 166 167 /** 168 * A type serializer that prefers type use annotation metadata to 169 * deserialize the type. 170 * 171 * 172 * @param <V> the value type 173 * @since 4.2.0 174 */ 175 interface Annotated<V> extends TypeSerializer<V> { 176 177 @Override 178 V deserialize(AnnotatedType type, ConfigurationNode node) throws SerializationException; 179 180 @Override 181 default V deserialize(final Type type, final ConfigurationNode node) throws SerializationException { 182 return this.deserialize(GenericTypeReflector.annotate(type), node); 183 } 184 185 @Override 186 void serialize(AnnotatedType type, @Nullable V obj, ConfigurationNode node) throws SerializationException; 187 188 @Override 189 default void serialize(final Type type, final @Nullable V obj, final ConfigurationNode node) throws SerializationException { 190 this.serialize(GenericTypeReflector.annotate(type), obj, node); 191 } 192 193 @Override 194 default @Nullable V emptyValue(final AnnotatedType specificType, final ConfigurationOptions options) { 195 return null; 196 } 197 198 @Override 199 default @Nullable V emptyValue(final Type specificType, final ConfigurationOptions options) { 200 return this.emptyValue(GenericTypeReflector.annotate(specificType), options); 201 } 202 203 } 204 205}