Skip to content

Commit d2e2034

Browse files
committed
Merge branch 'generic-utils'
This branch reorganizes the lower-level generics-related helper methods of ClassUtils and ConversionUtils into a dedicated utility class: GenericUtils. The old method signatures have been deprecated. The original idea was to use some of these methods to assist with better ObjectIndex lazy object resolution, but it turns out that even with clever use of generics reflection, it is not tenable to reliably detect the type from the LazyObjects instance alone. So the new features of GenericUtils, while very nifty and probably useful in the future, are not in immediate use anywhere within SciJava Common.
2 parents b31f17a + 129bc52 commit d2e2034

File tree

6 files changed

+479
-310
lines changed

6 files changed

+479
-310
lines changed

src/main/java/org/scijava/util/ClassUtils.java

Lines changed: 66 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131

3232
package org.scijava.util;
3333

34-
import com.googlecode.gentyref.GenericTypeReflector;
35-
3634
import java.io.File;
3735
import java.lang.annotation.Annotation;
3836
import java.lang.reflect.Array;
@@ -54,72 +52,6 @@ private ClassUtils() {
5452
// prevent instantiation of utility class
5553
}
5654

57-
// -- Type conversion and casting --
58-
59-
/**
60-
* @deprecated use {@link ConversionUtils#convert(Object, Class)}
61-
*/
62-
@Deprecated
63-
public static <T> T convert(final Object value, final Class<T> type) {
64-
return ConversionUtils.convert(value, type);
65-
}
66-
67-
/**
68-
* @deprecated use {@link ConversionUtils#canConvert(Class, Class)}
69-
*/
70-
@Deprecated
71-
public static boolean canConvert(final Class<?> c, final Class<?> type) {
72-
return ConversionUtils.canConvert(c, type);
73-
}
74-
75-
/**
76-
* @deprecated use {@link ConversionUtils#canConvert(Object, Class)}
77-
*/
78-
@Deprecated
79-
public static boolean canConvert(final Object value, final Class<?> type) {
80-
return ConversionUtils.canConvert(value, type);
81-
}
82-
83-
/**
84-
* @deprecated use {@link ConversionUtils#cast(Object, Class)}
85-
*/
86-
@Deprecated
87-
public static <T> T cast(final Object obj, final Class<T> type) {
88-
return ConversionUtils.cast(obj, type);
89-
}
90-
91-
/**
92-
* @deprecated use {@link ConversionUtils#canCast(Class, Class)}
93-
*/
94-
@Deprecated
95-
public static boolean canCast(final Class<?> c, final Class<?> type) {
96-
return ConversionUtils.canCast(c, type);
97-
}
98-
99-
/**
100-
* @deprecated use {@link ConversionUtils#canCast(Object, Class)}
101-
*/
102-
@Deprecated
103-
public static boolean canCast(final Object obj, final Class<?> type) {
104-
return ConversionUtils.canCast(obj, type);
105-
}
106-
107-
/**
108-
* @deprecated use {@link ConversionUtils#getNonprimitiveType(Class)}
109-
*/
110-
@Deprecated
111-
public static <T> Class<T> getNonprimitiveType(final Class<T> type) {
112-
return ConversionUtils.getNonprimitiveType(type);
113-
}
114-
115-
/**
116-
* @deprecated use {@link ConversionUtils#getNullValue(Class)}
117-
*/
118-
@Deprecated
119-
public static <T> T getNullValue(final Class<T> type) {
120-
return ConversionUtils.getNullValue(type);
121-
}
122-
12355
// -- Class loading, querying and reflection --
12456

