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 static java.util.Objects.requireNonNull; 020 021import org.checkerframework.checker.nullness.qual.Nullable; 022import org.spongepowered.configurate.serialize.SerializationException; 023import org.spongepowered.configurate.util.CheckedFunction; 024 025import java.lang.reflect.AnnotatedElement; 026import java.lang.reflect.AnnotatedType; 027import java.util.function.Supplier; 028 029/** 030 * Interface that gathers metadata from classes. 031 * 032 * <p>Any type of data object can be added this way.</p> 033 * 034 * @param <I> intermediate data type 035 * @since 4.0.0 036 */ 037public interface FieldDiscoverer<I> { 038 039 /** 040 * Create a new field discoverer that will handle record classes. 041 * 042 * @return new discoverer 043 * @since 4.0.0 044 */ 045 static FieldDiscoverer<?> record() { 046 return RecordFieldDiscoverer.INSTANCE; 047 } 048 049 /** 050 * Create a new discoverer for object instance fields. 051 * 052 * <p>This discoverer will process any non-static and non-transient field 053 * in the object.</p> 054 * 055 * @param instanceFactory a factory for instance providers 056 * @return new discoverer 057 * @since 4.0.0 058 */ 059 static FieldDiscoverer<?> object(final CheckedFunction<AnnotatedType, @Nullable Supplier<Object>, SerializationException> instanceFactory) { 060 return new ObjectFieldDiscoverer(requireNonNull(instanceFactory, "instanceFactory")); 061 } 062 063 /** 064 * Create a new discoverer for object instance fields. 065 * 066 * <p>Only objects with empty constructors can be created.</p> 067 * 068 * @return new discoverer 069 * @see #object(CheckedFunction) for more details on which fields will 070 * be discovered. 071 * @since 4.0.0 072 */ 073 static FieldDiscoverer<?> emptyConstructorObject() { 074 return ObjectFieldDiscoverer.EMPTY_CONSTRUCTOR_INSTANCE; 075 } 076 077 /** 078 * Inspect the {@code target} type for fields to be supplied to 079 * the {@code collector}. 080 * 081 * <p>If the target type is handleable, a non-null value must be returned. 082 * Fields can only be collected from one source at the moment, so if the 083 * instance factory is null any discovered fields will be discarded.</p> 084 * 085 * @param target type to inspect 086 * @param collector collector for discovered fields. 087 * @param <V> object type 088 * @return a factory for handling the construction of object instances, or 089 * {@code null} if {@code target} is not of a handleable type. 090 * @throws SerializationException if any fields have invalid data 091 * @since 4.0.0 092 */ 093 <V> @Nullable InstanceFactory<I> discover(AnnotatedType target, FieldCollector<I, V> collector) throws SerializationException; 094 095 /** 096 * A handler that controls the deserialization process for an object. 097 * 098 * @param <I> intermediate type 099 * @since 4.0.0 100 */ 101 interface InstanceFactory<I> { 102 103 /** 104 * Return a new instance of the intermediary type to be populated. 105 * 106 * @return new intermediate container 107 * @since 4.0.0 108 */ 109 I begin(); 110 111 /** 112 * Return a finalized object based on the provided intermediate. 113 * 114 * @param intermediate intermediate container to hold values 115 * @return final value 116 * @throws SerializationException if unable to construct a 117 * @since 4.0.0 118 */ 119 Object complete(I intermediate) throws SerializationException; 120 121 /** 122 * Get whether or not new object instances can be created. 123 * 124 * @return new instance creation 125 * @since 4.0.0 126 */ 127 boolean canCreateInstances(); 128 } 129 130 /** 131 * A handler for working with mutable objects in the object mapper. 132 * 133 * @param <I> intermediate type 134 * @since 4.0.0 135 */ 136 interface MutableInstanceFactory<I> extends InstanceFactory<I> { 137 138 /** 139 * Apply the intermediate data to an existing object. 140 * 141 * @param instance instance to write to 142 * @param intermediate intermediate container 143 * @throws SerializationException if unable to apply info 144 * @since 4.0.0 145 */ 146 void complete(Object instance, I intermediate) throws SerializationException; 147 } 148 149 /** 150 * A collector for the necessary metadata for fields. 151 * 152 * @param <I> intermediate type 153 * @param <V> container type 154 * @since 4.0.0 155 */ 156 @FunctionalInterface 157 interface FieldCollector<I, V> { 158 159 /** 160 * Accept metadata that defines a specific field. 161 * 162 * @param name name 163 * @param type declared field type, as resolved as possible 164 * @param annotations combined element containing all annotations 165 * applicable to the field 166 * @param deserializer a function to populate the intermediate state 167 * with a single deserialized field value. 168 * @param serializer a function to extract a value from a completed 169 * object instance. 170 * @since 4.0.0 171 */ 172 void accept(String name, AnnotatedType type, AnnotatedElement annotations, FieldData.Deserializer<I> deserializer, 173 CheckedFunction<V, @Nullable Object, Exception> serializer); 174 } 175 176}