Skip to content

Commit

Permalink
[eclipse-ee4j#617] Refactored code with Optional - use more Optional API
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Pinsky <[email protected]>
  • Loading branch information
api-from-the-ion committed Feb 12, 2024
1 parent fa1f4e1 commit 0574ee2
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,13 @@ JsonbCreator createJsonbCreator(Executable executable, JsonbCreator existing, Cl
@SuppressWarnings("unchecked")
final AdapterBinding<?, ?> adapterBinding = jsonbContext.getComponentMatcher().introspectAdapterBinding(adapterClass, null);

if (expectedClass.isPresent() && !(
ReflectionUtils.getRawType(adapterBinding.getBindingType()).isAssignableFrom(expectedClass.get()))) {
throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_INCOMPATIBLE,
adapterBinding.getBindingType(),
expectedClass.get()));
}
expectedClass.ifPresent(clazz -> {
if (!ReflectionUtils.getRawType(adapterBinding.getBindingType()).isAssignableFrom(clazz)) {
throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_INCOMPATIBLE,
adapterBinding.getBindingType(),
clazz));
}
});
return adapterBinding;
}

Expand Down Expand Up @@ -387,7 +388,6 @@ public Optional<Boolean> isPropertyNillable(Property property) {
@SuppressWarnings("deprecation")
Optional<Boolean> optionalBoolean = jsonbProperty.map(JsonbProperty::nillable);
return optionalBoolean;

}

