Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[599] Add better support for resolution of wildcard types. #661

Merged
merged 3 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion etc/copyright.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ die(){ echo "${1}" ; exit 1 ;}
readonly RESULT_FILE="target/copyright-check.txt"
mkdir target

mvn -q org.glassfish.copyright:glassfish-copyright-maven-plugin:copyright \
mvn -q validate -Pcopyright \
> ${RESULT_FILE} || (cat ${RESULT_FILE}; die "Error running the Maven command")

grep -i "copyright" ${RESULT_FILE} \
Expand Down
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@
<plugin>
<groupId>org.glassfish.copyright</groupId>
<artifactId>glassfish-copyright-maven-plugin</artifactId>
<configuration>
<!-- Ignore the year to comply with Eclipse Foundation. -->
<ignoreYear>true</ignoreYear>
</configuration>
<executions>
<!--Copyright goal does not fail when copyright is not properly updated,
but prints out which file has incorrect copyright.-->
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) 2015 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) 2021 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 @@ -233,7 +233,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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure if this is the correct place to fix this. I did attempt to fix it by defaulting to Optional.of(Object.class) in the ReflecionUtils.getOptionalRawType(). However, that did break some tests and I wasn't sure if that was correct either.

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) 2015 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);
}

}
Loading