This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 20b218b77983d986927000e9b006a4ecf71df300
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Sep 23 19:20:31 2020 +0200
Parameterize `Numbers.primitiveToWrapper(Class<N>)` method.
It avoids "unsafe cast" warning in `FeatureTypebuilder.addAttribute(…)`.
---
.../sis/feature/builder/FeatureTypeBuilder.java | 12 ++--
.../apache/sis/feature/builder/package-info.java | 3 +-
.../feature/builder/AttributeTypeBuilderTest.java | 29 +++++----
.../src/main/java/org/apache/sis/util/Numbers.java | 12 ++--
.../test/java/org/apache/sis/util/NumbersTest.java | 68 ++++++++++++++--------
5 files changed, 76 insertions(+), 48 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
index ebdd3d3..fc4cefa 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
@@ -25,7 +25,6 @@ import java.util.Map;
import java.util.Locale;
import java.util.Set;
import java.util.Objects;
-import org.apache.sis.util.Numbers;
import org.opengis.util.NameSpace;
import org.opengis.util.GenericName;
import org.opengis.util.NameFactory;
@@ -42,6 +41,7 @@ import org.apache.sis.internal.feature.Resources;
import org.apache.sis.util.CorruptedObjectException;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.Numbers;
// Branch-dependent imports
import org.opengis.feature.AttributeType;
@@ -102,7 +102,8 @@ import org.opengis.feature.Operation;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @author Alexis Manin (Geomatys)
+ * @version 1.1
*
* @see org.apache.sis.parameter.ParameterBuilder
*
@@ -677,16 +678,13 @@ public class FeatureTypeBuilder extends TypeBuilder {
*
* @see #properties()
*/
- public <V> AttributeTypeBuilder<V> addAttribute(Class<V> valueClass)
{
+ public <V> AttributeTypeBuilder<V> addAttribute(final Class<V> valueClass)
{
ensureNonNull("valueClass", valueClass);
if (Feature.class.isAssignableFrom(valueClass)) {
// We disallow Feature.class because that type shall be handled as association
instead than attribute.
throw new IllegalArgumentException(errors().getString(Errors.Keys.IllegalArgumentValue_2,
"valueClass", valueClass));
}
-
- valueClass = (Class<V>) Numbers.primitiveToWrapper(valueClass);
-
- final AttributeTypeBuilder<V> property = new AttributeTypeBuilder<>(this,
valueClass);
+ final AttributeTypeBuilder<V> property = new AttributeTypeBuilder<>(this,
Numbers.primitiveToWrapper(valueClass));
properties.add(property);
clearCache();
return property;
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/package-info.java
b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/package-info.java
index 6f5c1f5..d3e46b7 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/package-info.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/package-info.java
@@ -54,7 +54,8 @@
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @author Alexis Manin (Geomatys)
+ * @version 1.1
*
* @see org.apache.sis.feature.DefaultFeatureType
*
diff --git a/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
b/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
index 1ae4a64..bb2b599 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
@@ -20,12 +20,8 @@ import java.util.Arrays;
import java.util.Set;
import java.util.Collections;
import com.esri.core.geometry.Geometry;
-import org.opengis.feature.Attribute;
-import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
-import org.opengis.feature.Property;
-import org.opengis.feature.PropertyType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.feature.Features;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.test.DependsOnMethod;
@@ -36,7 +32,12 @@ import org.junit.Test;
import static org.apache.sis.test.Assert.*;
// Branch-dependent imports
+import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.Property;
+import org.opengis.feature.PropertyType;
/**
@@ -45,7 +46,8 @@ import org.opengis.feature.AttributeType;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @author Alexis Manin (Geomatys)
+ * @version 1.1
* @since 0.8
* @module
*/
@@ -246,7 +248,11 @@ public final strictfp class AttributeTypeBuilderTest extends TestCase
{
assertFalse("remove(IDENTIFIER_COMPONENT)", roles.remove(AttributeRole.IDENTIFIER_COMPONENT));
}
+ /**
+ * Verifies that {@link FeatureTypeBuilder#addAttribute(Class)} converts primitive types
to their wrapper.
+ */
@Test
+ @SuppressWarnings("UnnecessaryBoxing")
public void testBoxing() {
final FeatureTypeBuilder ftb = new FeatureTypeBuilder().setName("boxing");
final AttributeTypeBuilder<Integer> boxBuilder = ftb.addAttribute(int.class).setName("boxed");
@@ -254,16 +260,17 @@ public final strictfp class AttributeTypeBuilderTest extends TestCase
{
final FeatureType ft = ftb.build();
final PropertyType boxedProperty = ft.getProperty("boxed");
- assertTrue(boxedProperty instanceof AttributeType);
- assertEquals("Attribute value type should have been boxed", Integer.class, ((AttributeType)boxedProperty).getValueClass());
+ assertInstanceOf("Unexpected property type.", AttributeType.class, boxedProperty);
+ assertEquals("Attribute value type should have been boxed", Integer.class, ((AttributeType<?>)
boxedProperty).getValueClass());
final Feature feature = ft.newInstance();
final Property p = feature.getProperty("boxed");
- assertTrue(p instanceof Attribute);
+ assertInstanceOf("Unexpected property type.", Attribute.class, p);
assertEquals("Attribute value type should have been boxed", Integer.class, ((Attribute<?>)
p).getType().getValueClass());
+
int value = 3;
- ((Attribute<Integer>) p).setValue(value);
- assertEquals(3, p.getValue());
+ Features.cast((Attribute<?>) p, Integer.class).setValue(value);
+ assertEquals(value, p.getValue());
feature.setPropertyValue("boxed", Integer.valueOf(4));
assertEquals(4, feature.getPropertyValue("boxed"));
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/Numbers.java b/core/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
index c922291..bab3a28 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
@@ -241,28 +241,32 @@ public final class Numbers extends Static {
* Changes a primitive class to its wrapper (for example {@code int} to {@link Integer}).
* If the specified class is not a primitive type, then it is returned unchanged.
*
+ * @param <N> the primitive and wrapper type (both have the same parametric
declaration).
* @param type the primitive type (can be {@code null}).
* @return the type as a wrapper.
*
* @see #wrapperToPrimitive(Class)
*/
- public static Class<?> primitiveToWrapper(final Class<?> type) {
+ @SuppressWarnings("unchecked")
+ public static <N> Class<N> primitiveToWrapper(final Class<N> type)
{
final Numbers mapping = MAPPING.get(type);
- return (mapping != null) ? mapping.wrapper : type;
+ return (mapping != null) ? (Class<N>) mapping.wrapper : type;
}
/**
* Changes a wrapper class to its primitive (for example {@link Integer} to {@code int}).
* If the specified class is not a wrapper type, then it is returned unchanged.
*
+ * @param <N> the primitive and wrapper type (both have the same parametric
declaration).
* @param type the wrapper type (can be {@code null}).
* @return the type as a primitive.
*
* @see #primitiveToWrapper(Class)
*/
- public static Class<?> wrapperToPrimitive(final Class<?> type) {
+ @SuppressWarnings("unchecked")
+ public static <N> Class<N> wrapperToPrimitive(final Class<N> type)
{
final Numbers mapping = MAPPING.get(type);
- return (mapping != null) ? mapping.primitive : type;
+ return (mapping != null) ? (Class<N>) mapping.primitive : type;
}
/**
diff --git a/core/sis-utility/src/test/java/org/apache/sis/util/NumbersTest.java b/core/sis-utility/src/test/java/org/apache/sis/util/NumbersTest.java
index fcc73e9..6bba3aa 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/util/NumbersTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/util/NumbersTest.java
@@ -30,7 +30,7 @@ import static org.apache.sis.util.Numbers.*;
* Tests the {@link Numbers} static methods.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
* @since 0.3
* @module
*/
@@ -101,18 +101,27 @@ public final strictfp class NumbersTest extends TestCase {
*/
@Test
public void testPrimitiveToWrapper() {
- assertEquals(Byte .class, primitiveToWrapper(Byte .TYPE));
- assertEquals(Short .class, primitiveToWrapper(Short .TYPE));
- assertEquals(Integer.class, primitiveToWrapper(Integer.TYPE));
- assertEquals(Long .class, primitiveToWrapper(Long .TYPE));
- assertEquals(Float .class, primitiveToWrapper(Float .TYPE));
- assertEquals(Double .class, primitiveToWrapper(Double .TYPE));
- assertEquals(Byte .class, primitiveToWrapper(Byte .class));
- assertEquals(Short .class, primitiveToWrapper(Short .class));
- assertEquals(Integer.class, primitiveToWrapper(Integer.class));
- assertEquals(Long .class, primitiveToWrapper(Long .class));
- assertEquals(Float .class, primitiveToWrapper(Float .class));
- assertEquals(Double .class, primitiveToWrapper(Double .class));
+ verifyPrimitiveToWrapper(Byte .class, Byte .TYPE);
+ verifyPrimitiveToWrapper(Short .class, Short .TYPE);
+ verifyPrimitiveToWrapper(Integer .class, Integer .TYPE);
+ verifyPrimitiveToWrapper(Long .class, Long .TYPE);
+ verifyPrimitiveToWrapper(Float .class, Float .TYPE);
+ verifyPrimitiveToWrapper(Double .class, Double .TYPE);
+ verifyPrimitiveToWrapper(Character.class, Character.TYPE);
+ verifyPrimitiveToWrapper(Boolean .class, Boolean .TYPE);
+ verifyPrimitiveToWrapper(Void .class, Void .TYPE);
+ assertSame(String.class, primitiveToWrapper(String.class));
+ }
+
+ /**
+ * Asserts that calls to {@link Numbers#primitiveToWrapper(Class)} produces the expected
wrapper.
+ * The {@code <N>} parameter type is for making sure that e.g. {@link Integer#TYPE}
has the same
+ * type declaration than {@code Integer.class} despite being different {@link Class}
instances.
+ */
+ private static <N> void verifyPrimitiveToWrapper(final Class<N> wrapper,
final Class<N> primitive) {
+ assertNotSame(wrapper, primitive);
+ assertSame (wrapper, primitiveToWrapper(primitive));
+ assertSame (wrapper, primitiveToWrapper(wrapper));
}
/**
@@ -120,18 +129,27 @@ public final strictfp class NumbersTest extends TestCase {
*/
@Test
public void testWrapperToPrimitive() {
- assertEquals(Byte .TYPE, wrapperToPrimitive(Byte .TYPE));
- assertEquals(Short .TYPE, wrapperToPrimitive(Short .TYPE));
- assertEquals(Integer.TYPE, wrapperToPrimitive(Integer.TYPE));
- assertEquals(Long .TYPE, wrapperToPrimitive(Long .TYPE));
- assertEquals(Float .TYPE, wrapperToPrimitive(Float .TYPE));
- assertEquals(Double .TYPE, wrapperToPrimitive(Double .TYPE));
- assertEquals(Byte .TYPE, wrapperToPrimitive(Byte .class));
- assertEquals(Short .TYPE, wrapperToPrimitive(Short .class));
- assertEquals(Integer.TYPE, wrapperToPrimitive(Integer.class));
- assertEquals(Long .TYPE, wrapperToPrimitive(Long .class));
- assertEquals(Float .TYPE, wrapperToPrimitive(Float .class));
- assertEquals(Double .TYPE, wrapperToPrimitive(Double .class));
+ verifyWrapperToPrimitive(Byte .TYPE, Byte .class);
+ verifyWrapperToPrimitive(Short .TYPE, Short .class);
+ verifyWrapperToPrimitive(Integer .TYPE, Integer .class);
+ verifyWrapperToPrimitive(Long .TYPE, Long .class);
+ verifyWrapperToPrimitive(Float .TYPE, Float .class);
+ verifyWrapperToPrimitive(Double .TYPE, Double .class);
+ verifyWrapperToPrimitive(Character.TYPE, Character.class);
+ verifyWrapperToPrimitive(Boolean .TYPE, Boolean .class);
+ verifyWrapperToPrimitive(Void .TYPE, Void .class);
+ assertSame(String.class, wrapperToPrimitive(String.class));
+ }
+
+ /**
+ * Asserts that calls to {@link Numbers#wrapperToPrimitive(Class)} produces the expected
wrapper.
+ * The {@code <N>} parameter type is for making sure that e.g. {@link Integer#TYPE}
has the same
+ * type declaration than {@code Integer.class} despite being different {@link Class}
instances.
+ */
+ private static <N> void verifyWrapperToPrimitive(final Class<N> primitive,
final Class<N> wrapper) {
+ assertNotSame(primitive, wrapper);
+ assertSame (primitive, wrapperToPrimitive(wrapper));
+ assertSame (primitive, wrapperToPrimitive(primitive));
}
/**
|