12557
/**
@@ -407,96 +339,6 @@ public static Field getField(final Class<?> c, final String fieldName) {
407339
}
408340
}
409341

410-
/**
411-
* Returns the "safe" type(s) of the given field, as viewed from the specified
412-
* type. This may be narrower than what {@link Field#getType()} returns, if
413-
* the field is declared in a superclass, or {@code type} has a type parameter
414-
* that is used in the type of the field.
415-
* <p>
416-
* For example, suppose we have the following three classes:
417-
* </p>
418-
*
419-
* <pre>
420-
* public class Thing&lt;T&gt; {
421-
* public T thing;
422-
* }
423-
*
424-
* public class NumberThing&lt;N extends Number&gt; extends Thing&lt;N&gt; { }
425-
*
426-
* public class IntegerThing extends NumberThing&lt;Integer&gt; { }
427-
* </pre>
428-
*
429-
* Then this method operates as follows:
430-
*
431-
* <pre>
432-
* field = ClassUtils.getField(Thing.class, "thing");
433-
*
434-
* field.getType(); // Object
435-
*
436-
* ClassUtils.getTypes(field, Thing.class).get(0); // Object
437-
* ClassUtils.getTypes(field, NumberThing.class).get(0); // Number
438-
* ClassUtils.getTypes(field, IntegerThing.class).get(0); // Integer
439-
* </pre>
440-
*
441-
* <p>
442-
* In cases of complex generics which take the intersection of
443-
* multiple types using the {@code &} operator, there may be multiple types
444-
* returned by this method. For example:
445-
* </p>
446-
*
447-
* <pre>
448-
* public class ComplexThing&lt;T extends Serializable &amp; Cloneable&gt; extends Thing&lt;T&gt; { }
449-
*
450-
* ClassUtils.getTypes(field, ComplexThing.class); // Serializable, Cloneable
451-
* </pre>
452-
*
453-
* @see #getGenericType(Field, Class)
454-
*/
455-
public static List<Class<?>> getTypes(final Field field, final Class<?> type)
456-
{
457-
final Type genericType = getGenericType(field, type);
458-
return GenericTypeReflector.getUpperBoundClassAndInterfaces(genericType);
459-
}
460-
461-
/**
462-
* Returns the "safe" generic type of the given field, as viewed from the
463-
* given type. This may be narrower than what {@link Field#getGenericType()}
464-
* returns, if the field is declared in a superclass, or {@code type} has a
465-
* type parameter that is used in the type of the field.
466-
* <p>
467-
* For example, suppose we have the following three classes:
468-
* </p>
469-
*
470-
* <pre>
471-
* public class Thing&lt;T&gt; {
472-
* public T thing;
473-
* }
474-
*
475-
* public class NumberThing&lt;N extends Number&gt; extends Thing&lt;N&gt; { }
476-
*
477-
* public class IntegerThing extends NumberThing&lt;Integer&gt; { }
478-
* </pre>
479-
*
480-
* Then this method operates as follows:
481-
*
482-
* <pre>
483-
* field = ClassUtils.getField(Thing.class, "thing");
484-
*
485-
* field.getType(); // Object
486-
* field.getGenericType(); // T
487-
*
488-
* ClassUtils.getGenericType(field, Thing.class); // T
489-
* ClassUtils.getGenericType(field, NumberThing.class); // N extends Number
490-
* ClassUtils.getGenericType(field, IntegerThing.class); // Integer
491-
* </pre>
492-
*
493-
* @see #getTypes(Field, Class)
494-
*/
495-
public static Type getGenericType(final Field field, final Class<?> type) {
496-
final Type wildType = GenericTypeReflector.addWildcardParameters(type);
497-
return GenericTypeReflector.getExactFieldType(field, wildType);
498-
}
499-
500342
/**
501343
* Gets the given field's value of the specified object instance, or null if
502344
* the value cannot be obtained.
@@ -521,8 +363,9 @@ public static void setValue(final Field field, final Object instance,
521363
{
522364
try {
523365
field.setAccessible(true);
524-
field.set(instance, ConversionUtils
525-
.convert(value, field.getGenericType()));
366+
final Type fieldType =
367+
GenericUtils.getFieldType(field, instance.getClass());
368+
field.set(instance, ConversionUtils.convert(value, fieldType));
526369
}
527370
catch (final IllegalAccessException e) {
528371
throw new IllegalArgumentException("No access to field: " +
@@ -599,4 +442,67 @@ public static int compare(final Class<?> c1, final Class<?> c2) {
599442
return MiscUtils.compare(name1, name2);
600443
}
601444

445+
// -- Deprecated methods --
446+
447+
/** @deprecated use {@link ConversionUtils#convert(Object, Class)} */
448+
@Deprecated
449+
public static <T> T convert(final Object value, final Class<T> type) {
450+
return ConversionUtils.convert(value, type);
451+
}
452+
453+
/** @deprecated use {@link ConversionUtils#canConvert(Class, Class)} */
454+
@Deprecated
455+
public static boolean canConvert(final Class<?> c, final Class<?> type) {
456+
return ConversionUtils.canConvert(c, type);
457+
}
458+
459+
/** @deprecated use {@link ConversionUtils#canConvert(Object, Class)} */
460+
@Deprecated
461+
public static boolean canConvert(final Object value, final Class<?> type) {
462+
return ConversionUtils.canConvert(value, type);
463+
}
464+
465+
/** @deprecated use {@link ConversionUtils#cast(Object, Class)} */
466+
@Deprecated
467+
public static <T> T cast(final Object obj, final Class<T> type) {
468+
return ConversionUtils.cast(obj, type);
469+
}
470+
471+
/** @deprecated use {@link ConversionUtils#canCast(Class, Class)} */
472+
@Deprecated
473+
public static boolean canCast(final Class<?> c, final Class<?> type) {
474+
return ConversionUtils.canCast(c, type);
475+
}
476+
477+
/** @deprecated use {@link ConversionUtils#canCast(Object, Class)} */
478+
@Deprecated
479+
public static boolean canCast(final Object obj, final Class<?> type) {
480+
return ConversionUtils.canCast(obj, type);
481+
}
482+
483+
/** @deprecated use {@link ConversionUtils#getNonprimitiveType(Class)} */
484+
@Deprecated
485+
public static <T> Class<T> getNonprimitiveType(final Class<T> type) {
486+
return ConversionUtils.getNonprimitiveType(type);
487+
}
488+
489+
/** @deprecated use {@link ConversionUtils#getNullValue(Class)} */
490+
@Deprecated
491+
public static <T> T getNullValue(final Class<T> type) {
492+
return ConversionUtils.getNullValue(type);
493+
}
494+
495+
/** @deprecated use {@link GenericUtils#getFieldClasses(Field, Class)} */
496+
@Deprecated
497+
public static List<Class<?>> getTypes(final Field field, final Class<?> type)
498+
{
499+
return GenericUtils.getFieldClasses(field, type);
500+
}
501+
502+
/** @deprecated use {@link GenericUtils#getFieldType(Field, Class)} */
503+
@Deprecated
504+
public static Type getGenericType(final Field field, final Class<?> type) {
505+
return GenericUtils.getFieldType(field, type);
506+
}
507+
602508
}

