Skip to content

Commit

Permalink
[eclipse-ee4j#617] Refactored repeated code in SerializationModelCrea…
Browse files Browse the repository at this point in the history
…tor & DeserializationModelCreator in serializer / deserializer creation from serializer / deserializer / adapter configuration in annotations

Signed-off-by: Anton Pinsky <[email protected]>
  • Loading branch information
api-from-the-ion committed Feb 12, 2024
1 parent ef7da0a commit e6054b2
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 163 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import jakarta.json.bind.JsonbException;
import jakarta.json.bind.config.BinaryDataStrategy;
import jakarta.json.bind.config.PropertyNamingStrategy;
import jakarta.json.stream.JsonParser;

import org.eclipse.yasson.internal.ComponentMatcher;
import org.eclipse.yasson.internal.DeserializationContextImpl;
import org.eclipse.yasson.internal.JsonbConfigProperties;
import org.eclipse.yasson.internal.JsonbContext;
Expand Down Expand Up @@ -149,47 +151,27 @@ private ModelDeserializer<JsonParser> deserializerChainInternal(LinkedList<Type>
} else if (userTypeMapping.containsKey(rawType)) {
Class<?> userTypeRaw = userTypeMapping.get(rawType);
ModelDeserializer<JsonParser> deserializer = deserializerChain(userTypeRaw);
models.put(cachedItem, deserializer);
return deserializer;
return cacheDeserializer(cachedItem, deserializer);
}

ClassCustomization classCustomization = classModel.getClassCustomization();
Optional<DeserializerBinding<?>> deserializerBinding = userDeserializer(type,
(ComponentBoundCustomization) propertyCustomization);
if (deserializerBinding.isPresent()) {
UserDefinedDeserializer user = new UserDefinedDeserializer(deserializerBinding.get().getComponent(),
JustReturn.instance(), type, classCustomization);
models.put(cachedItem, user);
return user;
ModelDeserializer<JsonParser> deserializer = createUserOrAdapterDeserializer(type, (ComponentBoundCustomization) propertyCustomization,
(adapterToType) -> {
Class<?> toType = ReflectionUtils.getRawType(adapterToType);
return typeDeserializer(toType,
jsonbContext.getMappingContext().getOrCreateClassModel(toType).getClassCustomization(),
JustReturn.instance());
},
JustReturn.instance(),
context -> context,
classCustomization,
() -> typeDeserializer(rawType,
propertyCustomization,
JustReturn.instance()));
if (deserializer != null) {
return cacheDeserializer(cachedItem, deserializer);
}

Optional<AdapterBinding<?, ?>> adapterBinding = adapterBinding(type, (ComponentBoundCustomization) propertyCustomization);
if (adapterBinding.isPresent()) {
AdapterBinding<?, ?> adapter = adapterBinding.get();
Class<?> toType = ReflectionUtils.getRawType(adapter.getToType());
ClassModel targetModel = jsonbContext.getMappingContext().getOrCreateClassModel(toType);
ModelDeserializer<JsonParser> typeDeserializer = typeDeserializer(toType,
targetModel.getClassCustomization(),
JustReturn.instance());
if (typeDeserializer == null) {
typeDeserializer = deserializerChain(adapter.getToType());
}
ModelDeserializer<JsonParser> targetAdapterModel = typeDeserializer;
AdapterDeserializer adapterDeserializer = new AdapterDeserializer(adapter, JustReturn.instance());
ModelDeserializer<JsonParser> adapterDeser = (parser, context) -> {
Object fromJson = targetAdapterModel.deserialize(parser, context);
return adapterDeserializer.deserialize(fromJson, context);
};
models.put(cachedItem, adapterDeser);
return adapterDeser;
}
ModelDeserializer<JsonParser> typeDeserializer = typeDeserializer(rawType,
propertyCustomization,
JustReturn.instance());
if (typeDeserializer != null) {
models.put(cachedItem, typeDeserializer);
return typeDeserializer;
}
if (Collection.class.isAssignableFrom(rawType)) {
return createCollectionDeserializer(cachedItem, rawType, chain);
} else if (Map.class.isAssignableFrom(rawType)) {
Expand Down Expand Up @@ -257,8 +239,7 @@ private ModelDeserializer<JsonParser> createObjectDeserializer(LinkedList<Type>
positionChecker = new PositionChecker(instanceCreator, rawType, Event.START_OBJECT);
}
ModelDeserializer<JsonParser> nullChecker = new NullCheckDeserializer(positionChecker, JustReturn.instance());
models.put(cachedItem, nullChecker);
return nullChecker;
return cacheDeserializer(cachedItem, nullChecker);
}

private ModelDeserializer<JsonParser> createCollectionDeserializer(CachedItem cachedItem,
Expand All @@ -278,8 +259,7 @@ private ModelDeserializer<JsonParser> createCollectionDeserializer(CachedItem ca
CollectionInstanceCreator instanceDeserializer = new CollectionInstanceCreator(collectionDeserializer, type);
PositionChecker positionChecker = new PositionChecker(instanceDeserializer, rawType, Event.START_ARRAY);
NullCheckDeserializer nullChecker = new NullCheckDeserializer(positionChecker, JustReturn.instance());
models.put(cachedItem, nullChecker);
return nullChecker;
return cacheDeserializer(cachedItem, nullChecker);
}

private ModelDeserializer<JsonParser> createMapDeserializer(CachedItem cachedItem,
Expand Down Expand Up @@ -309,8 +289,7 @@ private ModelDeserializer<JsonParser> createMapDeserializer(CachedItem cachedIte
rawType);
PositionChecker positionChecker = new PositionChecker(mapInstanceCreator, rawType, PositionChecker.Checker.CONTAINER);
NullCheckDeserializer nullChecker = new NullCheckDeserializer(positionChecker, JustReturn.instance());
models.put(cachedItem, nullChecker);
return nullChecker;
return cacheDeserializer(cachedItem, nullChecker);
}

private ModelDeserializer<JsonParser> createArrayDeserializer(CachedItem cachedItem,
Expand All @@ -327,8 +306,7 @@ private ModelDeserializer<JsonParser> createArrayDeserializer(CachedItem cachedI
ModelDeserializer<JsonParser> base64Deserializer = ArrayInstanceCreator.createBase64Deserializer(strategy,
typeProcessor);
NullCheckDeserializer nullChecker = new NullCheckDeserializer(base64Deserializer, JustReturn.instance());
models.put(cachedItem, nullChecker);
return nullChecker;
return cacheDeserializer(cachedItem, nullChecker);
}
Class<?> arrayType = rawType.getComponentType();
ModelDeserializer<JsonParser> typeProcessor = typeProcessor(chain,
Expand Down Expand Up @@ -359,8 +337,7 @@ private ModelDeserializer<JsonParser> createArrayCommonDeserializer(CachedItem c
ArrayInstanceCreator arrayInstanceCreator = ArrayInstanceCreator.create(rawType, component, arrayDeserializer);
PositionChecker positionChecker = new PositionChecker(arrayInstanceCreator, rawType, Event.START_ARRAY);
NullCheckDeserializer nullChecker = new NullCheckDeserializer(positionChecker, JustReturn.instance());
models.put(cachedItem, nullChecker);
return nullChecker;
return cacheDeserializer(cachedItem, nullChecker);
}

private OptionalDeserializer createOptionalDeserializer(LinkedList<Type> chain,
Expand All @@ -372,8 +349,7 @@ private OptionalDeserializer createOptionalDeserializer(LinkedList<Type> chain,
: Object.class;
ModelDeserializer<JsonParser> typeProcessor = typeProcessor(chain, colType, propertyCustomization, JustReturn.instance());
OptionalDeserializer optionalDeserializer = new OptionalDeserializer(typeProcessor, JustReturn.instance());
models.put(cachedItem, optionalDeserializer);
return optionalDeserializer;
return cacheDeserializer(cachedItem, optionalDeserializer);
}

private Set<String> collectIgnoredProperties(TypeInheritanceConfiguration typeInheritanceConfiguration) {
Expand All @@ -389,23 +365,50 @@ private Set<String> collectIgnoredProperties(TypeInheritanceConfiguration typeIn
}

private Function<String, String> propertyRenamer() {
boolean isCaseInsensitive = jsonbContext.getConfig()
.getProperty(PROPERTY_NAMING_STRATEGY)
.filter(prop -> prop.equals(PropertyNamingStrategy.CASE_INSENSITIVE))
.isPresent();

return isCaseInsensitive
? String::toLowerCase
: value -> value;
return jsonbContext.getConfig()
.getProperty(PROPERTY_NAMING_STRATEGY)
.filter(prop -> prop.equals(PropertyNamingStrategy.CASE_INSENSITIVE))
.map(val -> (Function<String, String>) String::toLowerCase).orElse(value -> value);
}

private Optional<AdapterBinding<?, ?>> adapterBinding(Type type, ComponentBoundCustomization classCustomization) {
return jsonbContext.getComponentMatcher().getDeserializeAdapterBinding(type, classCustomization);
}

private Optional<DeserializerBinding<?>> userDeserializer(Type type, ComponentBoundCustomization classCustomization) {
return jsonbContext.getComponentMatcher().getDeserializerBinding(type, classCustomization);
}
/**
* Create a deserializer from deserializer's or adapter's description in the given type.
*
* @param type type to find the information about deserializer or adapter
* @param customization customization witch probably has information about deserializer or adapter
* @param adapterTypeDeserializerCreateFunction function to create a deserializer for the type in which adapter maps
* @param delegate delegate deserializer for the deserializer created from deserializer or adapter
* @param adapterTypeDeserializerContextChangeFunction function to change the context of the deserializer for the type in which adapter maps, if
* needed
* @param deserializerCustomization customization to use on deserializer creation from deserializer information
* @param alternativeDeserializerSupplier supplier of the deserializer if no adapter or deserializer configuration was found for given
* customization
* @return deserializer for the given type or alternative deserializer if no deserializer or adapter was configured for the class or property
*/
private ModelDeserializer<JsonParser> createUserOrAdapterDeserializer(Type type, ComponentBoundCustomization customization,
Function<Type, ModelDeserializer<JsonParser>> adapterTypeDeserializerCreateFunction,
ModelDeserializer<Object> delegate,
Function<DeserializationContextImpl, DeserializationContextImpl> adapterTypeDeserializerContextChangeFunction,
Customization deserializerCustomization,
Supplier<ModelDeserializer<JsonParser>> alternativeDeserializerSupplier) {
// try to create a deserializer from deserializer configuration
ComponentMatcher componentMatcher = jsonbContext.getComponentMatcher();
Optional<DeserializerBinding<?>> deserializerBinding = componentMatcher.getDeserializerBinding(type, customization);
return deserializerBinding.map(binding ->
(ModelDeserializer<JsonParser>) new UserDefinedDeserializer(binding.getComponent(), delegate, type, deserializerCustomization))
.orElseGet(() -> {
// otherwise try to create a deserializer from adapter configuration or use alternative deserializer
Optional<AdapterBinding<?, ?>> adapterBinding = componentMatcher.getDeserializeAdapterBinding(type, customization);
return adapterBinding.map(adapter -> {
AdapterDeserializer adapterDeserializer = new AdapterDeserializer(adapter, delegate);
Type toType = adapter.getToType();
ModelDeserializer<JsonParser> typeDeserializer = adapterTypeDeserializerCreateFunction.apply(toType);
ModelDeserializer<JsonParser> targetAdapterModel = typeDeserializer == null ? deserializerChain(toType) : typeDeserializer;
return (ModelDeserializer<JsonParser>) (parser, context) ->
adapterDeserializer.deserialize(targetAdapterModel.deserialize(parser, adapterTypeDeserializerContextChangeFunction.apply(context)), context);
}).orElseGet(alternativeDeserializerSupplier);
});
}

private List<String> creatorParamsList(JsonbCreator creator) {
return Arrays.stream(creator.getParams()).map(CreatorModel::getName).collect(Collectors.toList());
Expand Down Expand Up @@ -437,46 +440,24 @@ private ModelDeserializer<JsonParser> typeProcessor(LinkedList<Type> chain,
Set<Event> events) {
Type resolved = ReflectionUtils.resolveType(chain, type);
Class<?> rawType = ReflectionUtils.getRawType(resolved);
Optional<DeserializerBinding<?>> deserializerBinding = userDeserializer(resolved,
(ComponentBoundCustomization) customization);
if (deserializerBinding.isPresent()) {
//TODO remove or not? fix for deserializer cycle
// ModelDeserializer<JsonParser> exactType = createNewChain(chain, memberDeserializer, rawType,
// resolved, customization);
// return new UserDefinedDeserializer(deserializerBinding.get().getJsonbDeserializer(),
// exactType,
// memberDeserializer,
// resolved,
// customization);
return new UserDefinedDeserializer(deserializerBinding.get().getComponent(),
memberDeserializer,
resolved,
customization);
}
Optional<AdapterBinding<?, ?>> adapterBinding = adapterBinding(resolved, (ComponentBoundCustomization) customization);
if (adapterBinding.isPresent()) {
AdapterBinding<?, ?> adapter = adapterBinding.get();
ModelDeserializer<JsonParser> typeDeserializer = typeDeserializer(ReflectionUtils.getRawType(adapter.getToType()),
customization,
JustReturn.instance(), events);
if (typeDeserializer == null) {
typeDeserializer = deserializerChain(adapter.getToType());
}
ModelDeserializer<JsonParser> targetAdapterModel = typeDeserializer;

AdapterDeserializer adapterDeserializer = new AdapterDeserializer(adapter, memberDeserializer);
return (parser, context) -> {
DeserializationContextImpl newContext = new DeserializationContextImpl(context);
Object fromJson = targetAdapterModel.deserialize(parser, newContext);
return adapterDeserializer.deserialize(fromJson, context);
};
}
ModelDeserializer<JsonParser> typeDeserializer = typeDeserializer(rawType, customization, memberDeserializer, events);
if (typeDeserializer == null) {
Class<?> implClass = resolveImplClass(rawType, customization);
return createNewChain(chain, memberDeserializer, implClass, resolved, customization);
/* TODO remove or not? fix for deserializer cycle
ModelDeserializer<JsonParser> exactType = createNewChain(chain, memberDeserializer, rawType,
resolved, customization);
return new UserDefinedDeserializer(deserializerBinding.get().getJsonbDeserializer(),
exactType,
memberDeserializer,
resolved,
customization);*/
ModelDeserializer<JsonParser> deserializer = createUserOrAdapterDeserializer(resolved, (ComponentBoundCustomization) customization,
(adapterToType) -> typeDeserializer(ReflectionUtils.getRawType(adapterToType), customization, JustReturn.instance(), events),
memberDeserializer,
DeserializationContextImpl::new,
customization,
() -> typeDeserializer(rawType, customization, memberDeserializer, events));
if (deserializer != null) {
return deserializer;
}
return typeDeserializer;
return createNewChain(chain, memberDeserializer, resolveImplClass(rawType, customization), resolved, customization);
}

private ModelDeserializer<JsonParser> createNewChain(LinkedList<Type> chain,
Expand Down Expand Up @@ -530,6 +511,11 @@ private CachedItem createCachedItem(Type type, Customization customization) {
return new CachedItem(type, customization.getDeserializeNumberFormatter(), customization.getDeserializeDateFormatter());
}

private <T extends ModelDeserializer<JsonParser>> T cacheDeserializer(CachedItem cachedItem, T deserializer) {
models.put(cachedItem, deserializer);
return deserializer;
}

private static final class CachedItem {

private final Type type;
Expand Down
Loading

0 comments on commit e6054b2

Please sign in to comment.