Skip to content

Commit

Permalink
[599] Add better support for resolution of wildcard types.
Browse files Browse the repository at this point in the history
Signed-off-by: James R. Perkins <[email protected]>
  • Loading branch information
jamezp committed Feb 6, 2025
1 parent 14e68b6 commit 332fada
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025 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 @@ -190,6 +190,10 @@ public static Type resolveItemVariableType(List<Type> chain, TypeVariable<?> typ
if (tmp != null) {
returnType = tmp;
}
// If the type is a WildcardType we need to resolve the most specific type
if (returnType instanceof WildcardType) {
return resolveMostSpecificBound(chain, (WildcardType) returnType, warn);
}
if (!(returnType instanceof TypeVariable)) {
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025 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 @@ -34,6 +34,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
import jakarta.json.bind.config.BinaryDataStrategy;
import jakarta.json.bind.config.PropertyNamingStrategy;
Expand Down Expand Up @@ -233,7 +235,7 @@ private ModelDeserializer<JsonParser> createObjectDeserializer(LinkedList<Type>
if (creatorModel.getCustomization().isRequired()) {
defaultCreatorValues.put(parameterName, new RequiredCreatorParameter(parameterName));
} else {
Class<?> rawParamType = ReflectionUtils.getRawType(creatorModel.getType());
Class<?> rawParamType = ReflectionUtils.getOptionalRawType(creatorModel.getType()).orElse(Object.class);
defaultCreatorValues.put(parameterName, DEFAULT_CREATOR_VALUES.getOrDefault(rawParamType, NULL_PROVIDER));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025 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 All @@ -13,6 +13,7 @@
package org.eclipse.yasson.defaultmapping.generics;

import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
Expand All @@ -36,8 +37,11 @@
import org.eclipse.yasson.defaultmapping.generics.model.AnotherGenericTestClass;
import org.eclipse.yasson.defaultmapping.generics.model.BoundedGenericClass;
import org.eclipse.yasson.defaultmapping.generics.model.Circle;
import org.eclipse.yasson.defaultmapping.generics.model.CollectionContainer;
import org.eclipse.yasson.defaultmapping.generics.model.CollectionElement;
import org.eclipse.yasson.defaultmapping.generics.model.CollectionWrapper;
import org.eclipse.yasson.defaultmapping.generics.model.ColoredCircle;
import org.eclipse.yasson.defaultmapping.generics.model.ConstructorContainer;
import org.eclipse.yasson.defaultmapping.generics.model.CyclicSubClass;
import org.eclipse.yasson.defaultmapping.generics.model.FinalGenericWrapper;
import org.eclipse.yasson.defaultmapping.generics.model.FinalMember;
Expand All @@ -49,6 +53,7 @@
import org.eclipse.yasson.defaultmapping.generics.model.MyCyclicGenericClass;
import org.eclipse.yasson.defaultmapping.generics.model.PropagatedGenericClass;
import org.eclipse.yasson.defaultmapping.generics.model.Shape;
import org.eclipse.yasson.defaultmapping.generics.model.StaticCreatorContainer;
import org.eclipse.yasson.defaultmapping.generics.model.WildCardClass;
import org.eclipse.yasson.defaultmapping.generics.model.WildcardMultipleBoundsClass;
import org.eclipse.yasson.serializers.model.Box;
Expand Down Expand Up @@ -474,6 +479,40 @@ public void lowerBoundTypeVariableInCollectionAttribute() throws Exception {
assertEquals(6, fromJson.get(0).field1);

}

@Test
public void genericConstructorCreator() {
final String expectedJson = "{\"value\":\"Test\"}";
final ConstructorContainer<String> container = new ConstructorContainer<>("Test");

assertEquals(expectedJson, defaultJsonb.toJson(container));
assertEquals(container, defaultJsonb.fromJson(expectedJson, ConstructorContainer.class));
}

@Test
public void genericStaticCreator() {
final String expectedJson = "{\"value\":\"static\"}";
final StaticCreatorContainer<String> container = StaticCreatorContainer.create("static");

assertEquals(expectedJson, defaultJsonb.toJson(container));
assertEquals(container, defaultJsonb.fromJson(expectedJson, StaticCreatorContainer.class));
}

@Test
public void wildcardCollectionContainer() {
final String expectedJson = "{\"collection\":{\"collection\":[{\"wrapped\":\"wrappedElement\"}]}}";
final CollectionContainer collectionContainer = new CollectionContainer();
final CollectionWrapper<CollectionElement<?>> collectionWrapper = new CollectionWrapper<>();
final CollectionElement<String> wildcardType = new CollectionElement<>();
wildcardType.setWrapped("wrappedElement");
final Collection<CollectionElement<?>> list = List.of(wildcardType);
collectionWrapper.setCollection(list);
collectionContainer.setCollection(collectionWrapper);

assertEquals(expectedJson, defaultJsonb.toJson(collectionContainer));
final CollectionContainer result = defaultJsonb.fromJson(expectedJson, CollectionContainer.class);
assertEquals(collectionContainer, result);
}

public interface FunctionalInterface<T> {
T getValue();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 Red Hat, Inc. and/or its affiliates.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.yasson.defaultmapping.generics.model;

import java.util.Collection;
import java.util.Objects;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class CollectionContainer {

private CollectionWrapper<CollectionElement<?>> collection;

public CollectionWrapper<CollectionElement<?>> getCollection() {
return collection;
}

public void setCollection(final CollectionWrapper<CollectionElement<?>> collection) {
this.collection = collection;
}

@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof CollectionContainer)) {
return false;
}
final CollectionContainer other = (CollectionContainer) obj;
final Collection<CollectionElement<?>> thisCollection = collection.getCollection();
final Collection<CollectionElement<?>> otherCollection = other.collection.getCollection();
if (thisCollection == null && otherCollection == null) {
return true;
}
if (thisCollection == null || otherCollection == null) {
return false;
}
return thisCollection.containsAll(otherCollection) && otherCollection.containsAll(thisCollection);
}

@Override
public int hashCode() {
return Objects.hash(collection);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2025 Red Hat, Inc. and/or its affiliates.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.yasson.defaultmapping.generics.model;

import java.util.Objects;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class CollectionElement<T> {

private T wrapped;

public T getWrapped() {
return wrapped;
}

public void setWrapped(T wrapped) {
this.wrapped = wrapped;
}

@Override
public int hashCode() {
return Objects.hash(wrapped);
}

@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CollectionElement)) {
return false;
}
final CollectionElement<?> other = (CollectionElement<?>) obj;
return Objects.equals(wrapped, other.wrapped);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 Red Hat, Inc. and/or its affiliates.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.yasson.defaultmapping.generics.model;

import java.util.Objects;

import jakarta.json.bind.annotation.JsonbCreator;
import jakarta.json.bind.annotation.JsonbProperty;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class ConstructorContainer<T> {

private final T value;

@JsonbCreator
public ConstructorContainer(@JsonbProperty("value") final T value) {
this.value = value;
}

public T getValue() {
return value;
}

@Override
public String toString() {
return "ConstructorContainer[value=" + value + "]";
}

@Override
public int hashCode() {
return Objects.hash(value);
}

@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ConstructorContainer)) {
return false;
}
final ConstructorContainer<?> other = (ConstructorContainer<?>) obj;
return Objects.equals(value, other.value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2025 Red Hat, Inc. and/or its affiliates.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.yasson.defaultmapping.generics.model;

import java.util.Objects;

import jakarta.json.bind.annotation.JsonbCreator;
import jakarta.json.bind.annotation.JsonbProperty;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class StaticCreatorContainer<T> {
private final T value;

private StaticCreatorContainer(T value) {
this.value = value;
}

@JsonbCreator
public static <T> StaticCreatorContainer<T> create(@JsonbProperty("value") final T value) {
return new StaticCreatorContainer<>(value);
}

public T getValue() {
return value;
}

@Override
public String toString() {
return "StaticCreatorContainer[value=" + value + "]";
}

@Override
public int hashCode() {
return Objects.hash(value);
}

@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof StaticCreatorContainer)) {
return false;
}
final StaticCreatorContainer<?> other = (StaticCreatorContainer<?>) obj;
return Objects.equals(value, other.value);
}

}

0 comments on commit 332fada

Please sign in to comment.