/**
Expand Down Expand Up @@ -466,14 +466,12 @@ public Map<AnnotationTarget, JsonbDateFormatter> getJsonbDateFormatCategorized(P

// No date format on property, try class level
// if property is not TypeVariable and its class is not date skip it
final Optional<Class<?>> propertyRawTypeOptional = ReflectionUtils.getOptionalRawType(property.getPropertyType());
if (propertyRawTypeOptional.isPresent()) {
Class<?> rawType = propertyRawTypeOptional.get();
if (!(
Date.class.isAssignableFrom(rawType) || Calendar.class.isAssignableFrom(rawType)
|| TemporalAccessor.class.isAssignableFrom(rawType))) {
return new HashMap<>();
}
Map<AnnotationTarget, JsonbDateFormatter> map = ReflectionUtils.getOptionalRawType(property.getPropertyType()).map(rawType ->
(Date.class.isAssignableFrom(rawType) || Calendar.class.isAssignableFrom(rawType)
|| TemporalAccessor.class.isAssignableFrom(rawType)) ? null : new HashMap<AnnotationTarget, JsonbDateFormatter>())
.orElse(null);
if (map != null) {
return map;
}

JsonbDateFormat classLevelDateFormatter = findAnnotation(property.getDeclaringClassElement().getAnnotations(),
Expand Down
54 changes: 25 additions & 29 deletions src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;

import jakarta.json.bind.JsonbConfig;
import jakarta.json.bind.adapter.JsonbAdapter;
Expand Down Expand Up @@ -203,53 +205,47 @@ public Optional<DeserializerBinding<?>> getDeserializerBinding(Type propertyRunt
return Optional.of(customization.getDeserializeAdapterBinding());
}

private <C, T extends AbstractComponentBinding<? extends C>> Optional<T> searchComponentBinding(Type runtimeType, Function<ComponentBindings<?, ?>, T> supplier) {
private <C, T extends AbstractComponentBinding<? extends C>> Optional<T> searchComponentBinding(Type runtimeType,
Function<ComponentBindings<?, ?>, T> bindingGetter) {
// First check if there is an exact match
Optional<T> match = getMatchingBinding(runtimeType, supplier);
Optional<T> match = getMatchingBinding(runtimeType, bindingGetter);
if (match.isPresent()) {
return match;
}

Optional<Class<?>> runtimeClass = ReflectionUtils.getOptionalRawType(runtimeType);
if (runtimeClass.isPresent()) {
return runtimeClass.map(clazz -> {
// Check if any interfaces have a match
for (Class<?> ifc : runtimeClass.get().getInterfaces()) {
match = getMatchingBinding(ifc, supplier);
if (match.isPresent()) {
return match;
}
Optional<T> interfaceMatch = findBindingInClasses(Arrays.stream(clazz.getInterfaces()), ifc -> getMatchingBinding(ifc, bindingGetter));
if (interfaceMatch.isPresent()) {
return interfaceMatch;
}

// check if the superclass has a match
Class<?> superClass = runtimeClass.get().getSuperclass();
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && superClass != Object.class) {
Optional<T> superBinding = searchComponentBinding(superClass, supplier);
Optional<T> superBinding =
findBindingInClasses(Stream.of(superClass), superClazz -> searchComponentBinding(superClazz, bindingGetter));
if (superBinding.isPresent()) {
return superBinding;
}
}
}

return Optional.empty();
return Optional.<T>empty();
}).orElse(Optional.empty());
}

private <C, T extends AbstractComponentBinding<? extends C>> Optional<T> getMatchingBinding(Type runtimeType, Function<ComponentBindings<?, ?>, T> supplier) {
ComponentBindings<?, ?> binding = userComponents.get(runtimeType);
if (binding != null) {
Optional<T> match = getMatchingBinding(runtimeType, binding, supplier);
if (match.isPresent()) {
return match;
}
}
return Optional.empty();
private <T> Optional<T> findBindingInClasses(Stream<Class<?>> stream, Function<Class<?>, Optional<T>> mapper) {
return stream
.map(mapper)
.filter(Optional::isPresent)
.findFirst().orElse(Optional.empty());
}

private <T> Optional<T> getMatchingBinding(Type runtimeType, ComponentBindings<?, ?> binding, Function<ComponentBindings<?, ?>, T> supplier) {
if (matches(runtimeType, binding.getBindingType())) {
final T component = supplier.apply(binding);
if (component != null) {
return Optional.of(component);
}
private <C, T extends AbstractComponentBinding<? extends C>> Optional<T> getMatchingBinding(Type runtimeType,
Function<ComponentBindings<?, ?>, T> bindingGetter) {
ComponentBindings<?, ?> binding = userComponents.get(runtimeType);
if (binding != null) {
return (matches(runtimeType, binding.getBindingType())) ? Optional.ofNullable(bindingGetter.apply(binding)) : Optional.empty();
}
return Optional.empty();
}
Expand Down
14 changes: 4 additions & 10 deletions src/main/java/org/eclipse/yasson/internal/JsonbContext.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -177,18 +177,12 @@ private JsonParserFactory initJsonParserFactory() {
protected Map<String, ?> createJsonpProperties(JsonbConfig jsonbConfig) {
//JSONP 1.0 actually ignores the value, just checks the key is present. Only set if JsonbConfig.FORMATTING is true.
final Optional<Object> property = jsonbConfig.getProperty(JsonbConfig.FORMATTING);
final Map<String, Object> factoryProperties = new HashMap<>();
if (property.isPresent()) {
final Object value = property.get();
return property.map(value -> {
if (!(value instanceof Boolean)) {
throw new JsonbException(Messages.getMessage(MessageKeys.JSONB_CONFIG_FORMATTING_ILLEGAL_VALUE));
}
if ((Boolean) value) {
factoryProperties.put(JsonGenerator.PRETTY_PRINTING, Boolean.TRUE);
}
return factoryProperties;
}
return factoryProperties;
return (Boolean) value ? new HashMap<>(Map.of(JsonGenerator.PRETTY_PRINTING, Boolean.TRUE)) : new HashMap<String, Object>();
}).orElse(new HashMap<>());
}

private JsonbComponentInstanceCreator initComponentInstanceCreator() {
Expand Down
16 changes: 6 additions & 10 deletions src/main/java/org/eclipse/yasson/internal/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,12 @@ public static Optional<Class<?>> getOptionalRawType(Type type) {
} else if (type instanceof TypeVariable) {
TypeVariable<?> typeVariable = TypeVariable.class.cast(type);
if (Objects.nonNull(typeVariable.getBounds())) {
Optional<Class<?>> specializedClass = Optional.empty();
for (Type bound : typeVariable.getBounds()) {
Optional<Class<?>> boundRawType = getOptionalRawType(bound);
if (boundRawType.isPresent() && !Object.class.equals(boundRawType.get())) {
if (specializedClass.isEmpty() || specializedClass.get().isAssignableFrom(boundRawType.get())) {
specializedClass = boundRawType;
}
}
}
return specializedClass;
return Arrays.stream(typeVariable.getBounds())
.map(ReflectionUtils::getOptionalRawType)
.filter(Optional::isPresent)
.filter(clazz -> !Object.class.equals(clazz.get()))
.reduce((clazz1, clazz2) -> clazz1.map(clazzGet1 -> clazzGet1.isAssignableFrom(clazz2.get())).orElse(false) ? clazz2 : clazz1)
.orElse(Optional.empty());
}
}
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -30,18 +30,18 @@ class UserDefinedDeserializer implements ModelDeserializer<JsonParser> {
private final Type rType;
private final Customization customization;

//TODO remove or not? deserializer cycle
// public UserDefinedDeserializer(JsonbDeserializer<?> userDefinedDeserializer,
// ModelDeserializer<JsonParser> exactType,
// ModelDeserializer<Object> delegate,
// Type rType,
// Customization customization) {
// this.userDefinedDeserializer = userDefinedDeserializer;
// this.exactType = exactType;
// this.delegate = delegate;
// this.rType = rType;
// this.customization = customization;
// }
/*TODO remove or not? deserializer cycle
public UserDefinedDeserializer(JsonbDeserializer<?> userDefinedDeserializer,
ModelDeserializer<JsonParser> exactType,
ModelDeserializer<Object> delegate,
Type rType,
Customization customization) {
this.userDefinedDeserializer = userDefinedDeserializer;
this.exactType = exactType;
this.delegate = delegate;
this.rType = rType;
this.customization = customization;
}*/
UserDefinedDeserializer(JsonbDeserializer<?> userDefinedDeserializer,
ModelDeserializer<Object> delegate,
Type rType,
Expand All @@ -56,15 +56,15 @@ class UserDefinedDeserializer implements ModelDeserializer<JsonParser> {
public Object deserialize(JsonParser value, DeserializationContextImpl context) {
DeserializationContextImpl newContext = new DeserializationContextImpl(context);
newContext.setCustomization(customization);
//TODO remove or not? deserializer cycle
// if (context.getUserProcessorChain().contains(userDefinedDeserializer.getClass())) {
// if (context.getLastValueEvent() != JsonParser.Event.START_ARRAY
// && context.getLastValueEvent() != JsonParser.Event.START_OBJECT) {
// newContext.setDisableNextPositionCheck(true);
// }
// return exactType.deserialize(value, newContext);
// }
// newContext.getUserProcessorChain().add(userDefinedDeserializer.getClass());
/*TODO remove or not? deserializer cycle
if (context.getUserProcessorChain().contains(userDefinedDeserializer.getClass())) {
if (context.getLastValueEvent() != JsonParser.Event.START_ARRAY
&& context.getLastValueEvent() != JsonParser.Event.START_OBJECT) {
newContext.setDisableNextPositionCheck(true);
}
return exactType.deserialize(value, newContext);
}
newContext.getUserProcessorChain().add(userDefinedDeserializer.getClass());*/
YassonParser yassonParser = new YassonParser(value, context.getLastValueEvent(), newContext);
Object object = userDefinedDeserializer.deserialize(yassonParser, newContext, rType);
yassonParser.skipRemaining();
Expand Down

0 comments on commit 0574ee2

Please sign in to comment.