src/main/java/org/scijava/util/ConversionUtils.java

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@
3333

3434
import java.lang.reflect.Array;
3535
import java.lang.reflect.Constructor;
36-
import java.lang.reflect.GenericArrayType;
3736
import java.lang.reflect.Modifier;
3837
import java.lang.reflect.ParameterizedType;
3938
import java.lang.reflect.Type;
40-
import java.lang.reflect.TypeVariable;
4139
import java.util.ArrayList;
4240
import java.util.Collection;
4341
import java.util.HashSet;
@@ -438,44 +436,6 @@ public static <T> T getNullValue(final Class<T> type) {
438436
return result;
439437
}
440438

441-
/**
442-
* Gets the raw class corresponding to the given type.
443-
* <p>
444-
* If the type is a {@link Class} it is simply casted. In the case of a
445-
* {@link ParameterizedType}, then {@link ParameterizedType#getRawType()} is
446-
* returned. Otherwise, returns null.
447-
* </p>
448-
*/
449-
public static Class<?> getClass(final Type type) {
450-
if (type instanceof Class) return (Class<?>) type;
451-
452-
if (type instanceof ParameterizedType) {
453-
return getClass(((ParameterizedType) type).getRawType());
454-
}
455-
456-
if (type instanceof TypeVariable<?>) {
457-
final Type[] types = ((TypeVariable<?>) type).getBounds();
458-
if (types.length == 1) return getClass(types[0]);
459-
}
460-
461-
return null;
462-
}
463-
464-
/**
465-
* Gets the component type of the given array type, or null if not an array.
466-
* Supports both regular array types (i.e., {@link Class#getComponentType()}
467-
* if {@code type} is a {@link Class}) and generic array types (i.e.,
468-
* {@link GenericArrayType#getGenericComponentType()} if {@code type} is a
469-
* {@link GenericArrayType}).
470-
*/
471-
public static Class<?> getComponentClass(final Type type) {
472-
if (type instanceof Class) return ((Class<?>) type).getComponentType();
473-
if (type instanceof GenericArrayType) {
474-
return getClass(((GenericArrayType) type).getGenericComponentType());
475-
}
476-
return null;
477-
}
478-
479439
// -- Helper methods --
480440

481441
private static Constructor<?> getConstructor(final Class<?> type,
@@ -560,4 +520,18 @@ private static Collection<Object> createCollection(final Class<?> type) {
560520
}
561521
}
562522

523+
// -- Deprecated methods --
524+
525+
/** @deprecated use {@link GenericUtils#getClass(Type)} */
526+
@Deprecated
527+
public static Class<?> getClass(final Type type) {
528+
return GenericUtils.getClass(type);
529+
}
530+
531+
/** @deprecated use {@link GenericUtils#getComponentClass(Type)} */
532+
@Deprecated
533+
public static Class<?> getComponentClass(final Type type) {
534+
return GenericUtils.getComponentClass(type);
535+
}
536+
563537
}

0 commit comments

Comments
 (0)