diff --git a/LICENSE b/LICENSE index f8c91199e6..d0549103c1 100644 --- a/LICENSE +++ b/LICENSE @@ -217,6 +217,9 @@ The text of each license is the standard Apache 2.0 license. * guava (https://github.com/google/guava) Files: java/fury-core/src/main/java/org/apache/fury/util/Preconditions.java + java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java + java/fury-core/src/main/java/org/apache/fury/reflect/Types.java + java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java * spark (https://github.com/apache/spark) Files: diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java index 583ca7ee7a..f09b76352e 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java @@ -49,7 +49,6 @@ import static org.apache.fury.util.Preconditions.checkArgument; import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.TypeToken; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -81,6 +80,7 @@ import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; @@ -112,13 +112,12 @@ public abstract class BaseObjectCodecBuilder extends CodecBuilder { public static final String CLASS_RESOLVER_NAME = "classResolver"; public static final String POJO_CLASS_TYPE_NAME = "classType"; public static final String STRING_SERIALIZER_NAME = "strSerializer"; - private static final TypeToken CLASS_RESOLVER_TYPE_TOKEN = TypeToken.of(ClassResolver.class); - private static final TypeToken STRING_SERIALIZER_TYPE_TOKEN = - TypeToken.of(StringSerializer.class); - private static final TypeToken SERIALIZER_TYPE = TypeToken.of(Serializer.class); - private static final TypeToken COLLECTION_SERIALIZER_TYPE = - TypeToken.of(AbstractCollectionSerializer.class); - private static final TypeToken MAP_SERIALIZER_TYPE = TypeToken.of(AbstractMapSerializer.class); + private static final TypeRef CLASS_RESOLVER_TYPE_TOKEN = TypeRef.of(ClassResolver.class); + private static final TypeRef STRING_SERIALIZER_TYPE_TOKEN = TypeRef.of(StringSerializer.class); + private static final TypeRef SERIALIZER_TYPE = TypeRef.of(Serializer.class); + private static final TypeRef COLLECTION_SERIALIZER_TYPE = + TypeRef.of(AbstractCollectionSerializer.class); + private static final TypeRef MAP_SERIALIZER_TYPE = TypeRef.of(AbstractMapSerializer.class); protected final Reference refResolverRef; protected final Reference classResolverRef = @@ -132,7 +131,7 @@ public abstract class BaseObjectCodecBuilder extends CodecBuilder { private final Map jitCallbackUpdateFields; protected LinkedList walkPath = new LinkedList<>(); - public BaseObjectCodecBuilder(TypeToken beanType, Fury fury, Class parentSerializerClass) { + public BaseObjectCodecBuilder(TypeRef beanType, Fury fury, Class parentSerializerClass) { super(new CodegenContext(), beanType); this.fury = fury; this.classResolver = fury.getClassResolver(); @@ -140,21 +139,21 @@ public BaseObjectCodecBuilder(TypeToken beanType, Fury fury, Class parentS addCommonImports(); ctx.reserveName(REF_RESOLVER_NAME); ctx.reserveName(CLASS_RESOLVER_NAME); - TypeToken refResolverTypeToken = TypeToken.of(fury.getRefResolver().getClass()); - refResolverRef = fieldRef(REF_RESOLVER_NAME, refResolverTypeToken); + TypeRef refResolverTypeRef = TypeRef.of(fury.getRefResolver().getClass()); + refResolverRef = fieldRef(REF_RESOLVER_NAME, refResolverTypeRef); Expression refResolverExpr = - new Invoke(furyRef, "getRefResolver", TypeToken.of(RefResolver.class)); + new Invoke(furyRef, "getRefResolver", TypeRef.of(RefResolver.class)); ctx.addField( - ctx.type(refResolverTypeToken), + ctx.type(refResolverTypeRef), REF_RESOLVER_NAME, - new Cast(refResolverExpr, refResolverTypeToken)); + new Cast(refResolverExpr, refResolverTypeRef)); Expression classResolverExpr = inlineInvoke(furyRef, "getClassResolver", CLASS_RESOLVER_TYPE_TOKEN); ctx.addField(ctx.type(CLASS_RESOLVER_TYPE_TOKEN), CLASS_RESOLVER_NAME, classResolverExpr); ctx.reserveName(STRING_SERIALIZER_NAME); stringSerializerRef = fieldRef(STRING_SERIALIZER_NAME, STRING_SERIALIZER_TYPE_TOKEN); ctx.addField( - ctx.type(TypeToken.of(StringSerializer.class)), + ctx.type(TypeRef.of(StringSerializer.class)), STRING_SERIALIZER_NAME, inlineInvoke(furyRef, "getStringSerializer", CLASS_RESOLVER_TYPE_TOKEN)); jitCallbackUpdateFields = new HashMap<>(); @@ -287,9 +286,8 @@ protected void addCommonImports() { ctx.addImports(AbstractCollectionSerializer.class, AbstractMapSerializer.class); } - protected Expression serializeFor( - Expression inputObject, Expression buffer, TypeToken typeToken) { - return serializeFor(inputObject, buffer, typeToken, false); + protected Expression serializeFor(Expression inputObject, Expression buffer, TypeRef typeRef) { + return serializeFor(inputObject, buffer, typeRef, false); } /** @@ -297,35 +295,32 @@ protected Expression serializeFor( * . */ protected Expression serializeFor( - Expression inputObject, - Expression buffer, - TypeToken typeToken, - boolean generateNewMethod) { - return serializeFor(inputObject, buffer, typeToken, null, generateNewMethod); + Expression inputObject, Expression buffer, TypeRef typeRef, boolean generateNewMethod) { + return serializeFor(inputObject, buffer, typeRef, null, generateNewMethod); } protected Expression serializeFor( Expression inputObject, Expression buffer, - TypeToken typeToken, + TypeRef typeRef, Expression serializer, boolean generateNewMethod) { // access rawType without jit lock to reduce lock competition. - Class rawType = getRawType(typeToken); + Class rawType = getRawType(typeRef); if (visitFury(fury -> fury.getClassResolver().needToWriteRef(rawType))) { return new If( not(writeRefOrNull(buffer, inputObject)), - serializeForNotNull(inputObject, buffer, typeToken, serializer, generateNewMethod)); + serializeForNotNull(inputObject, buffer, typeRef, serializer, generateNewMethod)); } else { // if typeToken is not final, ref tracking of subclass will be ignored too. - if (typeToken.isPrimitive()) { - return serializeForNotNull(inputObject, buffer, typeToken, serializer, generateNewMethod); + if (typeRef.isPrimitive()) { + return serializeForNotNull(inputObject, buffer, typeRef, serializer, generateNewMethod); } Expression action = new ListExpression( new Invoke( buffer, "writeByte", new Literal(Fury.REF_VALUE_FLAG, PRIMITIVE_BYTE_TYPE)), - serializeForNotNull(inputObject, buffer, typeToken, serializer, generateNewMethod)); + serializeForNotNull(inputObject, buffer, typeRef, serializer, generateNewMethod)); return new If( ExpressionUtils.eqNull(inputObject), new Invoke(buffer, "writeByte", new Literal(Fury.NULL_FLAG, PRIMITIVE_BYTE_TYPE)), @@ -338,8 +333,8 @@ protected Expression writeRefOrNull(Expression buffer, Expression object) { } protected Expression serializeForNotNull( - Expression inputObject, Expression buffer, TypeToken typeToken) { - return serializeForNotNull(inputObject, buffer, typeToken, null, false); + Expression inputObject, Expression buffer, TypeRef typeRef) { + return serializeForNotNull(inputObject, buffer, typeRef, null, false); } /** @@ -347,20 +342,17 @@ protected Expression serializeForNotNull( * . */ private Expression serializeForNotNull( - Expression inputObject, - Expression buffer, - TypeToken typeToken, - boolean generateNewMethod) { - return serializeForNotNull(inputObject, buffer, typeToken, null, generateNewMethod); + Expression inputObject, Expression buffer, TypeRef typeRef, boolean generateNewMethod) { + return serializeForNotNull(inputObject, buffer, typeRef, null, generateNewMethod); } private Expression serializeForNotNull( Expression inputObject, Expression buffer, - TypeToken typeToken, + TypeRef typeRef, Expression serializer, boolean generateNewMethod) { - Class clz = getRawType(typeToken); + Class clz = getRawType(typeRef); if (isPrimitive(clz) || isBoxed(clz)) { // for primitive, inline call here to avoid java boxing, rather call corresponding serializer. if (clz == byte.class || clz == Byte.class) { @@ -392,24 +384,24 @@ private Expression serializeForNotNull( // ensure // class consistence, we only need to ensure interface consistence. But in java serialization, // we need to ensure class consistence. - if (useCollectionSerialization(typeToken)) { + if (useCollectionSerialization(typeRef)) { action = - serializeForCollection(buffer, inputObject, typeToken, serializer, generateNewMethod); - } else if (useMapSerialization(typeToken)) { - action = serializeForMap(buffer, inputObject, typeToken, serializer, generateNewMethod); + serializeForCollection(buffer, inputObject, typeRef, serializer, generateNewMethod); + } else if (useMapSerialization(typeRef)) { + action = serializeForMap(buffer, inputObject, typeRef, serializer, generateNewMethod); } else { - action = serializeForNotNullObject(inputObject, buffer, typeToken, serializer); + action = serializeForNotNullObject(inputObject, buffer, typeRef, serializer); } return action; } } - protected boolean useCollectionSerialization(TypeToken typeToken) { - return visitFury(f -> f.getClassResolver().isCollection(TypeUtils.getRawType(typeToken))); + protected boolean useCollectionSerialization(TypeRef typeRef) { + return visitFury(f -> f.getClassResolver().isCollection(TypeUtils.getRawType(typeRef))); } - protected boolean useMapSerialization(TypeToken typeToken) { - return visitFury(f -> f.getClassResolver().isMap(TypeUtils.getRawType(typeToken))); + protected boolean useMapSerialization(TypeRef typeRef) { + return visitFury(f -> f.getClassResolver().isMap(TypeUtils.getRawType(typeRef))); } /** @@ -420,8 +412,8 @@ protected boolean useMapSerialization(TypeToken typeToken) { protected abstract boolean isMonomorphic(Class clz); protected Expression serializeForNotNullObject( - Expression inputObject, Expression buffer, TypeToken typeToken, Expression serializer) { - Class clz = getRawType(typeToken); + Expression inputObject, Expression buffer, TypeRef typeRef, Expression serializer) { + Class clz = getRawType(typeRef); if (serializer != null) { return new Invoke(serializer, "write", buffer, inputObject); } @@ -429,14 +421,14 @@ protected Expression serializeForNotNullObject( serializer = getOrCreateSerializer(clz); return new Invoke(serializer, "write", buffer, inputObject); } else { - return writeForNotNullNonFinalObject(inputObject, buffer, typeToken); + return writeForNotNullNonFinalObject(inputObject, buffer, typeRef); } } // Note that `CompatibleCodecBuilder` may mark some final objects as non-final. protected Expression writeForNotNullNonFinalObject( - Expression inputObject, Expression buffer, TypeToken typeToken) { - Class clz = getRawType(typeToken); + Expression inputObject, Expression buffer, TypeRef typeRef) { + Class clz = getRawType(typeRef); Expression clsExpr = new Invoke(inputObject, "getClass", "cls", CLASS_TYPE); ListExpression writeClassAndObject = new ListExpression(); Tuple2 classInfoRef = addClassInfoField(clz); @@ -447,7 +439,7 @@ protected Expression writeForNotNullNonFinalObject( neq(new Invoke(classInfo, "getCls", CLASS_TYPE), clsExpr), new Assign( classInfo, - inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeToken, clsExpr)))); + inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeRef, clsExpr)))); } writeClassAndObject.add( fury.getClassResolver().writeClassExpr(classResolverRef, buffer, classInfo)); @@ -506,7 +498,7 @@ protected Expression getOrCreateSerializer(Class cls) { serializerClass = Serializer.class; } } - TypeToken serializerTypeToken = TypeToken.of(serializerClass); + TypeRef serializerTypeRef = TypeRef.of(serializerClass); Expression fieldTypeExpr = getClassExpr(cls); // Don't invoke `Serializer.newSerializer` here, since it(ex. ObjectSerializer) may set itself // as global serializer, which overwrite serializer updates in jit callback. @@ -523,11 +515,8 @@ protected Expression getOrCreateSerializer(Class cls) { serializerRef = new Reference(name, SERIALIZER_TYPE, false); } else { ctx.addField( - true, - ctx.type(serializerClass), - name, - new Cast(newSerializerExpr, serializerTypeToken)); - serializerRef = fieldRef(name, serializerTypeToken); + true, ctx.type(serializerClass), name, new Cast(newSerializerExpr, serializerTypeRef)); + serializerRef = fieldRef(name, serializerTypeRef); } serializerMap.put(cls, serializerRef); } @@ -567,17 +556,17 @@ protected Tuple2 addClassInfoField(Class cls) { } if (!needUpdate) { Expression clsExpr = getClassExpr(cls); - classInfoExpr = inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeToken, clsExpr); + classInfoExpr = inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeRef, clsExpr); // Use `ctx.freshName(cls)` to avoid wrong name for arr type. String name = ctx.newName(ctx.newName(cls) + "ClassInfo"); ctx.addField(true, ctx.type(ClassInfo.class), name, classInfoExpr); - classInfoRef = Tuple2.of(fieldRef(name, classInfoTypeToken), false); + classInfoRef = Tuple2.of(fieldRef(name, classInfoTypeRef), false); } else { - classInfoExpr = inlineInvoke(classResolverRef, "nilClassInfo", classInfoTypeToken); + classInfoExpr = inlineInvoke(classResolverRef, "nilClassInfo", classInfoTypeRef); String name = ctx.newName(cls, "ClassInfo"); ctx.addField(false, ctx.type(ClassInfo.class), name, classInfoExpr); // Can't use fieldRef, since the field is not final. - classInfoRef = Tuple2.of(new Reference(name, classInfoTypeToken), true); + classInfoRef = Tuple2.of(new Reference(name, classInfoTypeRef), true); } sharedFieldMap.put(key, classInfoRef); return classInfoRef; @@ -596,11 +585,11 @@ protected Reference addClassInfoHolderField(Class cls) { return reference; } Expression classInfoHolderExpr = - inlineInvoke(classResolverRef, "nilClassInfoHolder", classInfoHolderTypeToken); + inlineInvoke(classResolverRef, "nilClassInfoHolder", classInfoHolderTypeRef); String name = ctx.newName(cls, "ClassInfoHolder"); ctx.addField(true, ctx.type(ClassInfoHolder.class), name, classInfoHolderExpr); // The class info field read only once, no need to shallow. - reference = new Reference(name, classInfoHolderTypeToken); + reference = new Reference(name, classInfoHolderTypeRef); sharedFieldMap.put(key, reference); return reference; } @@ -614,23 +603,23 @@ protected Expression readClassInfo(Class cls, Expression buffer, boolean inli Reference classInfoRef = addClassInfoField(cls).f0; if (inlineReadClassInfo) { return inlineInvoke( - classResolverRef, "readClassInfo", classInfoTypeToken, buffer, classInfoRef); + classResolverRef, "readClassInfo", classInfoTypeRef, buffer, classInfoRef); } else { return new Invoke( - classResolverRef, "readClassInfo", classInfoTypeToken, buffer, classInfoRef); + classResolverRef, "readClassInfo", classInfoTypeRef, buffer, classInfoRef); } } Reference classInfoHolderRef = addClassInfoHolderField(cls); if (inlineReadClassInfo) { return inlineInvoke( - classResolverRef, "readClassInfo", classInfoTypeToken, buffer, classInfoHolderRef); + classResolverRef, "readClassInfo", classInfoTypeRef, buffer, classInfoHolderRef); } else { return new Invoke( - classResolverRef, "readClassInfo", classInfoTypeToken, buffer, classInfoHolderRef); + classResolverRef, "readClassInfo", classInfoTypeRef, buffer, classInfoHolderRef); } } - protected TypeToken getSerializerType(TypeToken objType) { + protected TypeRef getSerializerType(TypeRef objType) { Class rawType = getRawType(objType); if (classResolver.isCollection(rawType)) { return COLLECTION_SERIALIZER_TYPE; @@ -651,12 +640,12 @@ protected TypeToken getSerializerType(TypeToken objType) { protected Expression serializeForCollection( Expression buffer, Expression collection, - TypeToken typeToken, + TypeRef typeRef, Expression serializer, boolean generateNewMethod) { // get serializer, write class info if necessary. if (serializer == null) { - Class clz = getRawType(typeToken); + Class clz = getRawType(typeRef); if (isMonomorphic(clz)) { serializer = getOrCreateSerializer(clz); } else { @@ -669,11 +658,11 @@ protected Expression serializeForCollection( neq(new Invoke(classInfo, "getCls", CLASS_TYPE), clsExpr), new Assign( classInfo, - inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeToken, clsExpr)))); + inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeRef, clsExpr)))); writeClassAction.add( fury.getClassResolver().writeClassExpr(classResolverRef, buffer, classInfo)); serializer = new Invoke(classInfo, "getSerializer", "serializer", SERIALIZER_TYPE, false); - serializer = new Cast(serializer, TypeToken.of(AbstractCollectionSerializer.class)); + serializer = new Cast(serializer, TypeRef.of(AbstractCollectionSerializer.class)); writeClassAction.add(serializer, new Return(serializer)); // Spit this into a separate method to avoid method too big to inline. serializer = @@ -684,16 +673,16 @@ protected Expression serializeForCollection( "writeCollectionClassInfo", false); } - } else if (!TypeToken.of(AbstractCollectionSerializer.class).isSupertypeOf(serializer.type())) { + } else if (!TypeRef.of(AbstractCollectionSerializer.class).isSupertypeOf(serializer.type())) { serializer = - new Cast(serializer, TypeToken.of(AbstractCollectionSerializer.class), "colSerializer"); + new Cast(serializer, TypeRef.of(AbstractCollectionSerializer.class), "colSerializer"); } // write collection data. ListExpression actions = new ListExpression(); Expression write = new If( inlineInvoke(serializer, "supportCodegenHook", PRIMITIVE_BOOLEAN_TYPE), - writeCollectionData(buffer, collection, serializer, getElementType(typeToken)), + writeCollectionData(buffer, collection, serializer, getElementType(typeRef)), new Invoke(serializer, "write", buffer, collection)); actions.add(write); if (generateNewMethod) { @@ -704,7 +693,7 @@ protected Expression serializeForCollection( } protected Expression writeCollectionData( - Expression buffer, Expression collection, Expression serializer, TypeToken elementType) { + Expression buffer, Expression collection, Expression serializer, TypeRef elementType) { Invoke onCollectionWrite = new Invoke( serializer, @@ -745,7 +734,7 @@ protected Expression writeCollectionData( Expression isDeclType = neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag); Expression elemSerializer; // make it in scope of `if(sameElementClass)` boolean maybeDecl = visitFury(f -> f.getClassResolver().isSerializable(elemClass)); - TypeToken serializerType = getSerializerType(elementType); + TypeRef serializerType = getSerializerType(elementType); if (maybeDecl) { elemSerializer = new If( @@ -865,7 +854,7 @@ private Tuple2 writeElementsHeader( } private Expression writeContainerElements( - TypeToken elementType, + TypeRef elementType, boolean trackingRef, Expression serializer, Expression hasNull, @@ -909,7 +898,7 @@ private Expression writeContainerElements( private Expression writeContainerElement( Expression buffer, Expression elem, - TypeToken elementType, + TypeRef elementType, boolean trackingRef, Expression hasNull, Expression elemSerializer) { @@ -957,11 +946,11 @@ private Expression writeContainerElement( protected Expression serializeForMap( Expression buffer, Expression map, - TypeToken typeToken, + TypeRef typeRef, Expression serializer, boolean generateNewMethod) { if (serializer == null) { - Class clz = getRawType(typeToken); + Class clz = getRawType(typeRef); if (isMonomorphic(clz)) { serializer = getOrCreateSerializer(clz); } else { @@ -974,12 +963,12 @@ protected Expression serializeForMap( neq(new Invoke(classInfo, "getCls", CLASS_TYPE), clsExpr), new Assign( classInfo, - inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeToken, clsExpr)))); + inlineInvoke(classResolverRef, "getClassInfo", classInfoTypeRef, clsExpr)))); // Note: writeClassExpr is thread safe. writeClassAction.add( fury.getClassResolver().writeClassExpr(classResolverRef, buffer, classInfo)); serializer = new Invoke(classInfo, "getSerializer", "serializer", SERIALIZER_TYPE, false); - serializer = new Cast(serializer, TypeToken.of(AbstractMapSerializer.class)); + serializer = new Cast(serializer, TypeRef.of(AbstractMapSerializer.class)); writeClassAction.add(serializer, new Return(serializer)); // Spit this into a separate method to avoid method too big to inline. serializer = @@ -987,12 +976,12 @@ protected Expression serializeForMap( ctx, ImmutableSet.of(buffer, map), writeClassAction, "writeMapClassInfo", false); } } else if (!AbstractMapSerializer.class.isAssignableFrom(serializer.type().getRawType())) { - serializer = new Cast(serializer, TypeToken.of(AbstractMapSerializer.class), "mapSerializer"); + serializer = new Cast(serializer, TypeRef.of(AbstractMapSerializer.class), "mapSerializer"); } Expression write = new If( inlineInvoke(serializer, "supportCodegenHook", PRIMITIVE_BOOLEAN_TYPE), - jitWriteMap(buffer, map, serializer, typeToken), + jitWriteMap(buffer, map, serializer, typeRef), new Invoke(serializer, "write", buffer, map)); if (generateNewMethod) { return invokeGenerated(ctx, ImmutableSet.of(buffer, map), write, "writeMap", false); @@ -1001,10 +990,10 @@ protected Expression serializeForMap( } private Expression jitWriteMap( - Expression buffer, Expression map, Expression serializer, TypeToken typeToken) { - Tuple2, TypeToken> keyValueType = TypeUtils.getMapKeyValueType(typeToken); - TypeToken keyType = keyValueType.f0; - TypeToken valueType = keyValueType.f1; + Expression buffer, Expression map, Expression serializer, TypeRef typeRef) { + Tuple2, TypeRef> keyValueType = TypeUtils.getMapKeyValueType(typeRef); + TypeRef keyType = keyValueType.f0; + TypeRef valueType = keyValueType.f1; Invoke onMapWrite = new Invoke(serializer, "onMapWrite", TypeUtils.mapOf(keyType, valueType), buffer, map); map = onMapWrite; @@ -1015,7 +1004,7 @@ private Expression jitWriteMap( new ForEach( entrySet, (i, entryObj) -> { - Expression entry = new Cast(entryObj, TypeToken.of(Map.Entry.class), "entry"); + Expression entry = new Cast(entryObj, TypeRef.of(Map.Entry.class), "entry"); Expression key = new Invoke(entry, "getKey", "keyObj", OBJECT_TYPE); key = tryCastIfPublic(key, keyType, "key"); Expression value = new Invoke(entry, "getValue", "valueObj", OBJECT_TYPE); @@ -1047,8 +1036,8 @@ protected Expression tryPreserveRefId(Expression buffer) { } protected Expression deserializeFor( - Expression buffer, TypeToken typeToken, Function callback) { - return deserializeFor(buffer, typeToken, callback, null); + Expression buffer, TypeRef typeRef, Function callback) { + return deserializeFor(buffer, typeRef, callback, null); } /** @@ -1059,20 +1048,20 @@ protected Expression deserializeFor( */ protected Expression deserializeFor( Expression buffer, - TypeToken typeToken, + TypeRef typeRef, Function callback, CutPoint cutPoint) { - Class rawType = getRawType(typeToken); + Class rawType = getRawType(typeRef); if (visitFury(f -> f.getClassResolver().needToWriteRef(rawType))) { - return readRef(buffer, callback, () -> deserializeForNotNull(buffer, typeToken, cutPoint)); + return readRef(buffer, callback, () -> deserializeForNotNull(buffer, typeRef, cutPoint)); } else { - if (typeToken.isPrimitive()) { - Expression value = deserializeForNotNull(buffer, typeToken, cutPoint); + if (typeRef.isPrimitive()) { + Expression value = deserializeForNotNull(buffer, typeRef, cutPoint); // Should put value expr ahead to avoid generated code in wrong scope. return new ListExpression(value, callback.apply(value)); } return readNullable( - buffer, typeToken, callback, () -> deserializeForNotNull(buffer, typeToken, cutPoint)); + buffer, typeRef, callback, () -> deserializeForNotNull(buffer, typeRef, cutPoint)); } } @@ -1099,7 +1088,7 @@ private Expression readRef( private Expression readNullable( Expression buffer, - TypeToken typeToken, + TypeRef typeRef, Function callback, Supplier deserializeForNotNull) { Expression notNull = @@ -1108,12 +1097,12 @@ private Expression readNullable( new Literal(Fury.NULL_FLAG, PRIMITIVE_BYTE_TYPE)); Expression value = deserializeForNotNull.get(); // use false to ignore null. - return new If(notNull, callback.apply(value), callback.apply(nullValue(typeToken)), false); + return new If(notNull, callback.apply(value), callback.apply(nullValue(typeRef)), false); } protected Expression deserializeForNotNull( - Expression buffer, TypeToken typeToken, CutPoint cutPoint) { - return deserializeForNotNull(buffer, typeToken, null, cutPoint); + Expression buffer, TypeRef typeRef, CutPoint cutPoint) { + return deserializeForNotNull(buffer, typeRef, null, cutPoint); } /** @@ -1123,8 +1112,8 @@ protected Expression deserializeForNotNull( * @param cutPoint for generate new method to cut off dependencies. */ protected Expression deserializeForNotNull( - Expression buffer, TypeToken typeToken, Expression serializer, CutPoint cutPoint) { - Class cls = getRawType(typeToken); + Expression buffer, TypeRef typeRef, Expression serializer, CutPoint cutPoint) { + Class cls = getRawType(typeRef); if (isPrimitive(cls) || isBoxed(cls)) { // for primitive, inline call here to avoid java boxing, rather call corresponding serializer. if (cls == byte.class || cls == Byte.class) { @@ -1151,19 +1140,19 @@ protected Expression deserializeForNotNull( return fury.getStringSerializer().readStringExpr(stringSerializerRef, buffer); } Expression obj; - if (useCollectionSerialization(typeToken)) { - obj = deserializeForCollection(buffer, typeToken, serializer, cutPoint); - } else if (useMapSerialization(typeToken)) { - obj = deserializeForMap(buffer, typeToken, serializer, cutPoint); + if (useCollectionSerialization(typeRef)) { + obj = deserializeForCollection(buffer, typeRef, serializer, cutPoint); + } else if (useMapSerialization(typeRef)) { + obj = deserializeForMap(buffer, typeRef, serializer, cutPoint); } else { if (isMonomorphic(cls)) { Preconditions.checkState(serializer == null); serializer = getOrCreateSerializer(cls); Class returnType = ReflectionUtils.getReturnType(getRawType(serializer.type()), "read"); - obj = new Invoke(serializer, "read", TypeToken.of(returnType), buffer); + obj = new Invoke(serializer, "read", TypeRef.of(returnType), buffer); } else { - obj = readForNotNullNonFinal(buffer, typeToken, serializer); + obj = readForNotNullNonFinal(buffer, typeRef, serializer); } } return obj; @@ -1171,9 +1160,9 @@ protected Expression deserializeForNotNull( } protected Expression readForNotNullNonFinal( - Expression buffer, TypeToken typeToken, Expression serializer) { + Expression buffer, TypeRef typeRef, Expression serializer) { if (serializer == null) { - Expression classInfo = readClassInfo(getRawType(typeToken), buffer); + Expression classInfo = readClassInfo(getRawType(typeRef), buffer); serializer = inlineInvoke(classInfo, "getSerializer", SERIALIZER_TYPE); } return new Invoke(serializer, "read", OBJECT_TYPE, buffer); @@ -1184,10 +1173,10 @@ protected Expression readForNotNullNonFinal( * with {@link BaseObjectCodecBuilder#serializeForCollection} */ protected Expression deserializeForCollection( - Expression buffer, TypeToken typeToken, Expression serializer, CutPoint cutPoint) { - TypeToken elementType = getElementType(typeToken); + Expression buffer, TypeRef typeRef, Expression serializer, CutPoint cutPoint) { + TypeRef elementType = getElementType(typeRef); if (serializer == null) { - Class cls = getRawType(typeToken); + Class cls = getRawType(typeRef); if (isMonomorphic(cls)) { serializer = getOrCreateSerializer(cls); } else { @@ -1195,9 +1184,7 @@ protected Expression deserializeForCollection( serializer = new Invoke(classInfo, "getSerializer", "serializer", SERIALIZER_TYPE, false); serializer = new Cast( - serializer, - TypeToken.of(AbstractCollectionSerializer.class), - "collectionSerializer"); + serializer, TypeRef.of(AbstractCollectionSerializer.class), "collectionSerializer"); } } else { checkArgument( @@ -1231,7 +1218,7 @@ protected Expression deserializeForCollection( } protected Expression readCollectionCodegen( - Expression buffer, Expression collection, Expression size, TypeToken elementType) { + Expression buffer, Expression collection, Expression size, TypeRef elementType) { ListExpression builder = new ListExpression(); Invoke flags = new Invoke(buffer, "readByte", "flags", PRIMITIVE_INT_TYPE, false); builder.add(flags); @@ -1258,7 +1245,7 @@ protected Expression readCollectionCodegen( Expression isDeclType = neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag); Invoke serializer = inlineInvoke(readClassInfo(elemClass, buffer), "getSerializer", SERIALIZER_TYPE); - TypeToken serializerType = getSerializerType(elementType); + TypeRef serializerType = getSerializerType(elementType); Expression elemSerializer; // make it in scope of `if(sameElementClass)` boolean maybeDecl = visitFury(f -> f.getClassResolver().isSerializable(elemClass)); if (maybeDecl) { @@ -1324,7 +1311,7 @@ protected Expression readCollectionCodegen( } private Expression readContainerElements( - TypeToken elementType, + TypeRef elementType, boolean trackingRef, Expression serializer, Expression hasNull, @@ -1359,7 +1346,7 @@ private Expression readContainerElements( private Expression readContainerElement( Expression buffer, - TypeToken elementType, + TypeRef elementType, boolean trackingRef, Expression hasNull, Expression elemSerializer, @@ -1412,19 +1399,18 @@ private Expression readContainerElement( * {@link BaseObjectCodecBuilder#serializeForMap} */ protected Expression deserializeForMap( - Expression buffer, TypeToken typeToken, Expression serializer, CutPoint cutPoint) { - Tuple2, TypeToken> keyValueType = TypeUtils.getMapKeyValueType(typeToken); - TypeToken keyType = keyValueType.f0; - TypeToken valueType = keyValueType.f1; + Expression buffer, TypeRef typeRef, Expression serializer, CutPoint cutPoint) { + Tuple2, TypeRef> keyValueType = TypeUtils.getMapKeyValueType(typeRef); + TypeRef keyType = keyValueType.f0; + TypeRef valueType = keyValueType.f1; if (serializer == null) { - Class cls = getRawType(typeToken); + Class cls = getRawType(typeRef); if (isMonomorphic(cls)) { serializer = getOrCreateSerializer(cls); } else { Expression classInfo = readClassInfo(cls, buffer); serializer = new Invoke(classInfo, "getSerializer", SERIALIZER_TYPE); - serializer = - new Cast(serializer, TypeToken.of(AbstractMapSerializer.class), "mapSerializer"); + serializer = new Cast(serializer, TypeRef.of(AbstractMapSerializer.class), "mapSerializer"); } } else { checkArgument( diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java index e2bb42bc6e..2fef8e3a45 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java @@ -34,7 +34,6 @@ import static org.apache.fury.type.TypeUtils.PRIMITIVE_VOID_TYPE; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.invoke.MethodHandle; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -56,6 +55,7 @@ import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.type.Descriptor; @@ -84,23 +84,23 @@ public abstract class CodecBuilder { protected static final String ROOT_OBJECT_NAME = "obj"; // avoid user class has field with name fury. protected static final String FURY_NAME = "fury"; - static TypeToken objectArrayTypeToken = TypeToken.of(Object[].class); - static TypeToken bufferTypeToken = TypeToken.of(MemoryBuffer.class); - static TypeToken classInfoTypeToken = TypeToken.of(ClassInfo.class); - static TypeToken classInfoHolderTypeToken = TypeToken.of(ClassInfoHolder.class); + static TypeRef objectArrayTypeRef = TypeRef.of(Object[].class); + static TypeRef bufferTypeRef = TypeRef.of(MemoryBuffer.class); + static TypeRef classInfoTypeRef = TypeRef.of(ClassInfo.class); + static TypeRef classInfoHolderTypeRef = TypeRef.of(ClassInfoHolder.class); protected final CodegenContext ctx; - protected final TypeToken beanType; + protected final TypeRef beanType; protected final Class beanClass; protected final boolean isRecord; private final Set duplicatedFields; - protected Reference furyRef = new Reference(FURY_NAME, TypeToken.of(Fury.class)); + protected Reference furyRef = new Reference(FURY_NAME, TypeRef.of(Fury.class)); public static final Reference recordComponentDefaultValues = new Reference("recordComponentDefaultValues", OBJECT_ARRAY_TYPE); protected final Map fieldMap = new HashMap<>(); protected boolean recordCtrAccessible; - public CodecBuilder(CodegenContext ctx, TypeToken beanType) { + public CodecBuilder(CodegenContext ctx, TypeRef beanType) { this.ctx = ctx; this.beanType = beanType; this.beanClass = getRawType(beanType); @@ -126,16 +126,16 @@ protected boolean sourcePublicAccessible(Class cls) { return ctx.sourcePublicAccessible(cls); } - protected Expression tryInlineCast(Expression expression, TypeToken targetType) { + protected Expression tryInlineCast(Expression expression, TypeRef targetType) { return tryCastIfPublic(expression, targetType, true); } - protected Expression tryCastIfPublic(Expression expression, TypeToken targetType) { + protected Expression tryCastIfPublic(Expression expression, TypeRef targetType) { return tryCastIfPublic(expression, targetType, false); } protected Expression tryCastIfPublic( - Expression expression, TypeToken targetType, boolean inline) { + Expression expression, TypeRef targetType, boolean inline) { Class rawType = getRawType(targetType); if (rawType == FinalObjectTypeStub.class) { // final field doesn't exist in this class, skip cast. @@ -145,14 +145,14 @@ protected Expression tryCastIfPublic( if (sourcePublicAccessible(rawType)) { return new Cast(expression, targetType); } else { - return new Cast(expression, ReflectionUtils.getPublicSuperType(TypeToken.of(rawType))); + return new Cast(expression, ReflectionUtils.getPublicSuperType(TypeRef.of(rawType))); } } return tryCastIfPublic(expression, targetType, "castedValue"); } protected Expression tryCastIfPublic( - Expression expression, TypeToken targetType, String valuePrefix) { + Expression expression, TypeRef targetType, String valuePrefix) { Class rawType = getRawType(targetType); if (sourcePublicAccessible(rawType) && !expression.type().wrap().isSubtypeOf(targetType.wrap())) { @@ -172,10 +172,10 @@ protected Reference getRecordCtrHandle() { new StaticInvoke( RecordUtils.class, "getRecordCtrHandle", - TypeToken.of(MethodHandle.class), + TypeRef.of(MethodHandle.class), beanClassExpr()); ctx.addField(ctx.type(MethodHandle.class), fieldName, getRecordCtrHandle); - fieldRef = new Reference(fieldName, TypeToken.of(MethodHandle.class)); + fieldRef = new Reference(fieldName, TypeRef.of(MethodHandle.class)); fieldMap.put(fieldName, fieldRef); } return fieldRef; @@ -188,7 +188,7 @@ protected Expression buildDefaultComponentsArray() { /** Returns an expression that get field value from bean. */ protected Expression getFieldValue(Expression inputBeanExpr, Descriptor descriptor) { - TypeToken fieldType = descriptor.getTypeToken(); + TypeRef fieldType = descriptor.getTypeRef(); Class rawType = descriptor.getRawType(); String fieldName = descriptor.getName(); if (isRecord) { @@ -234,7 +234,7 @@ protected Expression getFieldValue(Expression inputBeanExpr, Descriptor descript } private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor descriptor) { - TypeToken fieldType = descriptor.getTypeToken(); + TypeRef fieldType = descriptor.getTypeRef(); if (!sourcePublicAccessible(descriptor.getRawType())) { fieldType = OBJECT_TYPE; } @@ -249,7 +249,7 @@ private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor desc Tuple2, String> methodInfo = Functions.getterMethodInfo(descriptor.getRawType()); if (ref == null) { Class funcInterface = methodInfo.f0; - TypeToken getterType = TypeToken.of(funcInterface); + TypeRef getterType = TypeRef.of(funcInterface); Expression getter = new StaticInvoke( Functions.class, @@ -264,7 +264,7 @@ private Expression getRecordFieldValue(Expression inputBeanExpr, Descriptor desc } if (!fieldType.isPrimitive()) { Expression v = inlineInvoke(ref, methodInfo.f1, OBJECT_TYPE, fieldNullable, inputBeanExpr); - return tryCastIfPublic(v, descriptor.getTypeToken(), fieldName); + return tryCastIfPublic(v, descriptor.getTypeRef(), fieldName); } else { return new Invoke(ref, methodInfo.f1, fieldType, fieldNullable, inputBeanExpr); } @@ -277,7 +277,7 @@ private Expression reflectAccessField( Reference fieldRef = getReflectField(cls, descriptor.getField()); // boolean fieldNullable = !descriptor.getTypeToken().isPrimitive(); Invoke getObj = new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable, inputObject); - return new Cast(getObj, descriptor.getTypeToken(), descriptor.getName()); + return new Cast(getObj, descriptor.getTypeRef(), descriptor.getName()); } /** Returns an expression that get field value> from bean using {@link Unsafe}. */ @@ -285,10 +285,10 @@ private Expression unsafeAccessField( Expression inputObject, Class cls, Descriptor descriptor) { String fieldName = descriptor.getName(); Expression fieldOffsetExpr = getFieldOffset(cls, descriptor); - if (descriptor.getTypeToken().isPrimitive()) { + if (descriptor.getTypeRef().isPrimitive()) { // ex: Platform.UNSAFE.getFloat(obj, fieldOffset) Preconditions.checkArgument(!fieldNullable); - TypeToken returnType = descriptor.getTypeToken(); + TypeRef returnType = descriptor.getTypeRef(); String funcName = "get" + StringUtils.capitalize(descriptor.getRawType().toString()); return new StaticInvoke( Platform.class, funcName, returnType, false, inputObject, fieldOffsetExpr); @@ -302,7 +302,7 @@ private Expression unsafeAccessField( fieldNullable, inputObject, fieldOffsetExpr); - return tryCastIfPublic(getObj, descriptor.getTypeToken(), fieldName); + return tryCastIfPublic(getObj, descriptor.getTypeRef(), fieldName); } } @@ -317,7 +317,7 @@ private Expression getFieldOffset(Class cls, Descriptor descriptor) { fieldName + "_offset_", () -> { Expression classExpr = beanClassExpr(field.getDeclaringClass()); - new Invoke(classExpr, "getDeclaredField", TypeToken.of(Field.class)); + new Invoke(classExpr, "getDeclaredField", TypeRef.of(Field.class)); Expression reflectFieldRef = getReflectField(cls, field, false); return new StaticInvoke( Platform.class, "objectFieldOffset", PRIMITIVE_LONG_TYPE, reflectFieldRef) @@ -355,8 +355,8 @@ protected Expression setFieldValue(Expression bean, Descriptor d, Expression val if (!d.isFinalField() && !Modifier.isPrivate(d.getModifiers())) { if (AccessorHelper.defineSetter(d.getField())) { Class accessorClass = AccessorHelper.getAccessorClass(d.getField()); - if (!value.type().equals(d.getTypeToken())) { - value = new Cast(value, d.getTypeToken()); + if (!value.type().equals(d.getTypeRef())) { + value = new Cast(value, d.getTypeRef()); } return new StaticInvoke( accessorClass, d.getName(), PRIMITIVE_VOID_TYPE, false, bean, value); @@ -365,8 +365,8 @@ protected Expression setFieldValue(Expression bean, Descriptor d, Expression val if (d.getWriteMethod() != null && !Modifier.isPrivate(d.getWriteMethod().getModifiers())) { if (AccessorHelper.defineSetter(d.getWriteMethod())) { Class accessorClass = AccessorHelper.getAccessorClass(d.getWriteMethod()); - if (!value.type().equals(d.getTypeToken())) { - value = new Cast(value, d.getTypeToken()); + if (!value.type().equals(d.getTypeRef())) { + value = new Cast(value, d.getTypeRef()); } return new StaticInvoke( accessorClass, d.getWriteMethod().getName(), PRIMITIVE_VOID_TYPE, false, bean, value); @@ -392,10 +392,10 @@ private Expression reflectSetField(Expression bean, Field field, Expression valu * Unsafe}. */ private Expression unsafeSetField(Expression bean, Descriptor descriptor, Expression value) { - TypeToken fieldType = descriptor.getTypeToken(); + TypeRef fieldType = descriptor.getTypeRef(); // Use Field in case the class has duplicate field name as `fieldName`. Expression fieldOffsetExpr = getFieldOffset(beanClass, descriptor); - if (descriptor.getTypeToken().isPrimitive()) { + if (descriptor.getTypeRef().isPrimitive()) { Preconditions.checkArgument(value.type().equals(fieldType)); String funcName = "put" + StringUtils.capitalize(getRawType(fieldType).toString()); return new StaticInvoke(Platform.class, funcName, bean, fieldOffsetExpr, value); @@ -421,19 +421,19 @@ private Reference getReflectField(Class cls, Field field, boolean setAccessib Field.class, fieldRefName, () -> { - TypeToken fieldTypeToken = TypeToken.of(Field.class); + TypeRef fieldTypeRef = TypeRef.of(Field.class); Expression classExpr = beanClassExpr(field.getDeclaringClass()); Expression fieldExpr; if (GraalvmSupport.isGraalBuildtime()) { fieldExpr = inlineInvoke( - classExpr, "getDeclaredField", fieldTypeToken, Literal.ofString(fieldName)); + classExpr, "getDeclaredField", fieldTypeRef, Literal.ofString(fieldName)); } else { fieldExpr = new StaticInvoke( ReflectionUtils.class, "getField", - fieldTypeToken, + fieldTypeRef, classExpr, Literal.ofString(fieldName)); } @@ -450,7 +450,7 @@ private Reference getOrCreateField( Reference fieldRef = fieldMap.get(fieldName); if (fieldRef == null) { ctx.addField(isStatic, true, ctx.type(type), fieldName, value.get()); - fieldRef = new Reference(fieldName, TypeToken.of(type)); + fieldRef = new Reference(fieldName, TypeRef.of(type)); fieldMap.put(fieldName, fieldRef); } return fieldRef; diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/CodecUtils.java b/java/fury-core/src/main/java/org/apache/fury/builder/CodecUtils.java index b40e70297b..ed985b87d3 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/CodecUtils.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/CodecUtils.java @@ -19,12 +19,12 @@ package org.apache.fury.builder; -import com.google.common.reflect.TypeToken; import java.util.Collections; import org.apache.fury.Fury; import org.apache.fury.codegen.CodeGenerator; import org.apache.fury.codegen.CompileUnit; import org.apache.fury.meta.ClassDef; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.FieldResolver; import org.apache.fury.serializer.Serializer; @@ -47,7 +47,7 @@ public static Class> loadOrGenMetaSharedCodecClass( Fury fury, Class cls, ClassDef classDef) { Preconditions.checkNotNull(fury); MetaSharedCodecBuilder codecBuilder = - new MetaSharedCodecBuilder(TypeToken.of(cls), fury, classDef); + new MetaSharedCodecBuilder(TypeRef.of(cls), fury, classDef); return loadOrGenCodecClass(cls, fury, codecBuilder); } @@ -61,7 +61,7 @@ public static Class> loadOrGenCompatibleCodecClass( Class cls, Fury fury, FieldResolver fieldResolver, Class parentSerializerClass) { Preconditions.checkNotNull(fury); BaseObjectCodecBuilder codecBuilder = - new CompatibleCodecBuilder(TypeToken.of(cls), fury, fieldResolver, parentSerializerClass); + new CompatibleCodecBuilder(TypeRef.of(cls), fury, fieldResolver, parentSerializerClass); return loadOrGenCodecClass(cls, fury, codecBuilder); } diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java index b521c32134..71c897d0cd 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/CompatibleCodecBuilder.java @@ -33,7 +33,6 @@ import static org.apache.fury.type.TypeUtils.PRIMITIVE_VOID_TYPE; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -66,6 +65,7 @@ import org.apache.fury.codegen.ExpressionUtils; import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.FieldResolver; @@ -91,10 +91,7 @@ public class CompatibleCodecBuilder extends BaseObjectCodecBuilder { private final Map methodCache; public CompatibleCodecBuilder( - TypeToken beanType, - Fury fury, - FieldResolver fieldResolver, - Class superSerializerClass) { + TypeRef beanType, Fury fury, FieldResolver fieldResolver, Class superSerializerClass) { // if not resolveParent, there won't be necessary to implement // `CompatibleSerializerBase.readAndSetFields`. super(beanType, fury, superSerializerClass); @@ -108,15 +105,15 @@ public CompatibleCodecBuilder( } ctx.reserveName(FIELD_RESOLVER_NAME); endTagLiteral = new Literal(fieldResolver.getEndTag(), PRIMITIVE_LONG_TYPE); - TypeToken fieldResolverTypeToken = TypeToken.of(FieldResolver.class); - fieldResolverRef = fieldRef(FIELD_RESOLVER_NAME, fieldResolverTypeToken); + TypeRef fieldResolverTypeRef = TypeRef.of(FieldResolver.class); + fieldResolverRef = fieldRef(FIELD_RESOLVER_NAME, fieldResolverTypeRef); Expression fieldResolverExpr = inlineInvoke( classResolverRef, "getFieldResolver", - fieldResolverTypeToken, + fieldResolverTypeRef, getClassExpr(getRawType(beanType))); - ctx.addField(ctx.type(fieldResolverTypeToken), FIELD_RESOLVER_NAME, fieldResolverExpr); + ctx.addField(ctx.type(fieldResolverTypeRef), FIELD_RESOLVER_NAME, fieldResolverExpr); if (isRecord) { buildRecordComponentDefaultValues(); } @@ -140,7 +137,7 @@ protected boolean isMonomorphic(Class clz) { } private Descriptor createDescriptor(FieldInfo fieldInfo) { - TypeToken typeToken; + TypeRef typeRef; Field field = fieldInfo.getField(); if (fieldInfo instanceof MapFieldInfo) { MapFieldInfo mapFieldInfo = (MapFieldInfo) fieldInfo; @@ -148,11 +145,11 @@ private Descriptor createDescriptor(FieldInfo fieldInfo) { // consistent with // CompatibleSerializer. // TODO support nested collection/map generics. - typeToken = + typeRef = TypeUtils.mapOf( mapFieldInfo.getType(), mapFieldInfo.getKeyType(), mapFieldInfo.getValueType()); } else { - typeToken = TypeToken.of(field.getGenericType()); + typeRef = TypeRef.of(field.getGenericType()); } Method readerMethod = null; if (isRecord) { @@ -163,7 +160,7 @@ private Descriptor createDescriptor(FieldInfo fieldInfo) { Platform.throwException(e); } } - return new Descriptor(field, typeToken, readerMethod, null); + return new Descriptor(field, typeRef, readerMethod, null); } private Expression invokeGenerated( @@ -179,7 +176,7 @@ private Expression invokeGenerated( @Override public Expression buildEncodeExpression() { Reference inputObject = new Reference(ROOT_OBJECT_NAME, OBJECT_TYPE, false); - Reference buffer = new Reference(BUFFER_NAME, bufferTypeToken, false); + Reference buffer = new Reference(BUFFER_NAME, bufferTypeRef, false); ListExpression expressions = new ListExpression(); Expression bean = tryCastIfPublic(inputObject, beanType, ctx.newName(beanClass)); @@ -282,7 +279,7 @@ public Expression buildEncodeExpression() { if (fieldType == FieldTypes.OBJECT) { writeFieldValue.add( writeForNotNullNonFinalObject( - fieldValue, buffer, descriptor.getTypeToken())); + fieldValue, buffer, descriptor.getTypeRef())); } else { if (fieldType == FieldTypes.COLLECTION_ELEMENT_FINAL) { CollectionFieldInfo collectionFieldInfo = @@ -322,7 +319,7 @@ public Expression buildEncodeExpression() { } writeFieldValue.add( serializeForNotNull( - fieldValue, buffer, descriptor.getTypeToken())); + fieldValue, buffer, descriptor.getTypeRef())); } return new If( ExpressionUtils.not(writeRefOrNull(buffer, fieldValue)), @@ -350,7 +347,7 @@ private Expression writeEmbedTypeFieldValue( walkPath.add(descriptor.getDeclaringClass() + descriptor.getName()); Expression fieldValue = getFieldValue(bean, descriptor); walkPath.removeLast(); - return serializeFor(fieldValue, buffer, descriptor.getTypeToken()); + return serializeFor(fieldValue, buffer, descriptor.getTypeRef()); } @Override @@ -358,7 +355,7 @@ public Expression buildDecodeExpression() { if (isRecord) { return buildRecordDecodeExpression(); } - Reference buffer = new Reference(BUFFER_NAME, bufferTypeToken, false); + Reference buffer = new Reference(BUFFER_NAME, bufferTypeRef, false); ListExpression expressionBuilder = new ListExpression(); Expression bean = newBean(); Expression referenceObject = new Invoke(refResolverRef, "reference", PRIMITIVE_VOID_TYPE, bean); @@ -388,7 +385,7 @@ public Expression buildDecodeExpression() { } public Expression buildRecordDecodeExpression() { - Reference buffer = new Reference(BUFFER_NAME, bufferTypeToken, false); + Reference buffer = new Reference(BUFFER_NAME, bufferTypeRef, false); StaticInvoke components = new StaticInvoke( Platform.class, "copyObjectArray", OBJECT_ARRAY_TYPE, recordComponentDefaultValues); @@ -511,9 +508,8 @@ private Expression readEmbedTypes4( Expression deserializeAction = deserializeFor( buffer, - descriptor.getTypeToken(), - expr -> - setFieldValue(bean, descriptor, tryInlineCast(expr, descriptor.getTypeToken()))); + descriptor.getTypeRef(), + expr -> setFieldValue(bean, descriptor, tryInlineCast(expr, descriptor.getTypeRef()))); return new ListExpression( deserializeAction, new Assign(partFieldInfo, inlineInvoke(buffer, readIntFunc(), PRIMITIVE_LONG_TYPE))); @@ -717,9 +713,8 @@ private Expression readEmbedTypes8Field( Expression deserializeAction = deserializeFor( buffer, - descriptor.getTypeToken(), - expr -> - setFieldValue(bean, descriptor, tryInlineCast(expr, descriptor.getTypeToken()))); + descriptor.getTypeRef(), + expr -> setFieldValue(bean, descriptor, tryInlineCast(expr, descriptor.getTypeRef()))); return new ListExpression( deserializeAction, new Assign(partFieldInfo, inlineInvoke(buffer, readLongFunc(), PRIMITIVE_LONG_TYPE))); @@ -804,7 +799,7 @@ private Expression readObjectField( invokeGenerated( ctx, () -> { - TypeToken typeToken = descriptor.getTypeToken(); + TypeRef typeRef = descriptor.getTypeRef(); Expression refId = tryPreserveRefId(buffer); // indicates that the object is first read. Expression needDeserialize = @@ -821,7 +816,7 @@ private Expression readObjectField( inlineInvoke(buffer, "readByte", PRIMITIVE_BYTE_TYPE), expectType)); if (type == FieldTypes.OBJECT) { - deserializedValue.add(readForNotNullNonFinal(buffer, typeToken, null)); + deserializedValue.add(readForNotNullNonFinal(buffer, typeRef, null)); } else { if (type == FieldTypes.COLLECTION_ELEMENT_FINAL) { deserializedValue.add( @@ -840,12 +835,12 @@ private Expression readObjectField( deserializedValue.add( skipFinalClassInfo(((MapFieldInfo) fieldInfo).getValueType(), buffer)); } - Class clz = getRawType(typeToken); + Class clz = getRawType(typeRef); if (ReflectionUtils.isMonomorphic(clz)) { // deserializeForNotNull won't read field type if it's final deserializedValue.add(skipFinalClassInfo(clz, buffer)); } - deserializedValue.add(deserializeForNotNull(buffer, typeToken, null)); + deserializedValue.add(deserializeForNotNull(buffer, typeRef, null)); } Expression setReadObject = new Invoke(refResolverRef, "setReadObject", refId, deserializedValue); @@ -856,13 +851,13 @@ private Expression readObjectField( refId, deserializedValue, setReadObject, - setFieldValue(bean, descriptor, tryInlineCast(deserializedValue, typeToken))), + setFieldValue(bean, descriptor, tryInlineCast(deserializedValue, typeRef))), setFieldValue( bean, descriptor, tryInlineCast( new Invoke(refResolverRef, "getReadObject", OBJECT_TYPE, false), - typeToken)), + typeRef)), false, PRIMITIVE_VOID_TYPE); }, diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/MetaSharedCodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/MetaSharedCodecBuilder.java index c16df6d02e..8879f567ab 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/MetaSharedCodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/MetaSharedCodecBuilder.java @@ -21,7 +21,6 @@ import static org.apache.fury.builder.Generated.GeneratedMetaSharedSerializer.SERIALIZER_FIELD_NAME; -import com.google.common.reflect.TypeToken; import java.util.Collection; import java.util.SortedMap; import org.apache.fury.Fury; @@ -33,6 +32,7 @@ import org.apache.fury.config.FuryBuilder; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.meta.ClassDef; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.CodegenSerializer; import org.apache.fury.serializer.MetaSharedSerializer; import org.apache.fury.serializer.ObjectSerializer; @@ -65,7 +65,7 @@ public class MetaSharedCodecBuilder extends ObjectCodecBuilder { private final ClassDef classDef; - public MetaSharedCodecBuilder(TypeToken beanType, Fury fury, ClassDef classDef) { + public MetaSharedCodecBuilder(TypeRef beanType, Fury fury, ClassDef classDef) { super(beanType, fury, GeneratedMetaSharedSerializer.class); Preconditions.checkArgument( !fury.getConfig().checkClassVersion(), @@ -160,7 +160,7 @@ protected Expression createRecord(SortedMap recordComponent Object defaultValue = defaultValues[i]; assert components != null; RecordComponent component = components[i]; - recordComponents.put(i, new Literal(defaultValue, TypeToken.of(component.getType()))); + recordComponents.put(i, new Literal(defaultValue, TypeRef.of(component.getType()))); } } Expression[] params = recordComponents.values().toArray(new Expression[0]); diff --git a/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java b/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java index 6edc239f41..8ce55855f9 100644 --- a/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java @@ -34,7 +34,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import com.google.common.reflect.TypeToken; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -57,6 +56,7 @@ import org.apache.fury.codegen.Expression.StaticInvoke; import org.apache.fury.codegen.ExpressionVisitor; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.ObjectSerializer; import org.apache.fury.serializer.PrimitiveSerializers.LongSerializer; import org.apache.fury.type.Descriptor; @@ -86,7 +86,7 @@ public class ObjectCodecBuilder extends BaseObjectCodecBuilder { protected Map recordReversedMapping; public ObjectCodecBuilder(Class beanClass, Fury fury) { - super(TypeToken.of(beanClass), fury, Generated.GeneratedObjectSerializer.class); + super(TypeRef.of(beanClass), fury, Generated.GeneratedObjectSerializer.class); Collection descriptors = classResolver.getAllDescriptorsMap(beanClass, true).values(); classVersionHash = @@ -104,7 +104,7 @@ public ObjectCodecBuilder(Class beanClass, Fury fury) { } } - protected ObjectCodecBuilder(TypeToken beanType, Fury fury, Class superSerializerClass) { + protected ObjectCodecBuilder(TypeRef beanType, Fury fury, Class superSerializerClass) { super(beanType, fury, superSerializerClass); this.classVersionHash = null; if (isRecord) { @@ -138,7 +138,7 @@ protected boolean isMonomorphic(Class clz) { @Override public Expression buildEncodeExpression() { Reference inputObject = new Reference(ROOT_OBJECT_NAME, OBJECT_TYPE, false); - Reference buffer = new Reference(BUFFER_NAME, bufferTypeToken, false); + Reference buffer = new Reference(BUFFER_NAME, bufferTypeRef, false); ListExpression expressions = new ListExpression(); Expression bean = tryCastIfPublic(inputObject, beanType, ctx.newName(beanClass)); @@ -186,7 +186,7 @@ private Expression serializeGroup( // `bean` will be replaced by `Reference` to cut-off expr dependency. Expression fieldValue = getFieldValue(bean, d); walkPath.add(d.getDeclaringClass() + d.getName()); - Expression fieldExpr = serializeFor(fieldValue, buffer, d.getTypeToken()); + Expression fieldExpr = serializeFor(fieldValue, buffer, d.getTypeRef()); walkPath.removeLast(); groupExpressions.add(fieldExpr); } @@ -410,7 +410,7 @@ private Expression getWriterPos(Expression writerPos, long acc) { } public Expression buildDecodeExpression() { - Reference buffer = new Reference(BUFFER_NAME, bufferTypeToken, false); + Reference buffer = new Reference(BUFFER_NAME, bufferTypeRef, false); ListExpression expressions = new ListExpression(); if (fury.checkClassVersion()) { expressions.add(checkClassVersion(buffer)); @@ -481,7 +481,7 @@ private class FieldsCollector implements Expression { private final TreeMap recordValuesMap = new TreeMap<>(); @Override - public TypeToken type() { + public TypeRef type() { return beanType; } @@ -525,12 +525,12 @@ protected Expression deserializeGroup( Expression action = deserializeFor( buffer, - d.getTypeToken(), + d.getTypeRef(), // `bean` will be replaced by `Reference` to cut-off expr // dependency. expr -> setFieldValue( - exprHolder.get("bean"), d, tryInlineCast(expr, d.getTypeToken()))); + exprHolder.get("bean"), d, tryInlineCast(expr, d.getTypeRef()))); walkPath.removeLast(); groupExpressions.add(action); } @@ -548,8 +548,8 @@ protected Expression deserializeGroupForRecord( ListExpression groupExpressions = new ListExpression(); // use Reference to cut-off expr dependency. for (Descriptor d : group) { - Expression v = deserializeFor(buffer, d.getTypeToken(), expr -> expr); - Expression action = setFieldValue(bean, d, tryInlineCast(v, d.getTypeToken())); + Expression v = deserializeFor(buffer, d.getTypeRef(), expr -> expr); + Expression action = setFieldValue(bean, d, tryInlineCast(v, d.getTypeRef())); groupExpressions.add(action); } return groupExpressions; @@ -600,7 +600,7 @@ private List deserializeUnCompressedPrimitives( for (List group : primitiveGroups) { ListExpression groupExpressions = new ListExpression(); for (Descriptor descriptor : group) { - TypeToken type = descriptor.getTypeToken(); + TypeRef type = descriptor.getTypeRef(); Class clz = getRawType(type); Preconditions.checkArgument(isPrimitive(clz)); Expression fieldValue; @@ -666,7 +666,7 @@ private List deserializeCompressedPrimitives( int acc = 0; boolean compressStarted = false; for (Descriptor descriptor : group) { - TypeToken type = descriptor.getTypeToken(); + TypeRef type = descriptor.getTypeRef(); Class clz = getRawType(type); Preconditions.checkArgument(isPrimitive(clz)); Expression fieldValue; diff --git a/java/fury-core/src/main/java/org/apache/fury/codegen/CodegenContext.java b/java/fury-core/src/main/java/org/apache/fury/codegen/CodegenContext.java index 8ec6cacb86..e79ea7edd3 100644 --- a/java/fury-core/src/main/java/org/apache/fury/codegen/CodegenContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/codegen/CodegenContext.java @@ -26,7 +26,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.TypeToken; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -43,6 +42,7 @@ import org.apache.fury.codegen.Expression.Reference; import org.apache.fury.collection.Collections; import org.apache.fury.collection.Tuple2; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.Preconditions; import org.apache.fury.util.ReflectionUtils; import org.apache.fury.util.StringUtils; @@ -328,8 +328,8 @@ public String type(Class clz) { } /** return type name. since janino doesn't generics, we ignore type parameters in typeToken. */ - public String type(TypeToken typeToken) { - return type(getRawType(typeToken)); + public String type(TypeRef typeRef) { + return type(getRawType(typeRef)); } /** diff --git a/java/fury-core/src/main/java/org/apache/fury/codegen/Expression.java b/java/fury-core/src/main/java/org/apache/fury/codegen/Expression.java index 29b56715e1..1179716463 100644 --- a/java/fury-core/src/main/java/org/apache/fury/codegen/Expression.java +++ b/java/fury-core/src/main/java/org/apache/fury/codegen/Expression.java @@ -47,7 +47,6 @@ import static org.apache.fury.type.TypeUtils.maxType; import static org.apache.fury.util.Preconditions.checkArgument; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Array; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -57,6 +56,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.Preconditions; import org.apache.fury.util.ReflectionUtils; @@ -86,7 +86,7 @@ public interface Expression { * Returns the Class of the result of evaluating this expression. It is invalid to query the * type of unresolved expression (i.e., when `resolved` == false). */ - TypeToken type(); + TypeRef type(); /** * If expression is already generated in this context, returned exprCode won't contains code, so @@ -165,7 +165,7 @@ public ListExpression(List expressions) { } @Override - public TypeToken type() { + public TypeRef type() { Preconditions.checkNotNull(last); return last.type(); } @@ -235,14 +235,14 @@ class Literal implements Expression { public static final Literal False = new Literal(false, PRIMITIVE_BOOLEAN_TYPE); private final Object value; - private final TypeToken type; + private final TypeRef type; public Literal(String value) { this.value = value; this.type = STRING_TYPE; } - public Literal(Object value, TypeToken type) { + public Literal(Object value, TypeRef type) { this.value = value; this.type = type; } @@ -272,7 +272,7 @@ public static Literal ofString(String v) { } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -354,20 +354,20 @@ public String toString() { } class Null implements Expression { - private TypeToken type; + private TypeRef type; private final boolean typedNull; - public Null(TypeToken type) { + public Null(TypeRef type) { this(type, false); } - public Null(TypeToken type, boolean typedNull) { + public Null(TypeRef type, boolean typedNull) { this.type = type; this.typedNull = typedNull; } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -388,7 +388,7 @@ public String toString() { /** A Reference is a variable/field that can be accessed in the expression's CodegenContext. */ class Reference implements Expression { private final String name; - private final TypeToken type; + private final TypeRef type; private final boolean nullable; private final boolean fieldRef; @@ -396,27 +396,27 @@ public Reference(String name) { this(name, OBJECT_TYPE); } - public Reference(String name, TypeToken type) { + public Reference(String name, TypeRef type) { this(name, type, false); } - public Reference(String name, TypeToken type, boolean nullable) { + public Reference(String name, TypeRef type, boolean nullable) { this(name, type, nullable, false); } - public Reference(String name, TypeToken type, boolean nullable, boolean fieldRef) { + public Reference(String name, TypeRef type, boolean nullable, boolean fieldRef) { this.name = name; this.type = type; this.nullable = nullable; this.fieldRef = fieldRef; } - public static Reference fieldRef(String name, TypeToken type) { + public static Reference fieldRef(String name, TypeRef type) { return new Reference(name, type, false, true); } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -456,7 +456,7 @@ public String toString() { class Empty implements Expression { @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -474,7 +474,7 @@ public Block(String code) { } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -492,7 +492,7 @@ public ForceEvaluate(Expression expression) { } @Override - public TypeToken type() { + public TypeRef type() { return expression.type(); } @@ -515,17 +515,17 @@ public String toString() { class FieldValue extends Inlineable { private Expression targetObject; private final String fieldName; - private final TypeToken type; + private final TypeRef type; private final boolean fieldNullable; - public FieldValue(Expression targetObject, String fieldName, TypeToken type) { + public FieldValue(Expression targetObject, String fieldName, TypeRef type) { this(targetObject, fieldName, type, !type.isPrimitive(), false); } public FieldValue( Expression targetObject, String fieldName, - TypeToken type, + TypeRef type, boolean fieldNullable, boolean inline) { Preconditions.checkArgument(type != null); @@ -540,7 +540,7 @@ public FieldValue( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -631,7 +631,7 @@ public SetField(Expression targetObject, String fieldName, Expression fieldValue } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -680,7 +680,7 @@ public ReplaceStub(Expression targetObject) { } @Override - public TypeToken type() { + public TypeRef type() { return targetObject != null ? targetObject.type() : PRIMITIVE_VOID_TYPE; } @@ -702,20 +702,20 @@ public void setTargetObject(Expression targetObject) { class Cast extends Inlineable { private Expression targetObject; private final String castedValueNamePrefix; - private final TypeToken type; + private final TypeRef type; private final boolean ignoreUpcast; - public Cast(Expression targetObject, TypeToken type) { + public Cast(Expression targetObject, TypeRef type) { this(targetObject, type, "castedValue", true, true); } - public Cast(Expression targetObject, TypeToken type, String castedValueNamePrefix) { + public Cast(Expression targetObject, TypeRef type, String castedValueNamePrefix) { this(targetObject, type, castedValueNamePrefix, false, true); } public Cast( Expression targetObject, - TypeToken type, + TypeRef type, String castedValueNamePrefix, boolean inline, boolean ignoreUpcast) { @@ -732,7 +732,7 @@ public Cast( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -794,7 +794,7 @@ public String toString() { abstract class BaseInvoke extends Inlineable { final String functionName; - final TypeToken type; + final TypeRef type; Expression[] arguments; String returnNamePrefix; final boolean returnNullable; @@ -802,7 +802,7 @@ abstract class BaseInvoke extends Inlineable { public BaseInvoke( String functionName, - TypeToken type, + TypeRef type, Expression[] arguments, String returnNamePrefix, boolean returnNullable, @@ -827,25 +827,25 @@ public Invoke(Expression targetObject, String functionName, Expression... argume } /** Invoke don't accept arguments. */ - public Invoke(Expression targetObject, String functionName, TypeToken type) { + public Invoke(Expression targetObject, String functionName, TypeRef type) { this(targetObject, functionName, type, false); } /** Invoke don't accept arguments. */ public Invoke( - Expression targetObject, String functionName, String returnNamePrefix, TypeToken type) { + Expression targetObject, String functionName, String returnNamePrefix, TypeRef type) { this(targetObject, functionName, returnNamePrefix, type, false); } public Invoke( - Expression targetObject, String functionName, TypeToken type, Expression... arguments) { + Expression targetObject, String functionName, TypeRef type, Expression... arguments) { this(targetObject, functionName, "", type, false, arguments); } public Invoke( Expression targetObject, String functionName, - TypeToken type, + TypeRef type, boolean returnNullable, Expression... arguments) { this(targetObject, functionName, "", type, returnNullable, arguments); @@ -855,7 +855,7 @@ public Invoke( Expression targetObject, String functionName, String returnNamePrefix, - TypeToken type, + TypeRef type, boolean returnNullable, Expression... arguments) { this( @@ -872,7 +872,7 @@ public Invoke( Expression targetObject, String functionName, String returnNamePrefix, - TypeToken type, + TypeRef type, boolean returnNullable, boolean needTryCatch, Expression... arguments) { @@ -881,7 +881,7 @@ public Invoke( } public static Invoke inlineInvoke( - Expression targetObject, String functionName, TypeToken type, Expression... arguments) { + Expression targetObject, String functionName, TypeRef type, Expression... arguments) { Invoke invoke = new Invoke(targetObject, functionName, type, false, arguments); invoke.inlineCall = true; return invoke; @@ -890,7 +890,7 @@ public static Invoke inlineInvoke( public static Invoke inlineInvoke( Expression targetObject, String functionName, - TypeToken type, + TypeRef type, boolean needTryCatch, Expression... arguments) { Invoke invoke = @@ -900,7 +900,7 @@ public static Invoke inlineInvoke( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -1002,7 +1002,7 @@ public String toString() { class StaticInvoke extends BaseInvoke { private final Class staticObject; - public StaticInvoke(Class staticObject, String functionName, TypeToken type) { + public StaticInvoke(Class staticObject, String functionName, TypeRef type) { this(staticObject, functionName, type, false); } @@ -1011,14 +1011,14 @@ public StaticInvoke(Class staticObject, String functionName, Expression... ar } public StaticInvoke( - Class staticObject, String functionName, TypeToken type, Expression... arguments) { + Class staticObject, String functionName, TypeRef type, Expression... arguments) { this(staticObject, functionName, "", type, false, arguments); } public StaticInvoke( Class staticObject, String functionName, - TypeToken type, + TypeRef type, boolean returnNullable, Expression... arguments) { this(staticObject, functionName, "", type, returnNullable, arguments); @@ -1028,7 +1028,7 @@ public StaticInvoke( Class staticObject, String functionName, String returnNamePrefix, - TypeToken type, + TypeRef type, boolean returnNullable, Expression... arguments) { this(staticObject, functionName, returnNamePrefix, type, returnNullable, false, arguments); @@ -1049,7 +1049,7 @@ public StaticInvoke( Class staticObject, String functionName, String returnNamePrefix, - TypeToken type, + TypeRef type, boolean returnNullable, boolean inline, Expression... arguments) { @@ -1071,7 +1071,7 @@ public StaticInvoke( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -1167,7 +1167,7 @@ public String toString() { } class NewInstance implements Expression { - private TypeToken type; + private TypeRef type; private final Class rawType; private String unknownClassName; private List arguments; @@ -1181,19 +1181,18 @@ class NewInstance implements Expression { * unknownClassName} * @param unknownClassName unknownClassName that's unknown in compile-time */ - public NewInstance( - TypeToken interfaceType, String unknownClassName, Expression... arguments) { + public NewInstance(TypeRef interfaceType, String unknownClassName, Expression... arguments) { this(interfaceType, Arrays.asList(arguments), null); this.unknownClassName = unknownClassName; check(); } - public NewInstance(TypeToken type, Expression... arguments) { + public NewInstance(TypeRef type, Expression... arguments) { this(type, Arrays.asList(arguments), null); check(); } - private NewInstance(TypeToken type, List arguments, Expression outerPointer) { + private NewInstance(TypeRef type, List arguments, Expression outerPointer) { this.type = type; rawType = getRawType(type); this.outerPointer = outerPointer; @@ -1231,7 +1230,7 @@ private void check() { } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -1316,7 +1315,7 @@ public String toString() { } class NewArray implements Expression { - private TypeToken type; + private TypeRef type; private Expression[] elements; private int numDimensions; @@ -1330,7 +1329,7 @@ public NewArray(Class elemType, Expression dim) { this.numDimensions = 1; this.elemType = elemType; this.dim = dim; - type = TypeToken.of(Array.newInstance(elemType, 1).getClass()); + type = TypeRef.of(Array.newInstance(elemType, 1).getClass()); } /** @@ -1349,10 +1348,10 @@ public NewArray(Class elemType, int numDimensions, Expression dims) { for (int i = 0; i < numDimensions; i++) { stubSizes[i] = 1; } - type = TypeToken.of(Array.newInstance(elemType, stubSizes).getClass()); + type = TypeRef.of(Array.newInstance(elemType, stubSizes).getClass()); } - public NewArray(TypeToken type, Expression... elements) { + public NewArray(TypeRef type, Expression... elements) { this.type = type; this.elements = elements; this.numDimensions = 1; @@ -1367,7 +1366,7 @@ public static NewArray newArrayWithFirstDim( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -1476,7 +1475,7 @@ public AssignArrayElem(Expression targetArray, Expression value, Expression... i } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -1515,7 +1514,7 @@ class If implements Expression { private Expression predicate; private Expression trueExpr; private Expression falseExpr; - private TypeToken type; + private TypeRef type; private boolean nullable; public If(Expression predicate, Expression trueExpr) { @@ -1530,7 +1529,7 @@ public If( Expression trueExpr, Expression falseExpr, boolean nullable, - TypeToken type) { + TypeRef type) { this.predicate = predicate; this.trueExpr = trueExpr; this.falseExpr = falseExpr; @@ -1581,7 +1580,7 @@ public If(Expression predicate, Expression trueExpr, Expression falseExpr) { } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -1607,7 +1606,7 @@ public ExprCode doGenCode(CodegenContext ctx) { } else { cond = StringUtils.format("${condEvalValue}", "condEvalValue", condEval.value()); } - TypeToken type = this.type; + TypeRef type = this.type; if (!PRIMITIVE_VOID_TYPE.equals(type.unwrap())) { if (trueExpr instanceof Return && falseExpr instanceof Return) { type = PRIMITIVE_VOID_TYPE; @@ -1749,7 +1748,7 @@ public IsNull(Expression expr) { } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_BOOLEAN_TYPE; } @@ -1781,7 +1780,7 @@ public Not(Expression target) { } @Override - public TypeToken type() { + public TypeRef type() { return target.type(); } @@ -1808,7 +1807,7 @@ public String toString() { class BinaryOperator extends ValueExpression { private final boolean inline; private final String operator; - private final TypeToken type; + private final TypeRef type; private Expression left; private Expression right; @@ -1821,7 +1820,7 @@ public BinaryOperator(boolean inline, String operator, Expression left, Expressi } protected BinaryOperator( - boolean inline, String operator, Expression left, Expression right, TypeToken t) { + boolean inline, String operator, Expression left, Expression right, TypeRef t) { this.inline = inline; this.operator = operator; this.left = left; @@ -1849,7 +1848,7 @@ protected BinaryOperator( } @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -2030,7 +2029,7 @@ public While(BinaryOperator predicate, Expression action, Expression[] cutPoints } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -2073,7 +2072,7 @@ class ForEach implements Expression { @ClosureVisitable private final SerializableBiFunction action; - private final TypeToken elementType; + private final TypeRef elementType; /** * inputObject.type() must be multi-dimension array or Collection, not allowed to be primitive @@ -2083,7 +2082,7 @@ public ForEach( Expression inputObject, SerializableBiFunction action) { this.inputObject = inputObject; this.action = action; - TypeToken elementType; + TypeRef elementType; if (inputObject.type().isArray()) { elementType = inputObject.type().getComponentType(); } else { @@ -2094,7 +2093,7 @@ public ForEach( public ForEach( Expression inputObject, - TypeToken beanType, + TypeRef beanType, SerializableBiFunction action) { this.inputObject = inputObject; this.action = action; @@ -2102,7 +2101,7 @@ public ForEach( } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -2206,9 +2205,9 @@ public ZipForEach( this.right = right; this.action = action; Preconditions.checkArgument( - left.type().isArray() || TypeToken.of(Collection.class).isSupertypeOf(left.type())); + left.type().isArray() || TypeRef.of(Collection.class).isSupertypeOf(left.type())); Preconditions.checkArgument( - right.type().isArray() || TypeToken.of(Collection.class).isSupertypeOf(right.type())); + right.type().isArray() || TypeRef.of(Collection.class).isSupertypeOf(right.type())); if (left.type().isArray()) { Preconditions.checkArgument( right.type().isArray(), "Should both be array or neither be array"); @@ -2216,7 +2215,7 @@ public ZipForEach( } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -2235,14 +2234,14 @@ public ExprCode doGenCode(CodegenContext ctx) { String i = ctx.newName("i"); String leftElemValue = ctx.newName("leftElemValue"); String rightElemValue = ctx.newName("rightElemValue"); - TypeToken leftElemType; + TypeRef leftElemType; if (left.type().isArray()) { leftElemType = left.type().getComponentType(); } else { leftElemType = getElementType(left.type()); } leftElemType = ReflectionUtils.getPublicSuperType(leftElemType); - TypeToken rightElemType; + TypeRef rightElemType; if (right.type().isArray()) { rightElemType = right.type().getComponentType(); } else { @@ -2350,7 +2349,7 @@ public ForLoop( } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } @@ -2360,7 +2359,7 @@ public ExprCode doGenCode(CodegenContext ctx) { Preconditions.checkArgument(maxType.isPrimitive()); StringBuilder codeBuilder = new StringBuilder(); String i = ctx.newName("i"); - Reference iref = new Reference(i, TypeToken.of(maxType)); + Reference iref = new Reference(i, TypeRef.of(maxType)); Expression loopAction = action.apply(iref); ExprCode startExprCode = start.genCode(ctx); ExprCode endExprCode = end.genCode(ctx); @@ -2404,9 +2403,9 @@ public ExprCode doGenCode(CodegenContext ctx) { * that need List */ class ListFromIterable implements Expression { - private final TypeToken elementType; + private final TypeRef elementType; private Expression inputObject; - private final TypeToken type; + private final TypeRef type; public ListFromIterable(Expression inputObject) { this.inputObject = inputObject; @@ -2419,7 +2418,7 @@ public ListFromIterable(Expression inputObject) { /** Returns inputObject.type(), not {@code List}. */ @Override - public TypeToken type() { + public TypeRef type() { return type; } @@ -2473,7 +2472,7 @@ public Return(Expression expression) { } @Override - public TypeToken type() { + public TypeRef type() { return expression.type(); } @@ -2504,7 +2503,7 @@ public Assign(Expression from, Expression to) { } @Override - public TypeToken type() { + public TypeRef type() { return PRIMITIVE_VOID_TYPE; } diff --git a/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionUtils.java b/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionUtils.java index f1dbda5d7a..fcbbd1239c 100644 --- a/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionUtils.java +++ b/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionUtils.java @@ -28,7 +28,6 @@ import static org.apache.fury.codegen.Expression.StaticInvoke; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; @@ -36,6 +35,7 @@ import java.util.List; import org.apache.fury.codegen.Expression.Cast; import org.apache.fury.codegen.Expression.Null; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.Preconditions; import org.apache.fury.util.StringUtils; import org.apache.fury.util.function.Functions; @@ -45,10 +45,10 @@ public class ExpressionUtils { public static Expression newObjectArray(Expression... expressions) { - return new NewArray(TypeToken.of(Object[].class), expressions); + return new NewArray(TypeRef.of(Object[].class), expressions); } - public static Expression valueOf(TypeToken type, Expression value) { + public static Expression valueOf(TypeRef type, Expression value) { return new StaticInvoke(getRawType(type), "valueOf", type, false, value); } @@ -69,7 +69,7 @@ public static Not not(Expression target) { return new Not(target); } - public static Literal nullValue(TypeToken type) { + public static Literal nullValue(TypeRef type) { return new Literal(null, type); } @@ -140,8 +140,8 @@ public static Arithmetic subtract(Expression left, Expression right, String valu return arithmetic; } - public static Cast cast(Expression value, TypeToken typeToken) { - return new Cast(value, typeToken); + public static Cast cast(Expression value, TypeRef typeRef) { + return new Cast(value, typeRef); } public static Expression inline(Expression expression) { @@ -160,7 +160,7 @@ public static Expression uninline(Expression expression) { } public static StaticInvoke invokeStaticInline( - Class staticObject, String functionName, TypeToken type, Expression... arguments) { + Class staticObject, String functionName, TypeRef type, Expression... arguments) { return new StaticInvoke(staticObject, functionName, "", type, false, true, arguments); } diff --git a/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionVisitor.java b/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionVisitor.java index 5193cd977c..44fe103214 100644 --- a/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionVisitor.java +++ b/java/fury-core/src/main/java/org/apache/fury/codegen/ExpressionVisitor.java @@ -19,7 +19,6 @@ package org.apache.fury.codegen; -import com.google.common.reflect.TypeToken; import java.io.Serializable; import java.lang.invoke.SerializedLambda; import java.lang.reflect.Field; @@ -35,6 +34,7 @@ import org.apache.fury.codegen.Expression.ListExpression; import org.apache.fury.codegen.Expression.Reference; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.Preconditions; import org.apache.fury.util.ReflectionUtils; @@ -167,8 +167,8 @@ public void traverseChildren(Expression expr, Function func) traverseClosure(expr, field, func); } else { if (Iterable.class.isAssignableFrom(field.getType())) { - TypeToken fieldType = TypeToken.of(field.getGenericType()); - if (TypeUtils.getElementType(fieldType).equals(TypeToken.of(Expression.class))) { + TypeRef fieldType = TypeRef.of(field.getGenericType()); + if (TypeUtils.getElementType(fieldType).equals(TypeRef.of(Expression.class))) { List expressions = ReflectionUtils.getObjectFieldValue(expr, field); traverseList(expr, expressions, func); } diff --git a/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java b/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java index 9302149115..8714e3e36b 100644 --- a/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java +++ b/java/fury-core/src/main/java/org/apache/fury/meta/ClassDef.java @@ -24,7 +24,6 @@ import static org.apache.fury.type.TypeUtils.collectionOf; import static org.apache.fury.type.TypeUtils.mapOf; -import com.google.common.reflect.TypeToken; import java.io.ObjectStreamClass; import java.io.Serializable; import java.lang.reflect.Field; @@ -47,6 +46,7 @@ import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.MemoryUtils; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.serializer.CompatibleSerializer; import org.apache.fury.type.Descriptor; @@ -337,10 +337,10 @@ public FieldType getFieldType() { * reflection should be used to get the descriptor. */ public Descriptor toDescriptor(ClassResolver classResolver) { - TypeToken typeToken = fieldType.toTypeToken(classResolver); + TypeRef typeRef = fieldType.toTypeToken(classResolver); // This field doesn't exist in peer class, so any legal modifier will be OK. int stubModifiers = ReflectionUtils.getField(getClass(), "fieldName").getModifiers(); - return new Descriptor(typeToken, fieldName, stubModifiers, definedClass); + return new Descriptor(typeRef, fieldName, stubModifiers, definedClass); } @Override @@ -386,7 +386,7 @@ public boolean isMonomorphic() { * * @see FinalObjectTypeStub */ - public abstract TypeToken toTypeToken(ClassResolver classResolver); + public abstract TypeRef toTypeToken(ClassResolver classResolver); @Override public boolean equals(Object o) { @@ -456,8 +456,8 @@ public short getClassId() { } @Override - public TypeToken toTypeToken(ClassResolver classResolver) { - return TypeToken.of(classResolver.getRegisteredClass(classId)); + public TypeRef toTypeToken(ClassResolver classResolver) { + return TypeRef.of(classResolver.getRegisteredClass(classId)); } @Override @@ -512,7 +512,7 @@ public FieldType getElementType() { } @Override - public TypeToken toTypeToken(ClassResolver classResolver) { + public TypeRef toTypeToken(ClassResolver classResolver) { return collectionOf(elementType.toTypeToken(classResolver)); } @@ -574,7 +574,7 @@ public FieldType getValueType() { } @Override - public TypeToken toTypeToken(ClassResolver classResolver) { + public TypeRef toTypeToken(ClassResolver classResolver) { return mapOf(keyType.toTypeToken(classResolver), valueType.toTypeToken(classResolver)); } @@ -619,8 +619,8 @@ public ObjectFieldType(boolean isFinal) { } @Override - public TypeToken toTypeToken(ClassResolver classResolver) { - return isMonomorphic() ? TypeToken.of(FinalObjectTypeStub.class) : TypeToken.of(Object.class); + public TypeRef toTypeToken(ClassResolver classResolver) { + return isMonomorphic() ? TypeRef.of(FinalObjectTypeStub.class) : TypeRef.of(Object.class); } @Override @@ -676,7 +676,7 @@ static FieldType buildFieldType(ClassResolver classResolver, Field field) { private static FieldType buildFieldType(ClassResolver classResolver, GenericType genericType) { Preconditions.checkNotNull(genericType); boolean isFinal = genericType.isMonomorphic(); - if (COLLECTION_TYPE.isSupertypeOf(genericType.getTypeToken())) { + if (COLLECTION_TYPE.isSupertypeOf(genericType.getTypeRef())) { return new CollectionFieldType( isFinal, buildFieldType( @@ -684,7 +684,7 @@ private static FieldType buildFieldType(ClassResolver classResolver, GenericType genericType.getTypeParameter0() == null ? GenericType.build(Object.class) : genericType.getTypeParameter0())); - } else if (MAP_TYPE.isSupertypeOf(genericType.getTypeToken())) { + } else if (MAP_TYPE.isSupertypeOf(genericType.getTypeRef())) { return new MapFieldType( isFinal, buildFieldType( diff --git a/java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java new file mode 100644 index 0000000000..2823cbd77e --- /dev/null +++ b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.apache.fury.reflect; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Objects; + +public abstract class TypeParameter { + final TypeVariable typeVariable; + + public TypeParameter() { + Type superclass = getClass().getGenericSuperclass(); + if (!(superclass instanceof ParameterizedType)) { + throw new IllegalArgumentException(superclass + "isn't parameterized"); + } + this.typeVariable = + (TypeVariable) ((ParameterizedType) superclass).getActualTypeArguments()[0]; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TypeParameter that = (TypeParameter) o; + + return Objects.equals(typeVariable, that.typeVariable); + } + + @Override + public int hashCode() { + return typeVariable != null ? typeVariable.hashCode() : 0; + } + + @Override + public String toString() { + return "TypeParameter{" + "typeVariable=" + typeVariable + '}'; + } +} diff --git a/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java new file mode 100644 index 0000000000..9dae933ffc --- /dev/null +++ b/java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java @@ -0,0 +1,928 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.apache.fury.reflect; + +import static org.apache.fury.reflect.Types.asTypeVariableKeyOrNull; +import static org.apache.fury.reflect.Types.newArrayType; +import static org.apache.fury.reflect.Types.typeVariablesEquals; + +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.fury.type.TypeUtils; + +/** + * Mostly derived from Guava 32.1.2 com.google.common.reflect.TypeToken + * https://github.com/google/guava/blob/master/guava/src/com/google/common/reflect/TypeToken.java + */ +public class TypeRef { + + private final Type type; + private transient Class rawType; + private transient Map typeMappings; + + /** + * Constructs a new type token of {@code T}. + * + *

Clients create an empty anonymous subclass. This embeds the type parameter in the anonymous + * class's type hierarchy, so we can reconstitute it at runtime despite erasure. + * + *

For example: + * + *

{@code
+   * TypeRef> t = new TypeRef>() {};
+   * }
+ */ + protected TypeRef() { + this.type = capture(); + } + + private TypeRef(Class declaringClass) { + this.type = declaringClass; + } + + private TypeRef(Type type) { + this.type = type; + } + + /** Returns an instance of type token that wraps {@code type}. */ + public static TypeRef of(Class clazz) { + return new TypeRef<>(clazz); + } + + /** Returns an instance of type token that wraps {@code type}. */ + public static TypeRef of(Type type) { + return new TypeRef<>(type); + } + + /** Returns the captured type. */ + private Type capture() { + final Type superclass = getClass().getGenericSuperclass(); + if (!(superclass instanceof ParameterizedType)) { + throw new IllegalArgumentException(superclass + " isn't parameterized"); + } + return ((ParameterizedType) superclass).getActualTypeArguments()[0]; + } + + /** Returns the represented type. */ + public Type getType() { + return type; + } + + /** + * Returns the raw type of {@code T}. Formally speaking, if {@code T} is returned by {@link + * java.lang.reflect.Method#getGenericReturnType}, the raw type is what's returned by {@link + * java.lang.reflect.Method#getReturnType} of the same method object. Specifically: + * + *
    + *
  • If {@code T} is a {@code Class} itself, {@code T} itself is returned. + *
  • If {@code T} is a {@link ParameterizedType}, the raw type of the parameterized type is + * returned. + *
  • If {@code T} is a {@link GenericArrayType}, the returned type is the corresponding array + * class. For example: {@code List[] => List[]}. + *
  • If {@code T} is a type variable or a wildcard type, the raw type of the first upper bound + * is returned. For example: {@code => Foo}. + *
+ */ + public Class getRawType() { + Class cachedRawType = rawType; + if (cachedRawType != null) { + return cachedRawType; + } + @SuppressWarnings("unchecked") + Class rawType = (Class) TypeUtils.getRawType(type); + this.rawType = rawType; + return rawType; + } + + private static Stream> getRawTypes(Type... types) { + return Arrays.stream(types) + .flatMap( + type -> { + if (type instanceof TypeVariable) { + return getRawTypes(((TypeVariable) type).getBounds()); + } else if (type instanceof WildcardType) { + return getRawTypes(((WildcardType) type).getUpperBounds()); + } else if (type instanceof ParameterizedType) { + return Stream.of((Class) ((ParameterizedType) type).getRawType()); + } else if (type instanceof Class) { + return Stream.of((Class) type); + } else if (type instanceof GenericArrayType) { + Class rawType = + getArrayClass( + of(((GenericArrayType) type).getGenericComponentType()).getRawType()); + return Stream.of(rawType); + } else { + throw new AssertionError("Unknown type: " + type); + } + }); + } + + /** Returns true if this type is one of the primitive types (including {@code void}). */ + public boolean isPrimitive() { + return type instanceof Class && ((Class) type).isPrimitive(); + } + + /** + * Returns true if this type is known to be an array type, such as {@code int[]}, {@code T[]}, + * {@code []>} etc. + */ + public boolean isArray() { + return getComponentType(type) != null; + } + + /** + * Returns the array component type if this type represents an array ({@code int[]}, {@code T[]}, + * {@code []>} etc.), or else {@code null} is returned. + */ + public TypeRef getComponentType() { + return of(getComponentType(type)); + } + + /** + * Returns the array component type if this type represents an array ({@code int[]}, {@code T[]}, + * {@code []>} etc.), or else {@code null} is returned. + */ + private static Type getComponentType(Type type) { + if (type == null) { + return null; + } + if (type instanceof TypeVariable) { + return subtypeOfComponentType(((TypeVariable) type).getBounds()); + } else if (type instanceof WildcardType) { + return subtypeOfComponentType(((WildcardType) type).getUpperBounds()); + } else if (type instanceof Class) { + return ((Class) type).getComponentType(); + } else if (type instanceof GenericArrayType) { + return ((GenericArrayType) type).getGenericComponentType(); + } + return null; + } + + /** + * Returns {@code ? extends X} if any of {@code bounds} is a subtype of {@code X[]}; or null + * otherwise. + */ + private static Type subtypeOfComponentType(Type[] bounds) { + for (Type bound : bounds) { + final Type componentType = getComponentType(bound); + if (componentType != null) { + // Only the first bound can be a class or array. + // Bounds after the first can only be interfaces. + if (componentType instanceof Class) { + final Class componentClass = (Class) componentType; + if (componentClass.isPrimitive()) { + return componentClass; + } + } + return componentType; + } + } + return null; + } + + /** + * Resolves the given {@code type} against the type context represented by this type. For example: + * + *
{@code
+   * new TypeRef>() {}.resolveType(
+   *     List.class.getMethod("get", int.class).getGenericReturnType())
+   * => String.class
+   * }
+ */ + public TypeRef resolveType(Type iteratorReturnType) { + if (iteratorReturnType instanceof WildcardType) { // fast path + return of(iteratorReturnType); + } + Type invariantContext = WildcardCapturer.capture(type); + Map mappings = resolveTypeMappings(invariantContext); + return resolveType0(iteratorReturnType, mappings); + } + + private TypeRef resolveType0( + Type iteratorReturnType, Map mappings) { + if (iteratorReturnType instanceof TypeVariable) { + TypeVariable typeVariable = (TypeVariable) iteratorReturnType; + Type type = mappings.get(new Types.TypeVariableKey(typeVariable)); + if (type == null) { + return of(typeVariable); + } + return resolveType0(type, mappings); + } else if (iteratorReturnType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) iteratorReturnType; + Type owner = parameterizedType.getOwnerType(); + Type resolvedOwner = owner == null ? null : resolveType0(owner, mappings).type; + Type resolvedRawType = resolveType0(parameterizedType.getRawType(), mappings).type; + + Type[] args = parameterizedType.getActualTypeArguments(); + + Type[] resolvedArgs = new Type[args.length]; + for (int i = 0; i < args.length; i++) { + resolvedArgs[i] = resolveType0(args[i], mappings).type; + } + + return of(new Types.ParameterizedTypeImpl(resolvedOwner, resolvedRawType, resolvedArgs)); + } else if (iteratorReturnType instanceof GenericArrayType) { + Type componentType = ((GenericArrayType) iteratorReturnType).getGenericComponentType(); + Type resolvedComponentType = resolveType0(componentType, mappings).type; + return of(newArrayType(resolvedComponentType)); + } + return of(iteratorReturnType); + } + + private Map resolveTypeMappings() { + Map cachedMappings = this.typeMappings; + if (cachedMappings != null) { + return cachedMappings; + } + Map typeMappings = resolveTypeMappings(type); + this.typeMappings = typeMappings; + return typeMappings; + } + + private static Map resolveTypeMappings(Type contextType) { + Map result = new HashMap<>(); + populateTypeMapping(result, contextType); + return result; + } + + private static void populateTypeMapping(Map storage, Type... types) { + for (Type type : types) { + if (type == null) { + continue; + } + + if (type instanceof TypeVariable) { + populateTypeMapping(storage, ((TypeVariable) type).getBounds()); + } else if (type instanceof WildcardType) { + populateTypeMapping(storage, ((WildcardType) type).getUpperBounds()); + } else if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + + Class rawClass = (Class) parameterizedType.getRawType(); + TypeVariable[] vars = rawClass.getTypeParameters(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + storageFiller: + for (int i = 0; i < vars.length; i++) { + TypeVariable typeVariable = vars[i]; + Types.TypeVariableKey key = new Types.TypeVariableKey(typeVariable); + if (storage.containsKey(key)) { + continue; + } + Type arg = typeArgs[i]; + // First, check whether var -> arg forms a cycle + for (Type t = arg; t != null; t = storage.get(asTypeVariableKeyOrNull(t))) { + if (typeVariablesEquals(typeVariable, t)) { + // cycle detected, remove the entire cycle from the mapping so that + // each type variable resolves deterministically to itself. + // Otherwise, an F -> T cycle will end up resolving both F and T + // nondeterministically to either F or T. + Type x = arg; + while (x != null) { + x = storage.remove(asTypeVariableKeyOrNull(x)); + } + break storageFiller; + } + } + storage.put(key, arg); + } + populateTypeMapping(storage, rawClass); + populateTypeMapping(storage, parameterizedType.getOwnerType()); + } else if (type instanceof Class) { + Class clazz = (Class) type; + populateTypeMapping(storage, clazz.getGenericSuperclass()); + populateTypeMapping(storage, clazz.getGenericInterfaces()); + } else { + throw new AssertionError("Unknown type: " + type); + } + } + } + + /** + * Returns the generic form of {@code superclass}. For example, if this is {@code + * ArrayList}, {@code Iterable} is returned given the input {@code + * Iterable.class}. + */ + public TypeRef getSupertype(Class superclass) { + if (type instanceof TypeVariable) { + return getSupertypeFromBounds(superclass, ((TypeVariable) type).getBounds()); + } + if (type instanceof WildcardType) { + return getSupertypeFromBounds(superclass, ((WildcardType) type).getUpperBounds()); + } + if (superclass.isArray()) { + Type componentType; + if (type instanceof Class) { + componentType = ((Class) type).getComponentType(); + } else if (type instanceof GenericArrayType) { + componentType = ((GenericArrayType) type).getGenericComponentType(); + } else { + throw new AssertionError("Unknown type: " + type); + } + if (componentType == null) { + throw new IllegalArgumentException(superclass + " isn't a super type of " + this); + } + + @SuppressWarnings("rawtypes") + TypeRef componentTypeRef = of(componentType); + + @SuppressWarnings("unchecked") + TypeRef componentSupertype = componentTypeRef.getSupertype(superclass.getComponentType()); + + return of(newArrayType(componentSupertype.type)); + } + + Map mappings = resolveTypeMappings(); + @SuppressWarnings("unchecked") // resolved supertype + TypeRef supertype = + (TypeRef) resolveType0(toGenericType(superclass), mappings); + return supertype; + } + + private static Type toGenericType(Class cls) { + if (cls.isArray()) { + return Types.newArrayType( + // If we are passed with int[].class, don't turn it to GenericArrayType + toGenericType(cls.getComponentType())); + } + TypeVariable>[] typeParams = cls.getTypeParameters(); + Type ownerType = + cls.isMemberClass() && !Modifier.isStatic(cls.getModifiers()) + ? toGenericType(cls.getEnclosingClass()) + : null; + if (typeParams.length > 0 || (ownerType != null && ownerType != cls.getEnclosingClass())) { + return new Types.ParameterizedTypeImpl(ownerType, cls, typeParams); + } else { + return cls; + } + } + + private TypeRef getSupertypeFromBounds(Class superclass, Type[] bounds) { + for (Type upperBound : bounds) { + TypeRef bound = of(upperBound); + if (bound.isSubtypeOf(superclass)) { + @SuppressWarnings({"unchecked"}) // guarded by the isSubtypeOf check. + TypeRef result = (TypeRef) bound.getSupertype(superclass); + return result; + } + } + throw new IllegalArgumentException(superclass + " isn't a super type of " + this); + } + + /** + * Returns subtype of {@code this} with {@code subclass} as the raw class. For example, if this is + * {@code Iterable} and {@code subclass} is {@code List}, {@code List} is + * returned. + */ + public final TypeRef getSubtype(Class subclass) { + if (type instanceof WildcardType) { + Type[] lowerBounds = ((WildcardType) type).getLowerBounds(); + if (lowerBounds.length > 0) { + TypeRef bound = of(lowerBounds[0]); + // Java supports only one lowerbound anyway. + return bound.getSubtype(subclass); + } + throw new IllegalArgumentException(subclass + " isn't a subclass of " + this); + } + Type componentType = getComponentType(type); + if (componentType != null) { + Class subclassComponentType = subclass.getComponentType(); + if (subclassComponentType == null) { + throw new IllegalArgumentException( + subclass + " does not appear to be a subtype of " + this); + } + // array is covariant. component type is subtype, so is the array type. + // requireNonNull is safe because we call getArraySubtype only when isArray(). + TypeRef componentSubtype = of(componentType).getSubtype(subclassComponentType); + // If we are passed with int[].class, don't turn it to GenericArrayType + return of(Types.newArrayType(componentSubtype.type)); + } + + Class rawType = getRawType(); + if (!rawType.isAssignableFrom(subclass)) { + throw new IllegalArgumentException(subclass + " isn't a subclass of " + this); + } + + // If both runtimeType and subclass are not parameterized, return subclass + // If runtimeType is not parameterized but subclass is, process subclass as a parameterized type + // If runtimeType is a raw type (i.e. is a parameterized type specified as a Class), we + // return subclass as a raw type + if (type instanceof Class + && ((subclass.getTypeParameters().length == 0) + || (rawType.getTypeParameters().length != 0))) { + // no resolution needed + @SuppressWarnings({"unchecked"}) // subclass isn't + TypeRef result = (TypeRef) of(subclass); + return result; + } + // class Base {} + // class Sub extends Base {} + // Base.subtype(Sub.class): + + // Sub.getSupertype(Base.class) => Base + // => X=String, Y=Integer + // => Sub=Sub + TypeRef genericSubtype = of(toGenericType(subclass)); + @SuppressWarnings({"rawtypes", "unchecked"}) // subclass isn't + Type supertypeWithArgsFromSubtype = genericSubtype.getSupertype((Class) rawType).type; + + if (genericSubtype.type instanceof WildcardType) { + @SuppressWarnings({"unchecked"}) // subclass isn't + TypeRef result = (TypeRef) genericSubtype; + return result; + } + + Map mappings = new HashMap<>(); + populateTypeMappings(mappings, supertypeWithArgsFromSubtype, type); + + return (TypeRef) resolveType0(genericSubtype.type, mappings); + } + + private void populateTypeMappings( + Map mappings, Type supertypeWithArgsFromSubtype, Type toType) { + if (supertypeWithArgsFromSubtype instanceof TypeVariable) { + Types.TypeVariableKey typeVariableKey = + new Types.TypeVariableKey((TypeVariable) supertypeWithArgsFromSubtype); + mappings.put(typeVariableKey, toType); + } else if (supertypeWithArgsFromSubtype instanceof WildcardType) { + if (!(toType instanceof WildcardType)) { + return; // okay to say is anything + } + WildcardType supertypeWildcard = (WildcardType) supertypeWithArgsFromSubtype; + WildcardType toWildcardType = (WildcardType) toType; + Type[] fromUpperBounds = supertypeWildcard.getUpperBounds(); + Type[] toUpperBounds = toWildcardType.getUpperBounds(); + Type[] fromLowerBounds = supertypeWildcard.getLowerBounds(); + Type[] toLowerBounds = toWildcardType.getLowerBounds(); + for (int i = 0; i < fromUpperBounds.length; i++) { + populateTypeMappings(mappings, fromUpperBounds[i], toUpperBounds[i]); + } + for (int i = 0; i < fromLowerBounds.length; i++) { + populateTypeMappings(mappings, fromLowerBounds[i], toLowerBounds[i]); + } + } else if (supertypeWithArgsFromSubtype instanceof ParameterizedType) { + if (toType instanceof WildcardType) { + return; // Okay to say Foo is + } + ParameterizedType toParameterizedType = (ParameterizedType) toType; + ParameterizedType supertypeParameterized = (ParameterizedType) supertypeWithArgsFromSubtype; + if (supertypeParameterized.getOwnerType() != null + && toParameterizedType.getOwnerType() != null) { + populateTypeMappings( + mappings, supertypeParameterized.getOwnerType(), toParameterizedType.getOwnerType()); + } + Type[] fromArgs = supertypeParameterized.getActualTypeArguments(); + Type[] toArgs = toParameterizedType.getActualTypeArguments(); + for (int i = 0; i < fromArgs.length; i++) { + populateTypeMappings(mappings, fromArgs[i], toArgs[i]); + } + } else if (supertypeWithArgsFromSubtype instanceof Class) { + if (toType instanceof WildcardType) { + return; // Okay to say Foo is + } + // Can't map from a raw class to anything other than itself or a wildcard. + // You can't say "assuming String is Integer". + // And we don't support "assuming String is T"; user has to say "assuming T is String". + throw new IllegalArgumentException( + "No type mapping from " + supertypeWithArgsFromSubtype + " to " + toType); + } else if (supertypeWithArgsFromSubtype instanceof GenericArrayType) { + if (toType instanceof WildcardType) { + return; // Okay to say A[] is + } + Type componentType = getComponentType(toType); + Type fromComponentType = + ((GenericArrayType) supertypeWithArgsFromSubtype).getGenericComponentType(); + populateTypeMappings(mappings, fromComponentType, componentType); + } else { + throw new AssertionError("Unknown type: " + toType); + } + } + + /** Returns true if this type is a subtype of the given {@code type}. */ + public boolean isSubtypeOf(TypeRef type) { + return isSubtypeOf(type.getType()); + } + + /** Returns true if this type is a subtype of the given {@code type}. */ + public final boolean isSubtypeOf(Type supertype) { + if (supertype instanceof WildcardType) { + for (Type bound : ((WildcardType) supertype).getLowerBounds()) { + if (isSubtypeOf(bound)) { + return true; + } + } + return false; + } + + if (type instanceof WildcardType) { + return anyTypeIsSubTypeOf(type, ((WildcardType) type).getUpperBounds()); + } + + if (type instanceof TypeVariable) { + if (type.equals(supertype)) { + return true; + } + + return anyTypeIsSubTypeOf(type, ((TypeVariable) type).getBounds()); + } + + if (supertype instanceof Class) { + return anyRawTypeIsSubclassOf((Class) supertype); + } + if (supertype instanceof ParameterizedType) { + ParameterizedType parameterizedSuperType = (ParameterizedType) supertype; + Class matchedClass = of(parameterizedSuperType).getRawType(); + if (!anyRawTypeIsSubclassOf(matchedClass)) { + return false; + } + TypeVariable[] typeParameters = matchedClass.getTypeParameters(); + Type[] supertypeArgs = parameterizedSuperType.getActualTypeArguments(); + for (int i = 0; i < typeParameters.length; i++) { + TypeVariable typeParameter = typeParameters[i]; + + Map mappings = resolveTypeMappings(); + TypeRef subtypeParam = resolveType0(typeParameter, mappings); + + if (!subtypeParam.is(supertypeArgs[i], typeParameter)) { + return false; + } + } + + if (Modifier.isStatic(((Class) parameterizedSuperType.getRawType()).getModifiers()) + || parameterizedSuperType.getOwnerType() == null) { + return true; + } + + return collectTypes(this) + .anyMatch( + type -> { + if (type.type instanceof ParameterizedType) { + return of(((ParameterizedType) type.type).getOwnerType()).isSubtypeOf(supertype); + } else if (type.type instanceof Class) { + return of(((Class) type.type).getEnclosingClass()).isSubtypeOf(supertype); + } + return false; + }); + } + + if (supertype instanceof GenericArrayType) { + if (type instanceof Class) { + Class fromClass = (Class) type; + if (!fromClass.isArray()) { + return false; + } + return of(fromClass.getComponentType()) + .isSubtypeOf(((GenericArrayType) supertype).getGenericComponentType()); + } else if (type instanceof GenericArrayType) { + return of(((GenericArrayType) type).getGenericComponentType()) + .isSubtypeOf(((GenericArrayType) supertype).getGenericComponentType()); + } else { + return false; + } + } + + return false; + } + + private Stream> collectTypes(TypeRef type) { + return Stream.of(type) + .flatMap( + t -> { + Stream> genericInterfacesTypeRefs = + t.getGenericInterfaces().flatMap(this::collectTypes); + TypeRef superclass = t.getGenericSuperclass(); + return superclass == null + ? genericInterfacesTypeRefs + : Stream.concat(genericInterfacesTypeRefs, collectTypes(superclass)); + }); + } + + private Stream> getGenericInterfaces() { + if (type instanceof TypeVariable) { + return boundsAsInterfaces(((TypeVariable) type).getBounds()); + } + if (type instanceof WildcardType) { + return boundsAsInterfaces(((WildcardType) type).getUpperBounds()); + } + Map mappings = resolveTypeMappings(); + return Arrays.stream(getRawType().getGenericInterfaces()) + .map( + interfaceType -> { + @SuppressWarnings("unchecked") // interface of T + TypeRef resolvedInterface = + (TypeRef) resolveType0(interfaceType, mappings); + return resolvedInterface; + }); + } + + private TypeRef getGenericSuperclass() { + if (type instanceof TypeVariable) { + // First bound is always the super class, if one exists. + return boundAsSuperclass(((TypeVariable) type).getBounds()[0]); + } + if (type instanceof WildcardType) { + // wildcard has one and only one upper bound. + return boundAsSuperclass(((WildcardType) type).getUpperBounds()[0]); + } + Type superclass = getRawType().getGenericSuperclass(); + if (superclass == null) { + return null; + } + + Map mappings = resolveTypeMappings(); + @SuppressWarnings("unchecked") // interface of T + TypeRef superToken = (TypeRef) resolveType0(superclass, mappings); + return superToken; + } + + private TypeRef boundAsSuperclass(Type bound) { + TypeRef token = of(bound); + if (token.getRawType().isInterface()) { + return null; + } + @SuppressWarnings("unchecked") // only upper bound of T is passed in. + TypeRef superclass = (TypeRef) token; + return superclass; + } + + private Stream> boundsAsInterfaces(Type[] bounds) { + return Arrays.stream(bounds) + .map(TypeRef::of) + .filter(boundType -> boundType.getRawType().isInterface()); + } + + private boolean is(Type formalType, TypeVariable declaration) { + if (type.equals(formalType)) { + return true; + } + if (formalType instanceof WildcardType) { + WildcardType your = canonicalizeWildcardType(declaration, (WildcardType) formalType); + // if "formalType" is , "this" can be: + // Foo, SubFoo, , , or + // . + // if "formalType" is , "this" can be: + // Foo, SuperFoo, or . + for (Type bound : your.getUpperBounds()) { + if (!of(bound).isSupertypeOf(type)) { + return false; + } + } + for (Type bound : your.getLowerBounds()) { + if (!of(bound).isSupertypeOf(type)) { + return false; + } + } + return true; + } + return canonicalizeWildcardsInType(type).equals(canonicalizeWildcardsInType(formalType)); + } + + private static WildcardType canonicalizeWildcardType( + TypeVariable declaration, WildcardType type) { + Type[] declared = declaration.getBounds(); + List upperBounds = new ArrayList<>(); + upperBoundsGenerator: + for (Type bound : type.getUpperBounds()) { + for (Type declaredType : declared) { + if (of(declaredType).isSubtypeOf(bound)) { + continue upperBoundsGenerator; + } + } + upperBounds.add(canonicalizeWildcardsInType(bound)); + } + return new Types.WildcardTypeImpl(type.getLowerBounds(), upperBounds.toArray(new Type[0])); + } + + private static Type canonicalizeWildcardsInType(Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + Class rawType = (Class) parameterizedType.getRawType(); + TypeVariable[] typeVars = rawType.getTypeParameters(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < typeArgs.length; i++) { + Type typeArg = typeArgs[i]; + typeArgs[i] = + typeArg instanceof WildcardType + ? canonicalizeWildcardType(typeVars[i], (WildcardType) typeArg) + : canonicalizeWildcardsInType(typeArg); + } + return new Types.ParameterizedTypeImpl(parameterizedType.getOwnerType(), rawType, typeArgs); + } + if (type instanceof GenericArrayType) { + return Types.newArrayType( + canonicalizeWildcardsInType(((GenericArrayType) type).getGenericComponentType())); + } + return type; + } + + private static boolean anyTypeIsSubTypeOf(Type upperBound, Type[] declared) { + for (Type declaredType : declared) { + if (of(declaredType).isSubtypeOf(upperBound)) { + return true; + } + } + return false; + } + + private boolean anyRawTypeIsSubclassOf(Class supertype) { + return getRawTypes(type).anyMatch(supertype::isAssignableFrom); + } + + /** Returns true if this type is a supertype of the given {@code type}. */ + public final boolean isSupertypeOf(Type type) { + return isSupertypeOf(of(type)); + } + + /** Returns true if this type is a supertype of the given {@code type}. */ + public final boolean isSupertypeOf(TypeRef type) { + return type.isSubtypeOf(getType()); + } + + /** + * Returns the corresponding wrapper type if this is a primitive type; otherwise returns {@code + * this} itself. + */ + public final TypeRef wrap() { + if (isPrimitive()) { + @SuppressWarnings("unchecked") + final Class clazz = (Class) type; + // cast is safe: long.class and Long.class are both of type Class + @SuppressWarnings("unchecked") + final Class wrapped = (Class) TypeUtils.wrap(clazz); + return of(wrapped); + } + return this; + } + + /** + * Returns the corresponding primitive type if this is a wrapper type; otherwise returns {@code + * this} itself. + */ + public final TypeRef unwrap() { + if (isWrapper()) { + @SuppressWarnings("unchecked") // this is a wrapper class + final Class clazz = (Class) type; + // cast is safe: long.class and Long.class are both of type Class + @SuppressWarnings("unchecked") + final Class unwrapped = (Class) TypeUtils.unwrap(clazz); + return of(unwrapped); + } + return this; + } + + public TypeRef where(TypeParameter typeParam, Class typeArg) { + return where(typeParam, of(typeArg)); + } + + public final TypeRef where(TypeParameter typeParam, TypeRef typeArg) { + if (type instanceof WildcardType) { // fast path + return of(type); + } + Types.TypeVariableKey typeVariableKey = new Types.TypeVariableKey(typeParam.typeVariable); + @SuppressWarnings("unchecked") + TypeRef result = + (TypeRef) resolveType0(type, Collections.singletonMap(typeVariableKey, typeArg.type)); + return result; + } + + private boolean isWrapper() { + if (type instanceof Class) { + return TypeUtils.isBoxed((Class) type); + } + return false; + } + + /** + * Returns true if {@code o} is another {@code TypeToken} that represents the same {@link Type}. + */ + @Override + public boolean equals(Object o) { + if (o instanceof TypeRef) { + final TypeRef that = (TypeRef) o; + return type.equals(that.type); + } + return false; + } + + @Override + public int hashCode() { + return type.hashCode(); + } + + @Override + public String toString() { + return (type instanceof Class) ? ((Class) type).getName() : type.toString(); + } + + /** Returns the {@code Class} object of arrays with {@code componentType}. */ + private static Class getArrayClass(Class componentType) { + return Array.newInstance(componentType, 0).getClass(); + } + + private static class WildcardCapturer { + private static final WildcardCapturer INSTANCE = new WildcardCapturer(); + + static Type capture(Type type) { + return INSTANCE.capture0(type); + } + + final Type capture0(Type type) { + if (type instanceof Class) { + return type; + } + if (type instanceof TypeVariable) { + return type; + } + if (type instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType) type; + return newArrayType(capture0(arrayType.getGenericComponentType())); + } + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + Class rawType = (Class) parameterizedType.getRawType(); + TypeVariable[] typeVars = rawType.getTypeParameters(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < typeArgs.length; i++) { + typeArgs[i] = forTypeVariable(typeVars[i]).capture0(typeArgs[i]); + } + Type ownerType = parameterizedType.getOwnerType(); + return new Types.ParameterizedTypeImpl( + ownerType == null ? null : capture0(ownerType), rawType, typeArgs); + } + if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) type; + Type[] lowerBounds = wildcardType.getLowerBounds(); + return lowerBounds.length == 0 // ? extends something changes to capture-of + ? captureAsTypeVariable(wildcardType.getUpperBounds()) + : type; + } + throw new AssertionError("must have been one of the known types"); + } + + TypeVariable captureAsTypeVariable(Type[] upperBounds) { + String name = + "capture of ? extends " + + Stream.of(upperBounds).map(Type::toString).collect(Collectors.joining("&")); + return new Types.TypeVariableImpl<>(WildcardCapturer.class, name, upperBounds); + } + + private WildcardCapturer forTypeVariable(TypeVariable typeParam) { + return new WildcardCapturer() { + @Override + TypeVariable captureAsTypeVariable(Type[] upperBounds) { + // Since this is an artificially generated type variable, we don't bother checking + // subtyping between declared type bound and actual type bound. So it's possible that we + // may generate something like . + // Checking subtype between declared and actual type bounds + // adds recursive isSubtypeOf() call and feels complicated. + // There is no contract one way or another as long as isSubtypeOf() works as expected. + Type[] typeParamBounds = typeParam.getBounds(); + Type[] combinedUpperBounds = upperBounds; + if (typeParamBounds.length > 0) { + int upperBoundsLength = upperBounds.length; + combinedUpperBounds = new Type[typeParamBounds.length + upperBoundsLength]; + int i = 0; + for (; i < upperBoundsLength; i++) { + combinedUpperBounds[i] = upperBounds[i]; + } + rootFor: + for (; i < combinedUpperBounds.length; i++) { + Type typeParamBound = typeParamBounds[i - upperBoundsLength]; + for (Type upperBound : upperBounds) { + if (upperBound.equals(typeParamBound)) { + continue rootFor; + } + } + combinedUpperBounds[i] = typeParamBound; + } + } + return super.captureAsTypeVariable(combinedUpperBounds); + } + }; + } + } +} diff --git a/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java b/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java new file mode 100644 index 0000000000..1f35786344 --- /dev/null +++ b/java/fury-core/src/main/java/org/apache/fury/reflect/Types.java @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.apache.fury.reflect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Objects; +import javax.annotation.CheckForNull; + +class Types { + public static Type newArrayType(Type componentType) { + if (componentType instanceof WildcardType) { + WildcardType wildcard = (WildcardType) componentType; + Type[] lowerBounds = wildcard.getLowerBounds(); + if (lowerBounds.length == 1) { + return new WildcardTypeImpl(new Type[] {lowerBounds[0]}, new Type[] {Object.class}); + } else { + Type[] upperBounds = wildcard.getUpperBounds(); + return new WildcardTypeImpl(new Type[0], new Type[] {upperBounds[0]}); + } + } + return componentType instanceof Class + ? Array.newInstance((Class) componentType, 0).getClass() + : new GenericArrayTypeImpl(componentType); + } + + public static boolean typeVariablesEquals(TypeVariable a, Object bobj) { + if (bobj instanceof TypeVariable) { + TypeVariable b = (TypeVariable) bobj; + return a.getGenericDeclaration().equals(b.getGenericDeclaration()) + && a.getName().equals(b.getName()); + } else { + return false; + } + } + + public static TypeVariableKey asTypeVariableKeyOrNull(Type t) { + if (t instanceof TypeVariable) { + return new TypeVariableKey((TypeVariable) t); + } + return null; + } + + private static Type getOwnerTypeFromRawType(Class rawType) { + return ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType); + } + + private static String resolveTypeName(Type type) { + return type instanceof Class ? ((Class) type).getName() : type.toString(); + } + + public static class ParameterizedTypeImpl implements ParameterizedType { + private final Type[] actualTypeArguments; + private final Type rawType; + private final Type ownerType; + + public ParameterizedTypeImpl(Type ownerType, Type rawType, Type[] actualTypeArguments) { + if (ownerType == null) { + this.ownerType = getOwnerTypeFromRawType((Class) rawType); + } else { + this.ownerType = ownerType; + } + this.rawType = rawType; + this.actualTypeArguments = actualTypeArguments; + } + + @Override + public Type getOwnerType() { + return ownerType; + } + + @Override + public Type getRawType() { + return rawType; + } + + @Override + public Type[] getActualTypeArguments() { + return actualTypeArguments; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ParameterizedType)) { + return false; + } + + ParameterizedType that = (ParameterizedType) o; + + if (!Arrays.equals(actualTypeArguments, that.getActualTypeArguments())) { + return false; + } + if (!Objects.equals(rawType, that.getRawType())) { + return false; + } + return Objects.equals(ownerType, that.getOwnerType()); + } + + @Override + public int hashCode() { + int result = Arrays.hashCode(actualTypeArguments); + result = 31 * result + (rawType != null ? rawType.hashCode() : 0); + result = 31 * result + (ownerType != null ? ownerType.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "ParameterizedTypeImpl{" + + "actualTypeArguments=" + + Arrays.toString(actualTypeArguments) + + ", rawType=" + + rawType + + ", ownerType=" + + ownerType + + '}'; + } + } + + public static class GenericArrayTypeImpl implements GenericArrayType { + private final Type genericComponentType; + + public GenericArrayTypeImpl(Type genericComponentType) { + this.genericComponentType = genericComponentType; + } + + @Override + public Type getGenericComponentType() { + return genericComponentType; + } + + @Override + public String toString() { + return resolveTypeName(genericComponentType) + "[]"; + } + + @Override + public int hashCode() { + return genericComponentType.hashCode(); + } + + @Override + public boolean equals(@CheckForNull Object obj) { + if (obj instanceof GenericArrayType) { + GenericArrayType that = (GenericArrayType) obj; + return Objects.equals(getGenericComponentType(), that.getGenericComponentType()); + } + return false; + } + } + + public static class WildcardTypeImpl implements WildcardType { + private final Type[] upperBounds; + private final Type[] lowerBounds; + + public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { + this.upperBounds = upperBounds; + this.lowerBounds = lowerBounds; + } + + @Override + public Type[] getUpperBounds() { + return upperBounds; + } + + @Override + public Type[] getLowerBounds() { + return lowerBounds; + } + + @Override + public boolean equals(@CheckForNull Object obj) { + if (obj instanceof WildcardType) { + WildcardType that = (WildcardType) obj; + return Arrays.equals(lowerBounds, that.getLowerBounds()) + && Arrays.equals(upperBounds, that.getUpperBounds()); + } + return false; + } + + @Override + public int hashCode() { + return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("?"); + for (Type lowerBound : lowerBounds) { + builder.append(" super ").append(resolveTypeName(lowerBound)); + } + for (Type upperBound : upperBounds) { + if (!upperBound.equals(Object.class)) { + builder.append(" extends ").append(resolveTypeName(upperBound)); + } + } + return builder.toString(); + } + } + + public static class TypeVariableImpl implements TypeVariable { + private final D genericDeclaration; + private final String name; + private final Type[] upperBounds; + + TypeVariableImpl(D genericDeclaration, String name, Type[] upperBounds) { + this.genericDeclaration = genericDeclaration; + this.name = name; + this.upperBounds = upperBounds; + } + + @Override + public Type[] getBounds() { + return upperBounds; + } + + @Override + public D getGenericDeclaration() { + return genericDeclaration; + } + + @Override + public String getName() { + return name; + } + + @Override + public AnnotatedType[] getAnnotatedBounds() { + return new AnnotatedType[0]; + } + + @Override + public T getAnnotation(Class annotationClass) { + return null; + } + + @Override + public Annotation[] getAnnotations() { + return new Annotation[0]; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return new Annotation[0]; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TypeVariable)) { + return false; + } + + TypeVariable that = (TypeVariable) o; + return Objects.equals(genericDeclaration, that.getGenericDeclaration()) + && Objects.equals(name, that.getName()) + && Arrays.equals(upperBounds, that.getBounds()); + } + + @Override + public int hashCode() { + int result = genericDeclaration != null ? genericDeclaration.hashCode() : 0; + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + Arrays.hashCode(upperBounds); + return result; + } + } + + static class TypeVariableKey { + private final TypeVariable typeVariable; + + public TypeVariableKey(TypeVariable typeVariable) { + this.typeVariable = typeVariable; + } + + @Override + public boolean equals(Object o) { + return o instanceof TypeVariableKey + && Types.typeVariablesEquals(typeVariable, ((TypeVariableKey) o).typeVariable); + } + + @Override + public int hashCode() { + Annotation[] declaredAnnotations = typeVariable.getDeclaredAnnotations(); + String name = typeVariable.getName(); + + int result = 1; + result = + 31 * result + (declaredAnnotations != null ? Arrays.hashCode(declaredAnnotations) : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } + } + + private enum ClassOwnership { + OWNED_BY_ENCLOSING_CLASS { + @Override + Class getOwnerType(Class rawType) { + return rawType.getEnclosingClass(); + } + }, + LOCAL_CLASS_HAS_NO_OWNER { + @Override + Class getOwnerType(Class rawType) { + return rawType.isLocalClass() ? null : rawType.getEnclosingClass(); + } + }; + + abstract Class getOwnerType(Class rawType); + + static final ClassOwnership JVM_BEHAVIOR = detectJvmBehaviour(); + + private static ClassOwnership detectJvmBehaviour() { + class LocalClass {} + + LocalClass localClassInstance = new LocalClass() {}; + Class subclass = localClassInstance.getClass(); + ParameterizedType parameterizedType = (ParameterizedType) subclass.getGenericSuperclass(); + for (ClassOwnership behavior : ClassOwnership.values()) { + if (behavior.getOwnerType(LocalClass.class) == parameterizedType.getOwnerType()) { + return behavior; + } + } + throw new AssertionError(); + } + } +} diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index 9af9360bb4..42f38d77ba 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -29,7 +29,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; import com.google.common.collect.ImmutableMap; -import com.google.common.reflect.TypeToken; import java.io.Externalizable; import java.io.IOException; import java.io.Serializable; @@ -99,6 +98,7 @@ import org.apache.fury.memory.Platform; import org.apache.fury.meta.ClassDef; import org.apache.fury.meta.MetaString; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.ArraySerializers; import org.apache.fury.serializer.ArraySerializers.UnexistedArrayClassSerializer; import org.apache.fury.serializer.ArraySerializers.UnexistedEnumArrayClassSerializer; @@ -1765,9 +1765,9 @@ public int hashCode() { } } - public GenericType buildGenericType(TypeToken typeToken) { + public GenericType buildGenericType(TypeRef typeRef) { return GenericType.build( - typeToken.getType(), + typeRef.getType(), t -> { if (t.getClass() == Class.class) { return isMonomorphic((Class) t); diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java index 26230f4b51..53909cc0cb 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java @@ -27,7 +27,6 @@ import static org.apache.fury.resolver.FieldResolver.FieldInfoEncodingType.SEPARATE_TYPES_HASH; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -47,6 +46,7 @@ import org.apache.fury.collection.Tuple2; import org.apache.fury.exception.ClassNotCompatibleException; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.PrimitiveSerializers; import org.apache.fury.serializer.collection.CollectionSerializer; import org.apache.fury.serializer.collection.MapSerializer; @@ -742,26 +742,25 @@ public static FieldInfo of( NO_CLASS_ID); } if (Collection.class.isAssignableFrom(field.getType())) { - TypeToken elementTypeToken = - TypeUtils.getElementType(TypeToken.of(field.getGenericType())); + TypeRef elementTypeRef = TypeUtils.getElementType(TypeRef.of(field.getGenericType())); byte fieldType = - ReflectionUtils.isMonomorphic(getRawType(elementTypeToken)) + ReflectionUtils.isMonomorphic(getRawType(elementTypeRef)) ? FieldTypes.COLLECTION_ELEMENT_FINAL : FieldTypes.OBJECT; return new CollectionFieldInfo( - fury, field, fieldType, fieldInfoEncodingType, encodedFieldInfo, elementTypeToken); + fury, field, fieldType, fieldInfoEncodingType, encodedFieldInfo, elementTypeRef); } else if (Map.class.isAssignableFrom(field.getType())) { - Tuple2, TypeToken> kvType = - TypeUtils.getMapKeyValueType(TypeToken.of(field.getGenericType())); - TypeToken keyTypeToken = kvType.f0; - TypeToken valueTypeToken = kvType.f1; + Tuple2, TypeRef> kvType = + TypeUtils.getMapKeyValueType(TypeRef.of(field.getGenericType())); + TypeRef keyTypeRef = kvType.f0; + TypeRef valueTypeRef = kvType.f1; byte fieldType; - if (ReflectionUtils.isMonomorphic(getRawType(keyTypeToken)) - && ReflectionUtils.isMonomorphic(getRawType(valueTypeToken))) { + if (ReflectionUtils.isMonomorphic(getRawType(keyTypeRef)) + && ReflectionUtils.isMonomorphic(getRawType(valueTypeRef))) { fieldType = FieldTypes.MAP_KV_FINAL; - } else if (ReflectionUtils.isMonomorphic(getRawType(keyTypeToken))) { + } else if (ReflectionUtils.isMonomorphic(getRawType(keyTypeRef))) { fieldType = FieldTypes.MAP_KEY_FINAL; - } else if (ReflectionUtils.isMonomorphic(getRawType(valueTypeToken))) { + } else if (ReflectionUtils.isMonomorphic(getRawType(valueTypeRef))) { fieldType = FieldTypes.MAP_VALUE_FINAL; } else { fieldType = FieldTypes.OBJECT; @@ -772,8 +771,8 @@ public static FieldInfo of( fieldType, fieldInfoEncodingType, encodedFieldInfo, - keyTypeToken, - valueTypeToken); + keyTypeRef, + valueTypeRef); } else { return new FieldInfo( fury, @@ -856,7 +855,7 @@ public short getEmbeddedClassId() { public static class CollectionFieldInfo extends FieldInfo { // TODO support nested generics. - private final TypeToken elementTypeToken; + private final TypeRef elementTypeToken; private final Class elementType; private final ClassInfoHolder elementClassInfoHolder; @@ -866,7 +865,7 @@ public CollectionFieldInfo( byte fieldType, FieldInfoEncodingType fieldInfoEncodingType, long encodedFieldInfo, - TypeToken elementTypeToken) { + TypeRef elementTypeRef) { super( fury, field.getName(), @@ -877,8 +876,8 @@ public CollectionFieldInfo( encodedFieldInfo, NO_CLASS_ID); Preconditions.checkArgument(field != STUB_FIELD); - this.elementTypeToken = elementTypeToken; - this.elementType = getRawType(elementTypeToken); + this.elementTypeToken = elementTypeRef; + this.elementType = getRawType(elementTypeRef); elementClassInfoHolder = classResolver.nilClassInfoHolder(); } @@ -890,7 +889,7 @@ public ClassInfo getElementClassInfo(Class elementType) { return classResolver.getClassInfo(elementType, elementClassInfoHolder); } - public TypeToken getElementTypeToken() { + public TypeRef getElementTypeToken() { return elementTypeToken; } @@ -903,8 +902,8 @@ public static class MapFieldInfo extends FieldInfo { private final Class keyType; private final boolean isKeyTypeFinal; // TODO support nested generics. - private final TypeToken keyTypeToken; - private final TypeToken valueTypeToken; + private final TypeRef keyTypeToken; + private final TypeRef valueTypeToken; private final ClassInfoHolder keyClassInfoHolder; private final Class valueType; private final boolean isValueTypeFinal; @@ -916,8 +915,8 @@ public MapFieldInfo( byte fieldType, FieldInfoEncodingType separateTypesHash, long encodedFieldInfo, - TypeToken keyTypeToken, - TypeToken valueTypeToken) { + TypeRef keyTypeRef, + TypeRef valueTypeRef) { super( fury, field.getName(), @@ -928,12 +927,12 @@ public MapFieldInfo( encodedFieldInfo, NO_CLASS_ID); Preconditions.checkArgument(field != STUB_FIELD); - this.keyTypeToken = keyTypeToken; - this.valueTypeToken = valueTypeToken; - keyType = getRawType(keyTypeToken); + this.keyTypeToken = keyTypeRef; + this.valueTypeToken = valueTypeRef; + keyType = getRawType(keyTypeRef); isKeyTypeFinal = ReflectionUtils.isMonomorphic(keyType); keyClassInfoHolder = classResolver.nilClassInfoHolder(); - valueType = getRawType(valueTypeToken); + valueType = getRawType(valueTypeRef); isValueTypeFinal = ReflectionUtils.isMonomorphic(valueType); valueClassInfoHolder = classResolver.nilClassInfoHolder(); } diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java index 8108903e2b..0a8d26b960 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java @@ -21,7 +21,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.invoke.MethodHandle; import java.util.ArrayList; import java.util.Arrays; @@ -35,6 +34,7 @@ import org.apache.fury.exception.FuryException; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; @@ -188,7 +188,7 @@ private static FinalTypeField buildFinalTypeField(Fury fury, Descriptor d) { private static GenericTypeField buildContainerField(Fury fury, Descriptor d) { return new GenericTypeField( - d.getTypeToken(), + d.getTypeRef(), d.getDeclaringClass() + "." + d.getName(), d.getField() != null ? FieldAccessor.createAccessor(d.getField()) : null, fury); @@ -921,12 +921,12 @@ private GenericTypeField( } private GenericTypeField( - TypeToken typeToken, String qualifiedFieldName, FieldAccessor accessor, Fury fury) { - super(getRegisteredClassId(fury, getRawType(typeToken)), qualifiedFieldName, accessor); + TypeRef typeRef, String qualifiedFieldName, FieldAccessor accessor, Fury fury) { + super(getRegisteredClassId(fury, getRawType(typeRef)), qualifiedFieldName, accessor); // TODO support generics in Pojo, see ComplexObjectSerializer.getGenericTypes - genericType = fury.getClassResolver().buildGenericType(typeToken); + genericType = fury.getClassResolver().buildGenericType(typeRef); classInfoHolder = fury.getClassResolver().nilClassInfoHolder(); - trackingRef = fury.getClassResolver().needToWriteRef(getRawType(typeToken)); + trackingRef = fury.getClassResolver().needToWriteRef(getRawType(typeRef)); } @Override diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/StructSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/StructSerializer.java index dacec0c52f..6d678ba2de 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/StructSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/StructSerializer.java @@ -19,7 +19,6 @@ package org.apache.fury.serializer; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -35,6 +34,7 @@ import org.apache.fury.logging.LoggerFactory; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.Descriptor; import org.apache.fury.type.GenericType; import org.apache.fury.type.Generics; @@ -81,13 +81,13 @@ public StructSerializer(Fury fury, Class cls, String typeTag) { .sorted(Comparator.comparing(Field::getName)) .map(FieldAccessor::createAccessor) .toArray(FieldAccessor[]::new); - fieldGenerics = buildFieldGenerics(TypeToken.of(cls), fieldAccessors); + fieldGenerics = buildFieldGenerics(TypeRef.of(cls), fieldAccessors); genericTypesCache = new IdentityHashMap<>(); genericTypesCache.put(null, fieldGenerics); } private static GenericType[] buildFieldGenerics( - TypeToken type, FieldAccessor[] fieldAccessors) { + TypeRef type, FieldAccessor[] fieldAccessors) { return Arrays.stream(fieldAccessors) .map(fieldAccessor -> GenericType.build(type, fieldAccessor.getField().getGenericType())) .toArray(GenericType[]::new); @@ -152,7 +152,7 @@ private GenericType[] getGenericTypes(Generics generics) { this.genericType = genericType; fieldGenerics = genericTypesCache.get(genericType); if (fieldGenerics == null) { - fieldGenerics = buildFieldGenerics(genericType.getTypeToken(), fieldAccessors); + fieldGenerics = buildFieldGenerics(genericType.getTypeRef(), fieldAccessors); genericTypesCache.put(genericType, fieldGenerics); } this.fieldGenerics = fieldGenerics; @@ -217,10 +217,10 @@ int computeStructHash() { int computeFieldHash(int hash, GenericType fieldGeneric) { int id; - if (fieldGeneric.getTypeToken().isSubtypeOf(List.class)) { + if (fieldGeneric.getTypeRef().isSubtypeOf(List.class)) { // TODO(chaokunyang) add list element type into schema hash id = Type.LIST.getId(); - } else if (fieldGeneric.getTypeToken().isSubtypeOf(Map.class)) { + } else if (fieldGeneric.getTypeRef().isSubtypeOf(Map.class)) { // TODO(chaokunyang) add map key&value type into schema hash id = Type.MAP.getId(); } else { diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java index ccadf32a88..ff83917868 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java @@ -21,13 +21,13 @@ import static org.apache.fury.type.TypeUtils.MAP_TYPE; -import com.google.common.reflect.TypeToken; import java.lang.invoke.MethodHandle; import java.util.Map; import org.apache.fury.Fury; import org.apache.fury.collection.IdentityMap; import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassInfoHolder; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.resolver.RefResolver; @@ -382,13 +382,13 @@ public static void xwriteElements(Fury fury, MemoryBuffer buffer, Map value) { private Tuple2 getKVGenericType(GenericType genericType) { Tuple2 genericTypes = partialGenericKVTypeMap.get(genericType); if (genericTypes == null) { - TypeToken typeToken = genericType.getTypeToken(); - if (!MAP_TYPE.isSupertypeOf(typeToken)) { + TypeRef typeRef = genericType.getTypeRef(); + if (!MAP_TYPE.isSupertypeOf(typeRef)) { Tuple2 typeTuple = Tuple2.of(objType, objType); partialGenericKVTypeMap.put(genericType, typeTuple); return typeTuple; } - Tuple2, TypeToken> mapKeyValueType = TypeUtils.getMapKeyValueType(typeToken); + Tuple2, TypeRef> mapKeyValueType = TypeUtils.getMapKeyValueType(typeRef); genericTypes = Tuple2.of( fury.getClassResolver().buildGenericType(mapKeyValueType.f0.getType()), diff --git a/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java b/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java index e4af8d0a4e..3b6e683558 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/Descriptor.java @@ -23,7 +23,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -47,6 +46,7 @@ import org.apache.fury.annotation.Internal; import org.apache.fury.collection.Tuple2; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.Preconditions; import org.apache.fury.util.StringUtils; import org.apache.fury.util.record.RecordComponent; @@ -70,7 +70,7 @@ public static void clearDescriptorCache() { descCache = CacheBuilder.newBuilder().weakKeys().softValues().concurrencyLevel(64).build(); } - private TypeToken typeToken; + private TypeRef typeRef; private Class type; private final String name; private final int modifier; @@ -79,22 +79,22 @@ public static void clearDescriptorCache() { private final Method readMethod; private final Method writeMethod; - public Descriptor(Field field, TypeToken typeToken, Method readMethod, Method writeMethod) { + public Descriptor(Field field, TypeRef typeRef, Method readMethod, Method writeMethod) { this.field = field; this.name = field.getName(); this.modifier = field.getModifiers(); this.declaringClass = field.getDeclaringClass().getName(); this.readMethod = readMethod; this.writeMethod = writeMethod; - this.typeToken = typeToken; + this.typeRef = typeRef; } - public Descriptor(TypeToken typeToken, String name, int modifier, String declaringClass) { + public Descriptor(TypeRef typeRef, String name, int modifier, String declaringClass) { this.field = null; this.name = name; this.modifier = modifier; this.declaringClass = declaringClass; - this.typeToken = typeToken; + this.typeRef = typeRef; this.readMethod = null; this.writeMethod = null; } @@ -106,18 +106,18 @@ private Descriptor(Field field, Method readMethod) { this.declaringClass = field.getDeclaringClass().getName(); this.readMethod = readMethod; this.writeMethod = null; - this.typeToken = null; + this.typeRef = null; } private Descriptor( - TypeToken typeToken, + TypeRef typeRef, String name, int modifier, String declaringClass, Field field, Method readMethod, Method writeMethod) { - this.typeToken = typeToken; + this.typeRef = typeRef; this.name = name; this.modifier = modifier; this.declaringClass = declaringClass; @@ -126,9 +126,8 @@ private Descriptor( this.writeMethod = writeMethod; } - public Descriptor copy(TypeToken typeToken, Method readMethod, Method writeMethod) { - return new Descriptor( - typeToken, name, modifier, declaringClass, field, readMethod, writeMethod); + public Descriptor copy(TypeRef typeRef, Method readMethod, Method writeMethod) { + return new Descriptor(typeRef, name, modifier, declaringClass, field, readMethod, writeMethod); } public Field getField() { @@ -159,25 +158,25 @@ public Method getWriteMethod() { return writeMethod; } - /** Try not use {@link TypeToken#getRawType()} since it's expensive. */ + /** Try not use {@link TypeRef#getRawType()} since it's expensive. */ public Class getRawType() { Class type = this.type; if (type == null) { if (field != null) { return this.type = field.getType(); } else { - return this.type = TypeUtils.getRawType(getTypeToken()); + return this.type = TypeUtils.getRawType(getTypeRef()); } } return Objects.requireNonNull(type); } - public TypeToken getTypeToken() { - TypeToken typeToken = this.typeToken; - if (typeToken == null && field != null) { - this.typeToken = typeToken = TypeToken.of(field.getGenericType()); + public TypeRef getTypeRef() { + TypeRef typeRef = this.typeRef; + if (typeRef == null && field != null) { + this.typeRef = typeRef = TypeRef.of(field.getGenericType()); } - return typeToken; + return typeRef; } @Override @@ -187,7 +186,7 @@ public String toString() { sb.append(", field=").append(field); sb.append(", readMethod=").append(readMethod); sb.append(", writeMethod=").append(writeMethod); - sb.append(", typeToken=").append(typeToken); + sb.append(", typeToken=").append(typeRef); sb.append('}'); return sb.toString(); } @@ -393,18 +392,18 @@ static void warmField(Class context, Field field, ExecutorService compilation } else if (TypeUtils.isCollection(fieldRawType) || TypeUtils.isMap(fieldRawType)) { // warm up generic type, sun.reflect.generics.repository.FieldRepository // is expensive. - compilationService.submit(() -> warmGenericTask(TypeToken.of(field.getGenericType()))); + compilationService.submit(() -> warmGenericTask(TypeRef.of(field.getGenericType()))); } else if (fieldRawType.isArray()) { Class componentType = fieldRawType.getComponentType(); if (!componentType.isPrimitive()) { - compilationService.submit(() -> warmGenericTask(TypeToken.of(field.getGenericType()))); + compilationService.submit(() -> warmGenericTask(TypeRef.of(field.getGenericType()))); } } } // this method should b executed in background thread pool. - static void warmGenericTask(TypeToken typeToken) { - Class rawType = TypeUtils.getRawType(typeToken); + static void warmGenericTask(TypeRef typeRef) { + Class rawType = TypeUtils.getRawType(typeRef); if (rawType.isPrimitive() || rawType == String.class || rawType == Object.class) { return; } @@ -414,14 +413,14 @@ static void warmGenericTask(TypeToken typeToken) { if (!rawType.getName().startsWith("java")) { getAllDescriptorsMap(rawType); } else if (TypeUtils.isCollection(rawType)) { - TypeToken elementType = TypeUtils.getElementType(typeToken); + TypeRef elementType = TypeUtils.getElementType(typeRef); warmGenericTask(elementType); } else if (TypeUtils.isMap(rawType)) { - Tuple2, TypeToken> mapKeyValueType = TypeUtils.getMapKeyValueType(typeToken); + Tuple2, TypeRef> mapKeyValueType = TypeUtils.getMapKeyValueType(typeRef); warmGenericTask(mapKeyValueType.f0); warmGenericTask(mapKeyValueType.f1); } else if (rawType.isArray()) { - warmGenericTask(typeToken.getComponentType()); + warmGenericTask(typeRef.getComponentType()); } } @@ -488,7 +487,7 @@ static SortedMap buildBeanedDescriptorsMap( setter = null; } } - TypeToken fieldType = TypeToken.of(field.getGenericType()); + TypeRef fieldType = TypeRef.of(field.getGenericType()); descriptorMap.put(field, new Descriptor(field, fieldType, getter, setter)); } // Don't cache descriptors using a static `WeakHashMap, SortedMap>`, diff --git a/java/fury-core/src/main/java/org/apache/fury/type/DescriptorGrouper.java b/java/fury-core/src/main/java/org/apache/fury/type/DescriptorGrouper.java index 3a3f4273d2..6d6995a4e6 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/DescriptorGrouper.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/DescriptorGrouper.java @@ -215,7 +215,7 @@ private static Descriptor createDescriptor(Descriptor d) { if (readMethod == null && d.getWriteMethod() == null) { return d; } - return d.copy(d.getTypeToken(), readMethod, null); + return d.copy(d.getTypeRef(), readMethod, null); } public static DescriptorGrouper createDescriptorGrouper( diff --git a/java/fury-core/src/main/java/org/apache/fury/type/GenericType.java b/java/fury-core/src/main/java/org/apache/fury/type/GenericType.java index bc1b3ac8bc..8dc040226d 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/GenericType.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/GenericType.java @@ -21,7 +21,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -30,6 +29,7 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.serializer.Serializer; import org.apache.fury.util.ReflectionUtils; @@ -46,7 +46,7 @@ public class GenericType { } }; - final TypeToken typeToken; + final TypeRef typeRef; final Class cls; final GenericType[] typeParameters; final int typeParametersCount; @@ -58,9 +58,9 @@ public class GenericType { Serializer serializer; private Boolean trackingRef; - public GenericType(TypeToken typeToken, boolean isMonomorphic, GenericType... typeParameters) { - this.typeToken = typeToken; - this.cls = getRawType(typeToken); + public GenericType(TypeRef typeRef, boolean isMonomorphic, GenericType... typeParameters) { + this.typeRef = typeRef; + this.cls = getRawType(typeRef); this.typeParameters = typeParameters; typeParametersCount = typeParameters.length; hasGenericParameters = typeParameters.length > 0; @@ -77,7 +77,7 @@ public GenericType(TypeToken typeToken, boolean isMonomorphic, GenericType... } } - public static GenericType build(TypeToken type) { + public static GenericType build(TypeRef type) { return build(type.getType()); } @@ -102,7 +102,7 @@ public static GenericType build(Type type) { * class B extends A {} * } */ - public static GenericType build(TypeToken context, Type type) { + public static GenericType build(TypeRef context, Type type) { return build(context, type, defaultFinalPredicate); } @@ -111,10 +111,10 @@ public static GenericType build(Class context, Type type) { } public static GenericType build(Class context, Type type, Predicate finalPredicate) { - return build(TypeToken.of(context), type, finalPredicate); + return build(TypeRef.of(context), type, finalPredicate); } - public static GenericType build(TypeToken context, Type type, Predicate finalPredicate) { + public static GenericType build(TypeRef context, Type type, Predicate finalPredicate) { return build(context.resolveType(type).getType(), finalPredicate); } @@ -129,15 +129,15 @@ public static GenericType build(Type type, Predicate finalPredicate) { list.add(build); } GenericType[] genericTypes = list.toArray(new GenericType[0]); - return new GenericType(TypeToken.of(type), finalPredicate.test(type), genericTypes); + return new GenericType(TypeRef.of(type), finalPredicate.test(type), genericTypes); } else if (type instanceof GenericArrayType) { // List[] or T[] Type componentType = ((GenericArrayType) type).getGenericComponentType(); - return new GenericType(TypeToken.of(type), finalPredicate.test(type), build(componentType)); + return new GenericType(TypeRef.of(type), finalPredicate.test(type), build(componentType)); } else if (type instanceof TypeVariable) { // T TypeVariable typeVariable = (TypeVariable) type; Type typeVariableBound = typeVariable.getBounds()[0]; // Bound 0 are a class, other bounds are interface. - return new GenericType(TypeToken.of(typeVariableBound), finalPredicate.test(type)); + return new GenericType(TypeRef.of(typeVariableBound), finalPredicate.test(type)); } else if (type instanceof WildcardType) { // WildcardType: `T extends Number`, not a type, just an expression. // `? extends java.util.Collection>` @@ -145,16 +145,16 @@ public static GenericType build(Type type, Predicate finalPredicate) { if (upperBound instanceof ParameterizedType) { return build(upperBound); } else { - return new GenericType(TypeToken.of(upperBound), finalPredicate.test(type)); + return new GenericType(TypeRef.of(upperBound), finalPredicate.test(type)); } } else { // Class type: String, Integer - return new GenericType(TypeToken.of(type), finalPredicate.test(type)); + return new GenericType(TypeRef.of(type), finalPredicate.test(type)); } } - public TypeToken getTypeToken() { - return typeToken; + public TypeRef getTypeRef() { + return typeRef; } public Class getCls() { @@ -212,7 +212,7 @@ public boolean hasGenericParameters() { @Override public String toString() { - return "GenericType{" + typeToken.toString() + '}'; + return "GenericType{" + typeRef.toString() + '}'; } public static boolean isFinalByDefault(Class cls) { diff --git a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java index fbd9bec086..97874893a1 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java @@ -19,10 +19,10 @@ package org.apache.fury.type; -import com.google.common.reflect.TypeToken; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.apache.fury.collection.Tuple2; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.ReflectionUtils; /** Scala types utils using reflection without dependency on scala library. */ @@ -60,16 +60,16 @@ public static Class getScalaIterableType() { return SCALA_ITERABLE_TYPE; } - public static TypeToken getElementType(TypeToken typeToken) { - TypeToken supertype = typeToken.getSupertype(getScalaIterableType()); + public static TypeRef getElementType(TypeRef typeRef) { + TypeRef supertype = typeRef.getSupertype(getScalaIterableType()); return supertype.resolveType(SCALA_ITERATOR_RETURN_TYPE).resolveType(SCALA_NEXT_RETURN_TYPE); } /** Returns key/value type of scala map. */ - public static Tuple2, TypeToken> getMapKeyValueType(TypeToken typeToken) { - TypeToken kvTupleType = getElementType(typeToken); + public static Tuple2, TypeRef> getMapKeyValueType(TypeRef typeRef) { + TypeRef kvTupleType = getElementType(typeRef); ParameterizedType type = (ParameterizedType) kvTupleType.getType(); Type[] types = type.getActualTypeArguments(); - return Tuple2.of(TypeToken.of(types[0]), TypeToken.of(types[1])); + return Tuple2.of(TypeRef.of(types[0]), TypeRef.of(types[1])); } } diff --git a/java/fury-core/src/main/java/org/apache/fury/type/TypeUtils.java b/java/fury-core/src/main/java/org/apache/fury/type/TypeUtils.java index f1191ca47c..7eb5bf5b77 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/TypeUtils.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/TypeUtils.java @@ -19,9 +19,6 @@ package org.apache.fury.type; -import com.google.common.collect.ImmutableList; -import com.google.common.reflect.TypeParameter; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Modifier; @@ -50,6 +47,8 @@ import java.util.stream.Collectors; import org.apache.fury.collection.IdentityMap; import org.apache.fury.collection.Tuple2; +import org.apache.fury.reflect.TypeParameter; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.Preconditions; import org.apache.fury.util.ReflectionUtils; @@ -63,58 +62,58 @@ public class TypeUtils { public static final String JAVA_LONG = "long"; public static final String JAVA_FLOAT = "float"; public static final String JAVA_DOUBLE = "double"; - public static final TypeToken PRIMITIVE_VOID_TYPE = TypeToken.of(void.class); - public static final TypeToken VOID_TYPE = TypeToken.of(Void.class); - public static final TypeToken PRIMITIVE_BYTE_TYPE = TypeToken.of(byte.class); - public static final TypeToken PRIMITIVE_BOOLEAN_TYPE = TypeToken.of(boolean.class); - public static final TypeToken PRIMITIVE_CHAR_TYPE = TypeToken.of(char.class); - public static final TypeToken PRIMITIVE_SHORT_TYPE = TypeToken.of(short.class); - public static final TypeToken PRIMITIVE_INT_TYPE = TypeToken.of(int.class); - public static final TypeToken PRIMITIVE_LONG_TYPE = TypeToken.of(long.class); - public static final TypeToken PRIMITIVE_FLOAT_TYPE = TypeToken.of(float.class); - public static final TypeToken PRIMITIVE_DOUBLE_TYPE = TypeToken.of(double.class); - public static final TypeToken BYTE_TYPE = TypeToken.of(Byte.class); - public static final TypeToken BOOLEAN_TYPE = TypeToken.of(Boolean.class); - public static final TypeToken CHAR_TYPE = TypeToken.of(Character.class); - public static final TypeToken SHORT_TYPE = TypeToken.of(Short.class); - public static final TypeToken INT_TYPE = TypeToken.of(Integer.class); - public static final TypeToken LONG_TYPE = TypeToken.of(Long.class); - public static final TypeToken FLOAT_TYPE = TypeToken.of(Float.class); - public static final TypeToken DOUBLE_TYPE = TypeToken.of(Double.class); - public static final TypeToken STRING_TYPE = TypeToken.of(String.class); - public static final TypeToken BIG_DECIMAL_TYPE = TypeToken.of(BigDecimal.class); - public static final TypeToken BIG_INTEGER_TYPE = TypeToken.of(BigInteger.class); - public static final TypeToken DATE_TYPE = TypeToken.of(Date.class); - public static final TypeToken LOCAL_DATE_TYPE = TypeToken.of(LocalDate.class); - public static final TypeToken TIMESTAMP_TYPE = TypeToken.of(Timestamp.class); - public static final TypeToken INSTANT_TYPE = TypeToken.of(Instant.class); - public static final TypeToken BINARY_TYPE = TypeToken.of(byte[].class); - public static final TypeToken ITERABLE_TYPE = TypeToken.of(Iterable.class); - public static final TypeToken COLLECTION_TYPE = TypeToken.of(Collection.class); - public static final TypeToken LIST_TYPE = TypeToken.of(List.class); - public static final TypeToken ARRAYLIST_TYPE = TypeToken.of(ArrayList.class); - public static final TypeToken SET_TYPE = TypeToken.of(Set.class); - public static final TypeToken HASHSET_TYPE = TypeToken.of(HashSet.class); - public static final TypeToken MAP_TYPE = TypeToken.of(Map.class); - public static final TypeToken HASHMAP_TYPE = TypeToken.of(HashMap.class); - public static final TypeToken OBJECT_TYPE = TypeToken.of(Object.class); + public static final TypeRef PRIMITIVE_VOID_TYPE = TypeRef.of(void.class); + public static final TypeRef VOID_TYPE = TypeRef.of(Void.class); + public static final TypeRef PRIMITIVE_BYTE_TYPE = TypeRef.of(byte.class); + public static final TypeRef PRIMITIVE_BOOLEAN_TYPE = TypeRef.of(boolean.class); + public static final TypeRef PRIMITIVE_CHAR_TYPE = TypeRef.of(char.class); + public static final TypeRef PRIMITIVE_SHORT_TYPE = TypeRef.of(short.class); + public static final TypeRef PRIMITIVE_INT_TYPE = TypeRef.of(int.class); + public static final TypeRef PRIMITIVE_LONG_TYPE = TypeRef.of(long.class); + public static final TypeRef PRIMITIVE_FLOAT_TYPE = TypeRef.of(float.class); + public static final TypeRef PRIMITIVE_DOUBLE_TYPE = TypeRef.of(double.class); + public static final TypeRef BYTE_TYPE = TypeRef.of(Byte.class); + public static final TypeRef BOOLEAN_TYPE = TypeRef.of(Boolean.class); + public static final TypeRef CHAR_TYPE = TypeRef.of(Character.class); + public static final TypeRef SHORT_TYPE = TypeRef.of(Short.class); + public static final TypeRef INT_TYPE = TypeRef.of(Integer.class); + public static final TypeRef LONG_TYPE = TypeRef.of(Long.class); + public static final TypeRef FLOAT_TYPE = TypeRef.of(Float.class); + public static final TypeRef DOUBLE_TYPE = TypeRef.of(Double.class); + public static final TypeRef STRING_TYPE = TypeRef.of(String.class); + public static final TypeRef BIG_DECIMAL_TYPE = TypeRef.of(BigDecimal.class); + public static final TypeRef BIG_INTEGER_TYPE = TypeRef.of(BigInteger.class); + public static final TypeRef DATE_TYPE = TypeRef.of(Date.class); + public static final TypeRef LOCAL_DATE_TYPE = TypeRef.of(LocalDate.class); + public static final TypeRef TIMESTAMP_TYPE = TypeRef.of(Timestamp.class); + public static final TypeRef INSTANT_TYPE = TypeRef.of(Instant.class); + public static final TypeRef BINARY_TYPE = TypeRef.of(byte[].class); + public static final TypeRef ITERABLE_TYPE = TypeRef.of(Iterable.class); + public static final TypeRef COLLECTION_TYPE = TypeRef.of(Collection.class); + public static final TypeRef LIST_TYPE = TypeRef.of(List.class); + public static final TypeRef ARRAYLIST_TYPE = TypeRef.of(ArrayList.class); + public static final TypeRef SET_TYPE = TypeRef.of(Set.class); + public static final TypeRef HASHSET_TYPE = TypeRef.of(HashSet.class); + public static final TypeRef MAP_TYPE = TypeRef.of(Map.class); + public static final TypeRef HASHMAP_TYPE = TypeRef.of(HashMap.class); + public static final TypeRef OBJECT_TYPE = TypeRef.of(Object.class); public static Type ITERATOR_RETURN_TYPE; public static Type NEXT_RETURN_TYPE; public static Type KEY_SET_RETURN_TYPE; public static Type VALUES_RETURN_TYPE; - public static final TypeToken PRIMITIVE_BYTE_ARRAY_TYPE = TypeToken.of(byte[].class); - public static final TypeToken PRIMITIVE_BOOLEAN_ARRAY_TYPE = TypeToken.of(boolean[].class); - public static final TypeToken PRIMITIVE_SHORT_ARRAY_TYPE = TypeToken.of(short[].class); - public static final TypeToken PRIMITIVE_CHAR_ARRAY_TYPE = TypeToken.of(char[].class); - public static final TypeToken PRIMITIVE_INT_ARRAY_TYPE = TypeToken.of(int[].class); - public static final TypeToken PRIMITIVE_LONG_ARRAY_TYPE = TypeToken.of(long[].class); - public static final TypeToken PRIMITIVE_FLOAT_ARRAY_TYPE = TypeToken.of(float[].class); - public static final TypeToken PRIMITIVE_DOUBLE_ARRAY_TYPE = TypeToken.of(double[].class); - public static final TypeToken OBJECT_ARRAY_TYPE = TypeToken.of(Object[].class); + public static final TypeRef PRIMITIVE_BYTE_ARRAY_TYPE = TypeRef.of(byte[].class); + public static final TypeRef PRIMITIVE_BOOLEAN_ARRAY_TYPE = TypeRef.of(boolean[].class); + public static final TypeRef PRIMITIVE_SHORT_ARRAY_TYPE = TypeRef.of(short[].class); + public static final TypeRef PRIMITIVE_CHAR_ARRAY_TYPE = TypeRef.of(char[].class); + public static final TypeRef PRIMITIVE_INT_ARRAY_TYPE = TypeRef.of(int[].class); + public static final TypeRef PRIMITIVE_LONG_ARRAY_TYPE = TypeRef.of(long[].class); + public static final TypeRef PRIMITIVE_FLOAT_ARRAY_TYPE = TypeRef.of(float[].class); + public static final TypeRef PRIMITIVE_DOUBLE_ARRAY_TYPE = TypeRef.of(double[].class); + public static final TypeRef OBJECT_ARRAY_TYPE = TypeRef.of(Object[].class); - public static final TypeToken CLASS_TYPE = TypeToken.of(Class.class); + public static final TypeRef CLASS_TYPE = TypeRef.of(Class.class); /** * bean fields should all be in SUPPORTED_TYPES, enum, array/ITERABLE_TYPE/MAP_TYPE type, bean @@ -123,7 +122,7 @@ public class TypeUtils { *

If bean fields is ITERABLE_TYPE/MAP_TYPE, the type should be super class(inclusive) of * List/Set/Map, or else should be a no arg constructor. */ - public static Set> SUPPORTED_TYPES = new HashSet<>(); + public static Set> SUPPORTED_TYPES = new HashSet<>(); static { SUPPORTED_TYPES.add(PRIMITIVE_BYTE_TYPE); @@ -166,7 +165,7 @@ public class TypeUtils { // sorted by size private static final List> sortedPrimitiveClasses = - ImmutableList.of( + Arrays.asList( void.class, boolean.class, byte.class, @@ -177,7 +176,7 @@ public class TypeUtils { long.class, double.class); private static final List> sortedBoxedClasses = - ImmutableList.of( + Arrays.asList( Void.class, Boolean.class, Byte.class, @@ -271,7 +270,7 @@ public static Class maxType(Class... numericTypes) { } /** Returns size of primitive type. */ - public static int getSizeOfPrimitiveType(TypeToken numericType) { + public static int getSizeOfPrimitiveType(TypeRef numericType) { return getSizeOfPrimitiveType(getRawType(numericType)); } @@ -326,17 +325,17 @@ public static String defaultValue(String type, boolean typedNull) { } } - /** Faster method to get raw type from {@link TypeToken} than {@link TypeToken#getRawType}. */ - public static Class getRawType(TypeToken typeToken) { - Type type = typeToken.getType(); + /** Faster method to get raw type from {@link TypeRef} than {@link TypeRef#getRawType}. */ + public static Class getRawType(TypeRef typeRef) { + Type type = typeRef.getType(); if (type.getClass() == Class.class) { return (Class) type; } else { - return getRawType(typeToken.getType()); + return getRawType(typeRef.getType()); } } - /** Faster method to get raw type from {@link TypeToken} than {@link TypeToken#getRawType}. */ + /** Faster method to get raw type from {@link TypeRef} than {@link TypeRef#getRawType}. */ public static Class getRawType(Type type) { if (type instanceof TypeVariable) { return getRawType(((TypeVariable) type).getBounds()[0]); @@ -348,14 +347,14 @@ public static Class getRawType(Type type) { return ((Class) type); } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); - return Array.newInstance(getRawType(TypeToken.of(componentType)), 0).getClass(); + return Array.newInstance(getRawType(TypeRef.of(componentType)), 0).getClass(); } else { throw new AssertionError("Unknown type: " + type); } } /** Returns dimensions of multi-dimension array. */ - public static int getArrayDimensions(TypeToken type) { + public static int getArrayDimensions(TypeRef type) { return getArrayDimensions(getRawType(type)); } @@ -388,7 +387,7 @@ public static Tuple2, Integer> getArrayComponentInfo(Class type) { } /** Returns s string that represents array type declaration of type. */ - public static String getArrayType(TypeToken type) { + public static String getArrayType(TypeRef type) { return getArrayType(getRawType(type)); } @@ -417,8 +416,8 @@ public static String getArrayType(Class elemType, int[] dimensions) { * @param type array type * @return element type of multi-dimension array */ - public static TypeToken getMultiDimensionArrayElementType(TypeToken type) { - TypeToken t = type; + public static TypeRef getMultiDimensionArrayElementType(TypeRef type) { + TypeRef t = type; while (t != null && t.isArray()) { t = t.getComponentType(); } @@ -426,8 +425,8 @@ public static TypeToken getMultiDimensionArrayElementType(TypeToken type) } /** Returns element type of iterable. */ - public static TypeToken getElementType(TypeToken typeToken) { - Type type = typeToken.getType(); + public static TypeRef getElementType(TypeRef typeRef) { + Type type = typeRef.getType(); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; if (parameterizedType.getRawType() == List.class) { // fastpath @@ -435,28 +434,26 @@ public static TypeToken getElementType(TypeToken typeToken) { Preconditions.checkState(actualTypeArguments.length == 1); Type t = actualTypeArguments[0]; if (t.getClass() == Class.class) { // if t is wild type, upper should be parsed. - return TypeToken.of(t); + return TypeRef.of(t); } } } - if (typeToken.getType().getTypeName().startsWith("scala.collection")) { - return ScalaTypes.getElementType(typeToken); + if (typeRef.getType().getTypeName().startsWith("scala.collection")) { + return ScalaTypes.getElementType(typeRef); } - TypeToken supertype = - ((TypeToken>) typeToken).getSupertype(Iterable.class); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Iterable.class); return supertype.resolveType(ITERATOR_RETURN_TYPE).resolveType(NEXT_RETURN_TYPE); } - public static TypeToken getCollectionType(TypeToken typeToken) { + public static TypeRef getCollectionType(TypeRef typeRef) { @SuppressWarnings("unchecked") - TypeToken supertype = - ((TypeToken>) typeToken).getSupertype(Iterable.class); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Iterable.class); return supertype.getSubtype(Collection.class); } /** Returns key/value type of map. */ - public static Tuple2, TypeToken> getMapKeyValueType(TypeToken typeToken) { - Type type = typeToken.getType(); + public static Tuple2, TypeRef> getMapKeyValueType(TypeRef typeRef) { + Type type = typeRef.getType(); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; if (parameterizedType.getRawType() == Map.class) { // fastpath @@ -465,60 +462,59 @@ public static Tuple2, TypeToken> getMapKeyValueType(TypeToken if (actualTypeArguments[0].getClass() == Class.class && actualTypeArguments[1].getClass() == Class.class) { // if actualTypeArguments are wild type, upper should be parsed. - return Tuple2.of( - TypeToken.of(actualTypeArguments[0]), TypeToken.of(actualTypeArguments[1])); + return Tuple2.of(TypeRef.of(actualTypeArguments[0]), TypeRef.of(actualTypeArguments[1])); } } } - if (typeToken.getType().getTypeName().startsWith("scala.collection")) { - return ScalaTypes.getMapKeyValueType(typeToken); + if (typeRef.getType().getTypeName().startsWith("scala.collection")) { + return ScalaTypes.getMapKeyValueType(typeRef); } @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) typeToken).getSupertype(Map.class); - TypeToken keyType = getElementType(supertype.resolveType(KEY_SET_RETURN_TYPE)); - TypeToken valueType = getElementType(supertype.resolveType(VALUES_RETURN_TYPE)); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Map.class); + TypeRef keyType = getElementType(supertype.resolveType(KEY_SET_RETURN_TYPE)); + TypeRef valueType = getElementType(supertype.resolveType(VALUES_RETURN_TYPE)); return Tuple2.of(keyType, valueType); } - public static TypeToken> arrayListOf(Class elemType) { - return new TypeToken>() {}.where(new TypeParameter() {}, elemType); + public static TypeRef> arrayListOf(Class elemType) { + return new TypeRef>() {}.where(new TypeParameter() {}, elemType); } - public static TypeToken> listOf(Class elemType) { - return new TypeToken>() {}.where(new TypeParameter() {}, elemType); + public static TypeRef> listOf(Class elemType) { + return new TypeRef>() {}.where(new TypeParameter() {}, elemType); } - public static TypeToken> collectionOf(Class elemType) { - return collectionOf(TypeToken.of(elemType)); + public static TypeRef> collectionOf(Class elemType) { + return collectionOf(TypeRef.of(elemType)); } - public static TypeToken> collectionOf(TypeToken elemType) { - return new TypeToken>() {}.where(new TypeParameter() {}, elemType); + public static TypeRef> collectionOf(TypeRef elemType) { + return new TypeRef>() {}.where(new TypeParameter() {}, elemType); } - public static TypeToken> mapOf(Class keyType, Class valueType) { - return mapOf(TypeToken.of(keyType), TypeToken.of(valueType)); + public static TypeRef> mapOf(Class keyType, Class valueType) { + return mapOf(TypeRef.of(keyType), TypeRef.of(valueType)); } - public static TypeToken> mapOf(TypeToken keyType, TypeToken valueType) { - return new TypeToken>() {}.where(new TypeParameter() {}, keyType) + public static TypeRef> mapOf(TypeRef keyType, TypeRef valueType) { + return new TypeRef>() {}.where(new TypeParameter() {}, keyType) .where(new TypeParameter() {}, valueType); } - public static TypeToken> mapOf( - Class mapType, TypeToken keyType, TypeToken valueType) { - TypeToken> mapTypeToken = mapOf(keyType, valueType); - return mapTypeToken.getSubtype(mapType); + public static TypeRef> mapOf( + Class mapType, TypeRef keyType, TypeRef valueType) { + TypeRef> mapTypeRef = mapOf(keyType, valueType); + return mapTypeRef.getSubtype(mapType); } - public static TypeToken> mapOf( + public static TypeRef> mapOf( Class mapType, Class keyType, Class valueType) { - TypeToken> mapTypeToken = mapOf(keyType, valueType); - return mapTypeToken.getSubtype(mapType); + TypeRef> mapTypeRef = mapOf(keyType, valueType); + return mapTypeRef.getSubtype(mapType); } - public static TypeToken> hashMapOf(Class keyType, Class valueType) { - return new TypeToken>() {}.where(new TypeParameter() {}, keyType) + public static TypeRef> hashMapOf(Class keyType, Class valueType) { + return new TypeRef>() {}.where(new TypeParameter() {}, keyType) .where(new TypeParameter() {}, valueType); } @@ -531,24 +527,24 @@ public static boolean isMap(Class cls) { } public static boolean isBean(Type type) { - return isBean(TypeToken.of(type)); + return isBean(TypeRef.of(type)); } public static boolean isBean(Class clz) { - return isBean(TypeToken.of(clz)); + return isBean(TypeRef.of(clz)); } /** * Returns true if class is not array/iterable/map, and all fields is {@link - * TypeUtils#isSupported(TypeToken)}. Bean class can't be a non-static inner class. Public static + * TypeUtils#isSupported(TypeRef)}. Bean class can't be a non-static inner class. Public static * nested class is ok. */ - public static boolean isBean(TypeToken typeToken) { - return isBean(typeToken, new LinkedHashSet<>()); + public static boolean isBean(TypeRef typeRef) { + return isBean(typeRef, new LinkedHashSet<>()); } - private static boolean isBean(TypeToken typeToken, LinkedHashSet walkedTypePath) { - Class cls = getRawType(typeToken); + private static boolean isBean(TypeRef typeRef, LinkedHashSet walkedTypePath) { + Class cls = getRawType(typeRef); if (Modifier.isAbstract(cls.getModifiers()) || Modifier.isInterface(cls.getModifiers())) { return false; } @@ -559,23 +555,23 @@ private static boolean isBean(TypeToken typeToken, LinkedHashSet w if (cls.getEnclosingClass() != null && !Modifier.isStatic(cls.getModifiers())) { return false; } - LinkedHashSet newTypePath = new LinkedHashSet<>(walkedTypePath); - newTypePath.add(typeToken); + LinkedHashSet newTypePath = new LinkedHashSet<>(walkedTypePath); + newTypePath.add(typeRef); if (cls == Object.class) { // return false for typeToken that point to un-specialized generic type. return false; } boolean maybe = - !SUPPORTED_TYPES.contains(typeToken) - && !typeToken.isArray() + !SUPPORTED_TYPES.contains(typeRef) + && !typeRef.isArray() && !cls.isEnum() - && !ITERABLE_TYPE.isSupertypeOf(typeToken) - && !MAP_TYPE.isSupertypeOf(typeToken); + && !ITERABLE_TYPE.isSupertypeOf(typeRef) + && !MAP_TYPE.isSupertypeOf(typeRef); if (maybe) { return Descriptor.getDescriptors(cls).stream() .allMatch( d -> { - TypeToken t = d.getTypeToken(); + TypeRef t = d.getTypeRef(); // do field modifiers and getter/setter validation here, not in getDescriptors. // If Modifier.isFinal(d.getModifiers()), use reflection // private field that doesn't have getter/setter will be handled by reflection. @@ -590,13 +586,12 @@ private static boolean isBean(TypeToken typeToken, LinkedHashSet w } /** Check if typeToken is supported by row-format. */ - public static boolean isSupported(TypeToken typeToken) { - return isSupported(typeToken, new LinkedHashSet<>()); + public static boolean isSupported(TypeRef typeRef) { + return isSupported(typeRef, new LinkedHashSet<>()); } - private static boolean isSupported( - TypeToken typeToken, LinkedHashSet walkedTypePath) { - Class cls = getRawType(typeToken); + private static boolean isSupported(TypeRef typeRef, LinkedHashSet walkedTypePath) { + Class cls = getRawType(typeRef); if (!Modifier.isPublic(cls.getModifiers())) { return false; } @@ -605,33 +600,33 @@ private static boolean isSupported( // box. return true; } - if (SUPPORTED_TYPES.contains(typeToken)) { + if (SUPPORTED_TYPES.contains(typeRef)) { return true; - } else if (typeToken.isArray()) { - return isSupported(Objects.requireNonNull(typeToken.getComponentType())); - } else if (ITERABLE_TYPE.isSupertypeOf(typeToken)) { + } else if (typeRef.isArray()) { + return isSupported(Objects.requireNonNull(typeRef.getComponentType())); + } else if (ITERABLE_TYPE.isSupertypeOf(typeRef)) { boolean isSuperOfArrayList = cls.isAssignableFrom(ArrayList.class); boolean isSuperOfHashSet = cls.isAssignableFrom(HashSet.class); if ((!isSuperOfArrayList && !isSuperOfHashSet) && (cls.isInterface() || Modifier.isAbstract(cls.getModifiers()))) { return false; } - return isSupported(getElementType(typeToken)); - } else if (MAP_TYPE.isSupertypeOf(typeToken)) { + return isSupported(getElementType(typeRef)); + } else if (MAP_TYPE.isSupertypeOf(typeRef)) { boolean isSuperOfHashMap = cls.isAssignableFrom(HashMap.class); if (!isSuperOfHashMap && (cls.isInterface() || Modifier.isAbstract(cls.getModifiers()))) { return false; } - Tuple2, TypeToken> mapKeyValueType = getMapKeyValueType(typeToken); + Tuple2, TypeRef> mapKeyValueType = getMapKeyValueType(typeRef); return isSupported(mapKeyValueType.f0) && isSupported(mapKeyValueType.f1); } else { - if (walkedTypePath.contains(typeToken)) { + if (walkedTypePath.contains(typeRef)) { throw new UnsupportedOperationException( "cyclic type is not supported. walkedTypePath: " + walkedTypePath); } else { - LinkedHashSet newTypePath = new LinkedHashSet<>(walkedTypePath); - newTypePath.add(typeToken); - return isBean(typeToken, newTypePath); + LinkedHashSet newTypePath = new LinkedHashSet<>(walkedTypePath); + newTypePath.add(typeRef); + return isBean(typeRef, newTypePath); } } } @@ -648,20 +643,20 @@ public static LinkedHashSet> listBeansRecursiveInclusive(Class beanC } private static LinkedHashSet> listBeansRecursiveInclusive( - Class beanClass, LinkedHashSet> walkedTypePath) { + Class beanClass, LinkedHashSet> walkedTypePath) { LinkedHashSet> beans = new LinkedHashSet<>(); if (isBean(beanClass)) { beans.add(beanClass); } - LinkedHashSet> typeTokens = new LinkedHashSet<>(); + LinkedHashSet> typeRefs = new LinkedHashSet<>(); List descriptors = Descriptor.getDescriptors(beanClass); for (Descriptor descriptor : descriptors) { - TypeToken typeToken = descriptor.getTypeToken(); - typeTokens.add(descriptor.getTypeToken()); - typeTokens.addAll(getAllTypeArguments(typeToken)); + TypeRef typeRef = descriptor.getTypeRef(); + typeRefs.add(descriptor.getTypeRef()); + typeRefs.addAll(getAllTypeArguments(typeRef)); } - typeTokens.stream() + typeRefs.stream() .filter(typeToken -> isBean(getRawType(typeToken))) .forEach( typeToken -> { @@ -671,7 +666,7 @@ private static LinkedHashSet> listBeansRecursiveInclusive( throw new UnsupportedOperationException( "cyclic type is not supported. walkedTypePath: " + walkedTypePath); } else { - LinkedHashSet> newPath = new LinkedHashSet<>(walkedTypePath); + LinkedHashSet> newPath = new LinkedHashSet<>(walkedTypePath); newPath.add(typeToken); beans.addAll(listBeansRecursiveInclusive(cls, newPath)); } @@ -692,11 +687,11 @@ public static int computeStringHash(String str) { } /** Returns generic type arguments of typeToken. */ - public static List> getTypeArguments(TypeToken typeToken) { - if (typeToken.getType() instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) typeToken.getType(); + public static List> getTypeArguments(TypeRef typeRef) { + if (typeRef.getType() instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) typeRef.getType(); return Arrays.stream(parameterizedType.getActualTypeArguments()) - .map(TypeToken::of) + .map(TypeRef::of) .collect(Collectors.toList()); } else { return new ArrayList<>(); @@ -707,10 +702,10 @@ public static List> getTypeArguments(TypeToken typeToken) { * Returns generic type arguments of typeToken, includes generic type arguments of * generic type arguments recursively. */ - public static List> getAllTypeArguments(TypeToken typeToken) { - List> types = getTypeArguments(typeToken); - LinkedHashSet> allTypeArguments = new LinkedHashSet<>(types); - for (TypeToken type : types) { + public static List> getAllTypeArguments(TypeRef typeRef) { + List> types = getTypeArguments(typeRef); + LinkedHashSet> allTypeArguments = new LinkedHashSet<>(types); + for (TypeRef type : types) { allTypeArguments.addAll(getAllTypeArguments(type)); } diff --git a/java/fury-core/src/main/java/org/apache/fury/util/ReflectionUtils.java b/java/fury-core/src/main/java/org/apache/fury/util/ReflectionUtils.java index f5e7ee8db5..b78393fc3b 100644 --- a/java/fury-core/src/main/java/org/apache/fury/util/ReflectionUtils.java +++ b/java/fury-core/src/main/java/org/apache/fury/util/ReflectionUtils.java @@ -22,7 +22,6 @@ import static org.apache.fury.type.TypeUtils.OBJECT_TYPE; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -49,6 +48,7 @@ import org.apache.fury.annotation.Internal; import org.apache.fury.collection.Tuple3; import org.apache.fury.memory.Platform; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.function.Functions; import org.apache.fury.util.unsafe._JDKAccess; @@ -456,7 +456,7 @@ public static String getClassNameWithoutPackage(String className) { } } - public static boolean isPublic(TypeToken targetType) { + public static boolean isPublic(TypeRef targetType) { return Modifier.isPublic(getRawType(targetType).getModifiers()); } @@ -464,7 +464,7 @@ public static boolean isPublic(Class type) { return Modifier.isPublic(type.getModifiers()); } - public static boolean isPrivate(TypeToken targetType) { + public static boolean isPrivate(TypeRef targetType) { return Modifier.isPrivate(getRawType(targetType).getModifiers()); } @@ -488,9 +488,9 @@ public static boolean isMonomorphic(Class targetType) { return Modifier.isFinal(targetType.getModifiers()); } - public static TypeToken getPublicSuperType(TypeToken typeToken) { - if (!isPublic(typeToken)) { - Class rawType = Objects.requireNonNull(getRawType(typeToken)); + public static TypeRef getPublicSuperType(TypeRef typeRef) { + if (!isPublic(typeRef)) { + Class rawType = Objects.requireNonNull(getRawType(typeRef)); Class cls = rawType; while (cls != null && !isPublic(cls)) { cls = cls.getSuperclass(); @@ -498,15 +498,15 @@ public static TypeToken getPublicSuperType(TypeToken typeToken) { if (cls == null) { for (Class typeInterface : rawType.getInterfaces()) { if (isPublic(typeInterface)) { - return TypeToken.of(typeInterface); + return TypeRef.of(typeInterface); } } return OBJECT_TYPE; } else { - return TypeToken.of(cls); + return TypeRef.of(cls); } } else { - return typeToken; + return typeRef; } } diff --git a/java/fury-core/src/main/resources/META-INF/LICENSE b/java/fury-core/src/main/resources/META-INF/LICENSE index 4dcb88f8d8..83adf1aac1 100644 --- a/java/fury-core/src/main/resources/META-INF/LICENSE +++ b/java/fury-core/src/main/resources/META-INF/LICENSE @@ -217,6 +217,9 @@ The text of each license is the standard Apache 2.0 license. * guava (https://github.com/google/guava) Files: java/fury-core/src/main/java/org/apache/fury/util/Preconditions.java + java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java + java/fury-core/src/main/java/org/apache/fury/reflect/Types.java + java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java * spark (https://github.com/apache/spark) Files: diff --git a/java/fury-core/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties b/java/fury-core/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties index 4d8597f74b..4f4ddd71e5 100644 --- a/java/fury-core/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties +++ b/java/fury-core/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties @@ -173,4 +173,7 @@ Args=--initialize-at-build-time=org.apache.fury.memory.MemoryBuffer,\ org.apache.fury.meta.MetaString,\ org.apache.fury.meta.MetaStringDecoder$1,\ org.apache.fury.meta.MetaStringEncoder$1,\ - org.apache.fury.meta.MetaString$Encoding + org.apache.fury.meta.MetaString$Encoding,\ + org.apache.fury.reflect.Types$ClassOwnership,\ + org.apache.fury.reflect.Types$ClassOwnership$1,\ + org.apache.fury.reflect.Types$ClassOwnership$2 diff --git a/java/fury-core/src/test/java/org/apache/fury/FuryInitPerf.java b/java/fury-core/src/test/java/org/apache/fury/FuryInitPerf.java index 8cf5265224..55055c1c31 100644 --- a/java/fury-core/src/test/java/org/apache/fury/FuryInitPerf.java +++ b/java/fury-core/src/test/java/org/apache/fury/FuryInitPerf.java @@ -19,7 +19,6 @@ package org.apache.fury; -import com.google.common.reflect.TypeToken; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -27,6 +26,7 @@ import org.apache.fury.config.Language; import org.apache.fury.logging.Logger; import org.apache.fury.logging.LoggerFactory; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.resolver.MetaContext; import org.apache.fury.test.bean.BeanA; import org.apache.fury.test.bean.BeanB; @@ -66,7 +66,7 @@ public void testFuryInit() { interface Collection1 extends Collection {} public void testGenericsInit() { - TypeToken elementType = TypeUtils.getElementType(TypeToken.of(Collection1.class)); + TypeRef elementType = TypeUtils.getElementType(TypeRef.of(Collection1.class)); System.out.println(elementType); } diff --git a/java/fury-core/src/test/java/org/apache/fury/codegen/CodegenContextTest.java b/java/fury-core/src/test/java/org/apache/fury/codegen/CodegenContextTest.java index 38cbfcbcb7..feaf22b2b6 100644 --- a/java/fury-core/src/test/java/org/apache/fury/codegen/CodegenContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/codegen/CodegenContextTest.java @@ -19,10 +19,10 @@ package org.apache.fury.codegen; -import com.google.common.reflect.TypeToken; import java.util.List; import org.apache.fury.codegen.Expression.Invoke; import org.apache.fury.codegen.Expression.Literal; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.Serializer; import org.apache.fury.type.TypeUtils; import org.testng.Assert; @@ -36,14 +36,14 @@ public static class A { @Test public void type() { - TypeToken>> typeToken = new TypeToken>>() {}; + TypeRef>> typeRef = new TypeRef>>() {}; { CodegenContext ctx = new CodegenContext(); ctx.addImport(List.class); Assert.assertEquals("List", ctx.type(List.class)); } CodegenContext ctx = new CodegenContext(); - String type = ctx.type(typeToken); + String type = ctx.type(typeRef); Assert.assertEquals("java.util.List", type); Assert.assertEquals("int[][]", ctx.type(int[][].class)); } diff --git a/java/fury-core/src/test/java/org/apache/fury/codegen/ExpressionVisitorTest.java b/java/fury-core/src/test/java/org/apache/fury/codegen/ExpressionVisitorTest.java index e265c93ccf..4532be94d9 100644 --- a/java/fury-core/src/test/java/org/apache/fury/codegen/ExpressionVisitorTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/codegen/ExpressionVisitorTest.java @@ -21,7 +21,6 @@ import static org.testng.Assert.assertEquals; -import com.google.common.reflect.TypeToken; import java.lang.invoke.SerializedLambda; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,6 +28,7 @@ import java.util.Arrays; import java.util.List; import org.apache.fury.codegen.Expression.Literal; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.util.Preconditions; import org.apache.fury.util.ReflectionUtils; import org.testng.annotations.Test; @@ -38,7 +38,7 @@ public class ExpressionVisitorTest { @Test public void testTraverseExpression() throws InvocationTargetException, IllegalAccessException { Expression.Reference ref = - new Expression.Reference("a", TypeToken.of(ExpressionVisitorTest.class)); + new Expression.Reference("a", TypeRef.of(ExpressionVisitorTest.class)); Expression e1 = new Expression.Invoke(ref, "testTraverseExpression"); Literal start = Literal.ofInt(0); Literal end = Literal.ofInt(10); diff --git a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java index 6bfab8cecd..d7cd294455 100644 --- a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java @@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; -import com.google.common.reflect.TypeToken; import java.io.Serializable; import java.util.AbstractCollection; import java.util.ArrayDeque; @@ -62,6 +61,7 @@ import org.apache.fury.config.Language; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.MemoryUtils; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.collection.CollectionSerializers.JDKCompatibleCollectionSerializer; import org.apache.fury.type.GenericType; import org.testng.Assert; @@ -137,7 +137,7 @@ public void testCollectionGenerics(boolean referenceTrackingConfig) { .build(); List data = new ArrayList<>(ImmutableList.of("a", "b", "c")); byte[] bytes1 = fury.serialize(data); - fury.getGenerics().pushGenericType(GenericType.build(new TypeToken>() {})); + fury.getGenerics().pushGenericType(GenericType.build(new TypeRef>() {})); byte[] bytes2 = fury.serialize(data); Assert.assertTrue(bytes1.length > bytes2.length); assertEquals(fury.deserialize(bytes2), data); @@ -171,7 +171,7 @@ public void testSortedSet(boolean referenceTrackingConfig) { TreeSet data = new TreeSet<>(ImmutableSet.of("a", "b", "c")); serDeCheckSerializer(fury, data, "SortedSet"); byte[] bytes1 = fury.serialize(data); - fury.getGenerics().pushGenericType(GenericType.build(new TypeToken>() {})); + fury.getGenerics().pushGenericType(GenericType.build(new TypeRef>() {})); byte[] bytes2 = fury.serialize(data); Assert.assertTrue(bytes1.length > bytes2.length); fury.getGenerics().popGenericType(); diff --git a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java index 9b8c9a43e8..80e0a04455 100644 --- a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java @@ -26,7 +26,6 @@ import static org.testng.Assert.assertEquals; import com.google.common.collect.ImmutableMap; -import com.google.common.reflect.TypeToken; import java.io.Serializable; import java.util.AbstractMap; import java.util.ArrayList; @@ -49,6 +48,7 @@ import org.apache.fury.FuryTestBase; import org.apache.fury.collection.MapEntry; import org.apache.fury.config.Language; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.serializer.collection.CollectionSerializersTest.TestEnum; import org.apache.fury.test.bean.MapFields; import org.apache.fury.type.GenericType; @@ -94,7 +94,7 @@ public void testMapGenerics(boolean referenceTrackingConfig) { .build(); Map data = new HashMap<>(ImmutableMap.of("a", 1, "b", 2)); byte[] bytes1 = fury.serialize(data); - fury.getGenerics().pushGenericType(GenericType.build(new TypeToken>() {})); + fury.getGenerics().pushGenericType(GenericType.build(new TypeRef>() {})); byte[] bytes2 = fury.serialize(data); Assert.assertTrue(bytes1.length > bytes2.length); fury.getGenerics().popGenericType(); @@ -112,7 +112,7 @@ public void testSortedMap(boolean referenceTrackingConfig) { Map data = new TreeMap<>(ImmutableMap.of("a", 1, "b", 2)); serDeCheckSerializer(fury, data, "SortedMap"); byte[] bytes1 = fury.serialize(data); - fury.getGenerics().pushGenericType(GenericType.build(new TypeToken>() {})); + fury.getGenerics().pushGenericType(GenericType.build(new TypeRef>() {})); byte[] bytes2 = fury.serialize(data); Assert.assertTrue(bytes1.length > bytes2.length); fury.getGenerics().popGenericType(); diff --git a/java/fury-core/src/test/java/org/apache/fury/type/DescriptorGrouperTest.java b/java/fury-core/src/test/java/org/apache/fury/type/DescriptorGrouperTest.java index 69861f0f40..7eebdef093 100644 --- a/java/fury-core/src/test/java/org/apache/fury/type/DescriptorGrouperTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/type/DescriptorGrouperTest.java @@ -22,7 +22,6 @@ import static org.testng.Assert.*; import com.google.common.primitives.Primitives; -import com.google.common.reflect.TypeToken; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -32,6 +31,7 @@ import java.util.Map; import java.util.Random; import java.util.stream.Collectors; +import org.apache.fury.reflect.TypeRef; import org.testng.annotations.Test; @SuppressWarnings("UnstableApiUsage") @@ -41,13 +41,13 @@ private List createDescriptors() { List descriptors = new ArrayList<>(); int index = 0; for (Class aClass : Primitives.allPrimitiveTypes()) { - descriptors.add(new Descriptor(TypeToken.of(aClass), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(aClass), "f" + index++, -1, "TestClass")); } for (Class t : Primitives.allWrapperTypes()) { - descriptors.add(new Descriptor(TypeToken.of(t), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(t), "f" + index++, -1, "TestClass")); } - descriptors.add(new Descriptor(TypeToken.of(String.class), "f" + index++, -1, "TestClass")); - descriptors.add(new Descriptor(TypeToken.of(Object.class), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(String.class), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(Object.class), "f" + index++, -1, "TestClass")); Collections.shuffle(descriptors, new Random(17)); return descriptors; } @@ -88,7 +88,7 @@ public void testPrimitiveComparator() { List descriptors = new ArrayList<>(); int index = 0; for (Class aClass : Primitives.allPrimitiveTypes()) { - descriptors.add(new Descriptor(TypeToken.of(aClass), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(aClass), "f" + index++, -1, "TestClass")); } Collections.shuffle(descriptors, new Random(7)); descriptors.sort(DescriptorGrouper.getPrimitiveComparator(false, false)); @@ -113,7 +113,7 @@ public void testPrimitiveCompressedComparator() { List descriptors = new ArrayList<>(); int index = 0; for (Class aClass : Primitives.allPrimitiveTypes()) { - descriptors.add(new Descriptor(TypeToken.of(aClass), "f" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(aClass), "f" + index++, -1, "TestClass")); } Collections.shuffle(descriptors, new Random(7)); descriptors.sort(DescriptorGrouper.getPrimitiveComparator(true, true)); @@ -137,18 +137,17 @@ public void testPrimitiveCompressedComparator() { public void testGrouper() { List descriptors = createDescriptors(); int index = 0; - descriptors.add(new Descriptor(TypeToken.of(Object.class), "c" + index++, -1, "TestClass")); - descriptors.add(new Descriptor(TypeToken.of(Date.class), "c" + index++, -1, "TestClass")); - descriptors.add(new Descriptor(TypeToken.of(Instant.class), "c" + index++, -1, "TestClass")); - descriptors.add(new Descriptor(TypeToken.of(Instant.class), "c" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(Object.class), "c" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(Date.class), "c" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(Instant.class), "c" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(TypeRef.of(Instant.class), "c" + index++, -1, "TestClass")); + descriptors.add(new Descriptor(new TypeRef>() {}, "c" + index++, -1, "TestClass")); descriptors.add( - new Descriptor(new TypeToken>() {}, "c" + index++, -1, "TestClass")); + new Descriptor(new TypeRef>() {}, "c" + index++, -1, "TestClass")); descriptors.add( - new Descriptor(new TypeToken>() {}, "c" + index++, -1, "TestClass")); + new Descriptor(new TypeRef>() {}, "c" + index++, -1, "TestClass")); descriptors.add( - new Descriptor(new TypeToken>() {}, "c" + index++, -1, "TestClass")); - descriptors.add( - new Descriptor(new TypeToken>() {}, "c" + index++, -1, "TestClass")); + new Descriptor(new TypeRef>() {}, "c" + index++, -1, "TestClass")); DescriptorGrouper grouper = DescriptorGrouper.createDescriptorGrouper(descriptors, false, false, false); { @@ -188,22 +187,22 @@ public void testGrouper() { assertEquals(classes, expected); } { - List> types = + List> types = grouper.getCollectionDescriptors().stream() - .map(Descriptor::getTypeToken) + .map(Descriptor::getTypeRef) .collect(Collectors.toList()); - List> expected = - Arrays.asList(new TypeToken>() {}, new TypeToken>() {}); + List> expected = + Arrays.asList(new TypeRef>() {}, new TypeRef>() {}); assertEquals(types, expected); } { - List> types = + List> types = grouper.getMapDescriptors().stream() - .map(Descriptor::getTypeToken) + .map(Descriptor::getTypeRef) .collect(Collectors.toList()); - List> expected = + List> expected = Arrays.asList( - new TypeToken>() {}, new TypeToken>() {}); + new TypeRef>() {}, new TypeRef>() {}); assertEquals(types, expected); } { diff --git a/java/fury-core/src/test/java/org/apache/fury/type/DescriptorTest.java b/java/fury-core/src/test/java/org/apache/fury/type/DescriptorTest.java index 13c22f7383..cdc8d4bb29 100644 --- a/java/fury-core/src/test/java/org/apache/fury/type/DescriptorTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/type/DescriptorTest.java @@ -19,7 +19,6 @@ package org.apache.fury.type; -import com.google.common.reflect.TypeToken; import java.beans.IntrospectionException; import java.beans.Introspector; import java.lang.reflect.Field; @@ -28,6 +27,7 @@ import java.util.SortedMap; import java.util.stream.Collectors; import org.apache.fury.codegen.CodeGenerator; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.test.bean.BeanA; import org.testng.Assert; import org.testng.annotations.Test; @@ -49,8 +49,8 @@ public void testBuildBeanedDescriptorsMap() throws Exception { SortedMap map = Descriptor.buildBeanedDescriptorsMap(BeanA.class, true); Assert.assertTrue(map.containsKey(BeanA.class.getDeclaredField("f1"))); Assert.assertEquals( - map.get(BeanA.class.getDeclaredField("doubleList")).getTypeToken(), - new TypeToken>() {}); + map.get(BeanA.class.getDeclaredField("doubleList")).getTypeRef(), + new TypeRef>() {}); Assert.assertNotNull(map.get(BeanA.class.getDeclaredField("longStringField")).getReadMethod()); Assert.assertEquals( map.get(BeanA.class.getDeclaredField("longStringField")).getWriteMethod(), @@ -63,7 +63,7 @@ public void testBuildBeanedDescriptorsMap() throws Exception { @Test public void getDescriptorsTest() throws IntrospectionException { Class clz = BeanA.class; - TypeToken typeToken = TypeToken.of(clz); + TypeRef typeRef = TypeRef.of(clz); // sort to fix field order List descriptors = Arrays.stream(Introspector.getBeanInfo(clz).getPropertyDescriptors()) @@ -72,8 +72,8 @@ public void getDescriptorsTest() throws IntrospectionException { .filter(d -> d.getReadMethod() != null && d.getWriteMethod() != null) .map( p -> { - TypeToken returnType = typeToken.method(p.getReadMethod()).getReturnType(); - return Arrays.asList( + TypeRef returnType = TypeRef.of(p.getReadMethod().getReturnType()); + return Arrays.asList( p.getName(), returnType, p.getReadMethod().getName(), diff --git a/java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java b/java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java index 6c856af008..c55dd820bd 100644 --- a/java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java @@ -247,7 +247,7 @@ public void testGenerics() throws NoSuchFieldException { GenericType genericType = GenericType.build(Test4.class, Test2.class.getField(fieldName).getGenericType()); GenericType genericType1 = generics.nextGenericType(); - Assert.assertEquals(genericType1.typeToken, genericType.typeToken); + Assert.assertEquals(genericType1.typeRef, genericType.typeRef); increaseFuryDepth(fury, -1); generics.popGenericType(); } diff --git a/java/fury-core/src/test/java/org/apache/fury/type/TypeUtilsTest.java b/java/fury-core/src/test/java/org/apache/fury/type/TypeUtilsTest.java index 342dc01c97..0dbd58519a 100644 --- a/java/fury-core/src/test/java/org/apache/fury/type/TypeUtilsTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/type/TypeUtilsTest.java @@ -22,7 +22,6 @@ import static org.testng.Assert.assertEquals; import com.google.common.collect.ImmutableList; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Type; import java.util.AbstractList; import java.util.ArrayList; @@ -34,8 +33,10 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import org.apache.fury.collection.Tuple2; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.test.bean.BeanA; import org.apache.fury.test.bean.BeanB; import org.testng.Assert; @@ -47,50 +48,57 @@ public class TypeUtilsTest { public void getArrayTypeTest() { assertEquals("int[][][][][]", TypeUtils.getArrayType(int[][][][][].class)); assertEquals("java.lang.Object[][][][][]", TypeUtils.getArrayType(Object[][][][][].class)); - assertEquals("int[][][][][]", TypeUtils.getArrayType(TypeToken.of(int[][][][][].class))); + assertEquals("int[][][][][]", TypeUtils.getArrayType(TypeRef.of(int[][][][][].class))); assertEquals( - "java.lang.Object[][][][][]", TypeUtils.getArrayType(TypeToken.of(Object[][][][][].class))); + "java.lang.Object[][][][][]", TypeUtils.getArrayType(TypeRef.of(Object[][][][][].class))); } @Test - public void getElementTypeTest() throws NoSuchMethodException { - TypeToken typeToken = - Descriptor.getDescriptorsMap(BeanA.class).get("doubleList").getTypeToken(); + public void getElementTypeTest() throws NoSuchMethodException, NoSuchFieldException { + TypeRef typeRef = Descriptor.getDescriptorsMap(BeanA.class).get("doubleList").getTypeRef(); + + assertEquals( + new TypeRef>() {}.resolveType( + Optional.class.getDeclaredField("value").getGenericType()), + TypeRef.of(String.class)); + assertEquals( + new TypeRef>() {}.resolveType( + List.class.getMethod("size").getGenericReturnType()) + .getRawType(), + int.class); @SuppressWarnings("unchecked") - TypeToken supertype = - ((TypeToken>) typeToken).getSupertype(Iterable.class); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Iterable.class); final Type iteratorReturnType = Iterable.class.getMethod("iterator").getGenericReturnType(); final Type nextReturnType = Iterator.class.getMethod("next").getGenericReturnType(); - assertEquals(supertype.resolveType(iteratorReturnType), new TypeToken>() {}); + assertEquals(supertype.resolveType(iteratorReturnType), new TypeRef>() {}); assertEquals( supertype.resolveType(iteratorReturnType).resolveType(nextReturnType), - new TypeToken() {}); + new TypeRef() {}); } @Test public void getSubclassElementTypeTest() { abstract class A implements Collection> {} Assert.assertEquals( - TypeUtils.getElementType(TypeToken.of(A.class)), new TypeToken>() {}); + TypeUtils.getElementType(TypeRef.of(A.class)), new TypeRef>() {}); } @Test public void getMapKeyValueTypeTest() throws NoSuchMethodException { - TypeToken typeToken = - Descriptor.getDescriptorsMap(BeanA.class).get("stringBeanBMap").getTypeToken(); + TypeRef typeRef = Descriptor.getDescriptorsMap(BeanA.class).get("stringBeanBMap").getTypeRef(); @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) typeToken).getSupertype(Map.class); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Map.class); final Type keySetReturnType = Map.class.getMethod("keySet").getGenericReturnType(); final Type valuesReturnType = Map.class.getMethod("values").getGenericReturnType(); - TypeToken keyType = TypeUtils.getElementType(supertype.resolveType(keySetReturnType)); - assertEquals(TypeToken.of(String.class), keyType); - TypeToken valueType = TypeUtils.getElementType(supertype.resolveType(valuesReturnType)); - assertEquals(TypeToken.of(BeanB.class), valueType); - Tuple2, TypeToken> mapKeyValueType = - TypeUtils.getMapKeyValueType(TypeToken.of(Map.class)); + TypeRef keyType = TypeUtils.getElementType(supertype.resolveType(keySetReturnType)); + assertEquals(TypeRef.of(String.class), keyType); + TypeRef valueType = TypeUtils.getElementType(supertype.resolveType(valuesReturnType)); + assertEquals(TypeRef.of(BeanB.class), valueType); + Tuple2, TypeRef> mapKeyValueType = + TypeUtils.getMapKeyValueType(TypeRef.of(Map.class)); System.out.println(mapKeyValueType); } @@ -133,7 +141,7 @@ public void isBean() { @Test public void isSupported() { - TypeUtils.isSupported(TypeToken.of(AbstractList.class)); + TypeUtils.isSupported(TypeRef.of(AbstractList.class)); } public static class A { @@ -151,28 +159,28 @@ public void checkMethodOverride() throws NoSuchMethodException { @Test public void testTypeConstruct() { - assertEquals(TypeUtils.arrayListOf(Integer.class), new TypeToken>() {}); - assertEquals(TypeUtils.listOf(Integer.class), new TypeToken>() {}); + assertEquals(TypeUtils.arrayListOf(Integer.class), new TypeRef>() {}); + assertEquals(TypeUtils.listOf(Integer.class), new TypeRef>() {}); assertEquals( - TypeUtils.mapOf(String.class, Integer.class), new TypeToken>() {}); + TypeUtils.mapOf(String.class, Integer.class), new TypeRef>() {}); assertEquals( TypeUtils.hashMapOf(String.class, Integer.class), - new TypeToken>() {}); + new TypeRef>() {}); } @Test public void testMapOf() { - TypeToken> mapTypeToken = TypeUtils.mapOf(String.class, Integer.class); - Assert.assertEquals(mapTypeToken, new TypeToken>() {}); + TypeRef> mapTypeRef = TypeUtils.mapOf(String.class, Integer.class); + Assert.assertEquals(mapTypeRef, new TypeRef>() {}); Assert.assertEquals( TypeUtils.mapOf(HashMap.class, String.class, Integer.class), - new TypeToken>() {}); + new TypeRef>() {}); Assert.assertEquals( TypeUtils.hashMapOf(String.class, Integer.class), - new TypeToken>() {}); + new TypeRef>() {}); Assert.assertEquals( TypeUtils.mapOf(LinkedHashMap.class, String.class, Integer.class), - new TypeToken>() {}); + new TypeRef>() {}); } @Test @@ -247,16 +255,16 @@ public void testGetRawType() throws NoSuchFieldException { @Test public void getTypeArguments() { - TypeToken>> typeToken = - new TypeToken>>() {}; - assertEquals(TypeUtils.getTypeArguments(typeToken).size(), 2); + TypeRef>> typeRef = + new TypeRef>>() {}; + assertEquals(TypeUtils.getTypeArguments(typeRef).size(), 2); } @Test public void getAllTypeArguments() { - TypeToken>> typeToken = - new TypeToken>>() {}; - List> allTypeArguments = TypeUtils.getAllTypeArguments(typeToken); + TypeRef>> typeRef = + new TypeRef>>() {}; + List> allTypeArguments = TypeUtils.getAllTypeArguments(typeRef); assertEquals(allTypeArguments.size(), 3); assertEquals(allTypeArguments.get(2).getRawType(), BeanA.class); } diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayDataForEach.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayDataForEach.java index 68c534cb9a..45d1f1baf3 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayDataForEach.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayDataForEach.java @@ -21,7 +21,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import org.apache.fury.annotation.Internal; import org.apache.fury.codegen.ClosureVisitable; import org.apache.fury.codegen.Code; @@ -30,6 +29,7 @@ import org.apache.fury.codegen.Expression; import org.apache.fury.format.row.binary.BinaryArray; import org.apache.fury.format.row.binary.BinaryUtils; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.Preconditions; import org.apache.fury.util.StringUtils; @@ -44,7 +44,7 @@ public class ArrayDataForEach implements Expression { private final Expression inputArrayData; private final String accessMethod; - private final TypeToken elemType; + private final TypeRef elemType; @ClosureVisitable private final SerializableBiFunction notNullAction; @@ -57,7 +57,7 @@ public class ArrayDataForEach implements Expression { */ public ArrayDataForEach( Expression inputArrayData, - TypeToken elemType, + TypeRef elemType, SerializableBiFunction notNullAction) { this(inputArrayData, elemType, notNullAction, null); } @@ -68,7 +68,7 @@ public ArrayDataForEach( */ public ArrayDataForEach( Expression inputArrayData, - TypeToken elemType, + TypeRef elemType, SerializableBiFunction notNullAction, SerializableFunction nullAction) { Preconditions.checkArgument(getRawType(inputArrayData.type()) == BinaryArray.class); @@ -80,7 +80,7 @@ public ArrayDataForEach( } @Override - public TypeToken type() { + public TypeRef type() { return TypeUtils.PRIMITIVE_VOID_TYPE; } diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayEncoderBuilder.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayEncoderBuilder.java index 62ff1fdb43..990beeccc2 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayEncoderBuilder.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/ArrayEncoderBuilder.java @@ -22,7 +22,6 @@ import static org.apache.fury.type.TypeUtils.CLASS_TYPE; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import org.apache.arrow.vector.types.pojo.Field; import org.apache.fury.Fury; import org.apache.fury.codegen.CodeGenerator; @@ -34,6 +33,7 @@ import org.apache.fury.format.type.TypeInference; import org.apache.fury.logging.Logger; import org.apache.fury.logging.LoggerFactory; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.StringUtils; @@ -44,14 +44,14 @@ public class ArrayEncoderBuilder extends BaseBinaryEncoderBuilder { private static final String ROOT_ARRAY_NAME = "array"; private static final String ROOT_ARRAY_WRITER_NAME = "arrayWriter"; - private static final TypeToken ARROW_FIELD_TYPE = TypeToken.of(Field.class); - private final TypeToken arrayToken; + private static final TypeRef ARROW_FIELD_TYPE = TypeRef.of(Field.class); + private final TypeRef arrayToken; public ArrayEncoderBuilder(Class arrayCls, Class beanClass) { - this(TypeToken.of(arrayCls), TypeToken.of(beanClass)); + this(TypeRef.of(arrayCls), TypeRef.of(beanClass)); } - public ArrayEncoderBuilder(TypeToken clsType, TypeToken beanType) { + public ArrayEncoderBuilder(TypeRef clsType, TypeRef beanType) { super(new CodegenContext(), beanType); arrayToken = clsType; ctx.reserveName(ROOT_ARRAY_WRITER_NAME); @@ -133,7 +133,7 @@ public Expression buildEncodeExpression() { expressions.add( new Expression.Return( - new Expression.Invoke(arrayWriter, "toArray", TypeToken.of(BinaryArray.class)))); + new Expression.Invoke(arrayWriter, "toArray", TypeRef.of(BinaryArray.class)))); return expressions; } @@ -155,7 +155,7 @@ public Expression buildDecodeExpression() { } private Expression deserializeForCollection( - Expression arrayData, Expression collection, TypeToken elemType) { + Expression arrayData, Expression collection, TypeRef elemType) { ArrayDataForEach addElemsOp = new ArrayDataForEach( arrayData, diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/BaseBinaryEncoderBuilder.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/BaseBinaryEncoderBuilder.java index 3d52a7aa3a..0a5251f7a8 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/BaseBinaryEncoderBuilder.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/BaseBinaryEncoderBuilder.java @@ -21,7 +21,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -63,6 +62,7 @@ import org.apache.fury.format.row.binary.writer.BinaryWriter; import org.apache.fury.format.type.DataTypes; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.DateTimeUtils; import org.apache.fury.util.Preconditions; @@ -73,31 +73,30 @@ @SuppressWarnings("UnstableApiUsage") public abstract class BaseBinaryEncoderBuilder extends CodecBuilder { protected static final String REFERENCES_NAME = "references"; - protected static final TypeToken SCHEMA_TYPE = TypeToken.of(Schema.class); - protected static final TypeToken ARROW_FIELD_TYPE = TypeToken.of(Field.class); - protected static TypeToken schemaTypeToken = TypeToken.of(Schema.class); - protected static TypeToken writerTypeToken = TypeToken.of(BinaryWriter.class); - protected static TypeToken rowWriterTypeToken = - TypeToken.of(BinaryRowWriter.class); - protected static TypeToken arrayWriterTypeToken = - TypeToken.of(BinaryArrayWriter.class); - protected static TypeToken rowTypeToken = TypeToken.of(Row.class); - protected static TypeToken binaryRowTypeToken = TypeToken.of(BinaryRow.class); - protected static TypeToken binaryArrayTypeToken = TypeToken.of(BinaryArray.class); - - protected final Map, Reference> arrayWriterMap = new HashMap<>(); - protected final Map, Reference> beanEncoderMap = new HashMap<>(); + protected static final TypeRef SCHEMA_TYPE = TypeRef.of(Schema.class); + protected static final TypeRef ARROW_FIELD_TYPE = TypeRef.of(Field.class); + protected static TypeRef schemaTypeToken = TypeRef.of(Schema.class); + protected static TypeRef writerTypeToken = TypeRef.of(BinaryWriter.class); + protected static TypeRef rowWriterTypeToken = TypeRef.of(BinaryRowWriter.class); + protected static TypeRef arrayWriterTypeToken = + TypeRef.of(BinaryArrayWriter.class); + protected static TypeRef rowTypeToken = TypeRef.of(Row.class); + protected static TypeRef binaryRowTypeToken = TypeRef.of(BinaryRow.class); + protected static TypeRef binaryArrayTypeToken = TypeRef.of(BinaryArray.class); + + protected final Map, Reference> arrayWriterMap = new HashMap<>(); + protected final Map, Reference> beanEncoderMap = new HashMap<>(); // We need to call beanEncoder's rowWriter.reset() before write a corresponding nested bean every // time. // Outermost beanEncoder's rowWriter.reset() should be called outside generated code before // writer an outermost bean every time. - protected final Map, Reference> rowWriterMap = new HashMap<>(); + protected final Map, Reference> rowWriterMap = new HashMap<>(); public BaseBinaryEncoderBuilder(CodegenContext context, Class beanClass) { - this(context, TypeToken.of(beanClass)); + this(context, TypeRef.of(beanClass)); } - public BaseBinaryEncoderBuilder(CodegenContext context, TypeToken beanType) { + public BaseBinaryEncoderBuilder(CodegenContext context, TypeRef beanType) { super(context, beanType); ctx.reserveName(REFERENCES_NAME); @@ -140,9 +139,9 @@ protected Expression serializeFor( Expression ordinal, Expression inputObject, Expression writer, - TypeToken typeToken, + TypeRef typeRef, Expression arrowField) { - Class rawType = getRawType(typeToken); + Class rawType = getRawType(typeRef); if (TypeUtils.isPrimitive(rawType)) { return new ListExpression( // notNull is by default, no need to call setNotNullAt @@ -153,7 +152,7 @@ protected Expression serializeFor( } else if (rawType == BigDecimal.class) { return setValueOrNull(writer, ordinal, inputObject, inputObject); } else if (rawType == java.math.BigInteger.class) { - Invoke value = new Invoke(inputObject, "toByteArray", TypeToken.of(byte[].class)); + Invoke value = new Invoke(inputObject, "toByteArray", TypeRef.of(byte[].class)); return setValueOrNull(writer, ordinal, inputObject, value); } else if (rawType == java.time.LocalDate.class) { StaticInvoke value = @@ -196,13 +195,13 @@ protected Expression serializeFor( } else if (rawType.isEnum()) { Invoke value = new Invoke(inputObject, "name", TypeUtils.STRING_TYPE); return setValueOrNull(writer, ordinal, inputObject, value); - } else if (rawType.isArray() || TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeToken)) { + } else if (rawType.isArray() || TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)) { // place outer writer operations here, because map key/value arrays need to call // serializeForArray, // but don't setOffsetAndSize for array. Invoke offset = new Invoke(writer, "writerIndex", "writerIndex", TypeUtils.PRIMITIVE_INT_TYPE); - Expression serializeArray = serializeForArray(inputObject, writer, typeToken, arrowField); + Expression serializeArray = serializeForArray(inputObject, writer, typeRef, arrowField); Arithmetic size = ExpressionUtils.subtract( new Invoke(writer, "writerIndex", "writerIndex", TypeUtils.PRIMITIVE_INT_TYPE), @@ -214,10 +213,10 @@ protected Expression serializeFor( ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt", ordinal), expression); - } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeToken)) { - return serializeForMap(ordinal, writer, inputObject, typeToken, arrowField); + } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) { + return serializeForMap(ordinal, writer, inputObject, typeRef, arrowField); } else if (TypeUtils.isBean(rawType)) { - return serializeForBean(ordinal, writer, inputObject, typeToken, arrowField); + return serializeForBean(ordinal, writer, inputObject, typeRef, arrowField); } else { return serializeForObject(ordinal, writer, inputObject); } @@ -228,21 +227,21 @@ protected Expression serializeFor( * as {@link BinaryArray} using given writer. */ protected Expression serializeForArray( - Expression inputObject, Expression writer, TypeToken typeToken, Expression arrowField) { - return serializeForArray(inputObject, writer, typeToken, arrowField, false); + Expression inputObject, Expression writer, TypeRef typeRef, Expression arrowField) { + return serializeForArray(inputObject, writer, typeRef, arrowField, false); } protected Expression serializeForArray( Expression inputObject, Expression writer, - TypeToken typeToken, + TypeRef typeRef, Expression arrowField, boolean reuse) { - Reference arrayWriter = getOrCreateArrayWriter(typeToken, arrowField, writer, reuse); + Reference arrayWriter = getOrCreateArrayWriter(typeRef, arrowField, writer, reuse); StaticInvoke arrayElementField = new StaticInvoke( DataTypes.class, "arrayElementField", "elemField", ARROW_FIELD_TYPE, false, arrowField); - Class rawType = getRawType(typeToken); + Class rawType = getRawType(typeRef); if (rawType.isArray()) { FieldValue length = new FieldValue(inputObject, "length", TypeUtils.PRIMITIVE_INT_TYPE); Invoke reset = new Invoke(arrayWriter, "reset", length); @@ -258,11 +257,11 @@ protected Expression serializeForArray( i, value, arrayWriter, - Objects.requireNonNull(typeToken.getComponentType()), + Objects.requireNonNull(typeRef.getComponentType()), arrayElementField)); return new ListExpression(reset, forEach, arrayWriter); } - } else if (getRawType(typeToken) == Iterable.class) { + } else if (getRawType(typeRef) == Iterable.class) { ListFromIterable listFromIterable = new ListFromIterable(inputObject); Invoke size = new Invoke(listFromIterable, "size", TypeUtils.PRIMITIVE_INT_TYPE); Invoke reset = new Invoke(arrayWriter, "reset", size); @@ -271,11 +270,7 @@ protected Expression serializeForArray( listFromIterable, (i, value) -> serializeFor( - i, - value, - arrayWriter, - TypeUtils.getElementType(typeToken), - arrayElementField)); + i, value, arrayWriter, TypeUtils.getElementType(typeRef), arrayElementField)); return new ListExpression(reset, forEach, arrayWriter); } else { // collection Invoke size = new Invoke(inputObject, "size", TypeUtils.PRIMITIVE_INT_TYPE); @@ -285,11 +280,7 @@ protected Expression serializeForArray( inputObject, (i, value) -> serializeFor( - i, - value, - arrayWriter, - TypeUtils.getElementType(typeToken), - arrayElementField)); + i, value, arrayWriter, TypeUtils.getElementType(typeRef), arrayElementField)); return new ListExpression(reset, forEach, arrayWriter); } } @@ -299,18 +290,18 @@ protected Expression serializeForArray( * writer. */ protected Reference getOrCreateArrayWriter( - TypeToken typeToken, Expression arrayDataType, Expression writer) { - return getOrCreateArrayWriter(typeToken, arrayDataType, writer, false); + TypeRef typeRef, Expression arrayDataType, Expression writer) { + return getOrCreateArrayWriter(typeRef, arrayDataType, writer, false); } protected Reference getOrCreateArrayWriter( - TypeToken typeToken, Expression arrayDataType, Expression writer, boolean reuse) { + TypeRef typeRef, Expression arrayDataType, Expression writer, boolean reuse) { if (reuse) { return (Reference) writer; } return arrayWriterMap.computeIfAbsent( - typeToken, + typeRef, t -> { String name = ctx.newName("arrayWriter"); ctx.addField( @@ -329,7 +320,7 @@ protected Expression serializeForMap( Expression ordinal, Expression writer, Expression inputObject, - TypeToken typeToken, + TypeRef typeRef, Expression arrowField) { StaticInvoke keyArrayField = new StaticInvoke( @@ -349,9 +340,9 @@ protected Expression serializeForMap( arrowField); @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) typeToken).getSupertype(Map.class); - TypeToken keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); - TypeToken valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Map.class); + TypeRef keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); + TypeRef valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); Invoke keySet = new Invoke(inputObject, "keySet", keySetType); Expression keySerializationExpr = serializeForArray(keySet, writer, keySetType, keyArrayField); @@ -396,11 +387,11 @@ protected Expression serializeForBean( Expression ordinal, Expression writer, Expression inputObject, - TypeToken typeToken, + TypeRef typeRef, Expression structField) { - Class rawType = getRawType(typeToken); + Class rawType = getRawType(typeRef); Reference rowWriter; - Reference beanEncoder = beanEncoderMap.get(typeToken); + Reference beanEncoder = beanEncoderMap.get(typeRef); if (beanEncoder == null) { // janino generics don't add cast, so this `<${type}>` is only for generated code readability StaticInvoke schema = @@ -414,20 +405,20 @@ protected Expression serializeForBean( Preconditions.checkArgument(!codecClassName(rawType).contains(".")); String encoderName = ctx.newName(StringUtils.uncapitalize(codecClassName(rawType))); String encoderClass = codecQualifiedClassName(rawType); - TypeToken codecTypeToken = TypeToken.of(GeneratedRowEncoder.class); + TypeRef codecTypeRef = TypeRef.of(GeneratedRowEncoder.class); NewInstance newEncoder = new NewInstance( - codecTypeToken, + codecTypeRef, encoderClass, ExpressionUtils.newObjectArray(schema, newRowWriter, furyRef)); ctx.addField(encoderClass, encoderName, newEncoder); rowWriter = new Reference(rowWriterName, rowWriterTypeToken); - rowWriterMap.put(typeToken, rowWriter); - beanEncoder = new Reference(encoderName, codecTypeToken); - beanEncoderMap.put(typeToken, beanEncoder); + rowWriterMap.put(typeRef, rowWriter); + beanEncoder = new Reference(encoderName, codecTypeRef); + beanEncoderMap.put(typeRef, beanEncoder); } - rowWriter = rowWriterMap.get(typeToken); + rowWriter = rowWriterMap.get(typeRef); Invoke reset = new Invoke(rowWriter, "reset"); Invoke offset = new Invoke(writer, "writerIndex", "writerIndex", TypeUtils.PRIMITIVE_INT_TYPE); @@ -451,12 +442,12 @@ protected Expression serializeForBean( /** * Return an expression to serialize opaque inputObject as binary using fury * . When deserialization, using fury to deserialize sliced MemoryBuffer. See {@link - * BinaryUtils#getElemAccessMethodName(TypeToken)}, {@link Getters#getBuffer(int)} + * BinaryUtils#getElemAccessMethodName(TypeRef)}, {@link Getters#getBuffer(int)} */ protected Expression serializeForObject( Expression ordinal, Expression writer, Expression inputObject) { Invoke offset = new Invoke(writer, "writerIndex", "writerIndex", TypeUtils.PRIMITIVE_INT_TYPE); - Invoke buffer = new Invoke(writer, "getBuffer", "buffer", TypeToken.of(MemoryBuffer.class)); + Invoke buffer = new Invoke(writer, "getBuffer", "buffer", TypeRef.of(MemoryBuffer.class)); Expression setWriterIndex = new Invoke(buffer, "writerIndex", offset); Invoke serialize = new Invoke(furyRef, "serialize", buffer, inputObject); Invoke newWriterIndex = @@ -488,8 +479,8 @@ protected Expression setValueOrNull( * Returns an expression that deserialize value as a java object of type * typeToken. */ - protected Expression deserializeFor(Expression value, TypeToken typeToken) { - Class rawType = getRawType(typeToken); + protected Expression deserializeFor(Expression value, TypeRef typeRef) { + Class rawType = getRawType(typeRef); if (TypeUtils.isPrimitive(rawType) || TypeUtils.isBoxed(rawType)) { return value; } else if (rawType == BigDecimal.class) { @@ -510,17 +501,17 @@ protected Expression deserializeFor(Expression value, TypeToken typeToken) { } else if (rawType == String.class) { return value; } else if (rawType.isEnum()) { - return ExpressionUtils.valueOf(typeToken, value); + return ExpressionUtils.valueOf(typeRef, value); } else if (rawType.isArray()) { - return deserializeForArray(value, typeToken); - } else if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeToken)) { - return deserializeForCollection(value, typeToken); - } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeToken)) { - return deserializeForMap(value, typeToken); + return deserializeForArray(value, typeRef); + } else if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)) { + return deserializeForCollection(value, typeRef); + } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) { + return deserializeForMap(value, typeRef); } else if (TypeUtils.isBean(rawType)) { - return deserializeForBean(value, typeToken); + return deserializeForBean(value, typeRef); } else { - return deserializeForObject(value, typeToken); + return deserializeForObject(value, typeRef); } } @@ -528,23 +519,23 @@ protected Expression deserializeFor(Expression value, TypeToken typeToken) { * Returns an expression that deserialize row as a java bean of type typeToken * . */ - protected Expression deserializeForBean(Expression row, TypeToken typeToken) { - Reference beanEncoder = beanEncoderMap.get(typeToken); + protected Expression deserializeForBean(Expression row, TypeRef typeRef) { + Reference beanEncoder = beanEncoderMap.get(typeRef); if (beanEncoder == null) { throw new IllegalStateException("beanEncoder should have be added in serializeForBean()"); } Invoke beanObj = new Invoke(beanEncoder, "fromRow", TypeUtils.OBJECT_TYPE, false, row); - return new Cast(beanObj, typeToken, "bean"); + return new Cast(beanObj, typeRef, "bean"); } /** Returns an expression that deserialize mapData as a java map. */ - protected Expression deserializeForMap(Expression mapData, TypeToken typeToken) { - Expression javaMap = newMap(typeToken); + protected Expression deserializeForMap(Expression mapData, TypeRef typeRef) { + Expression javaMap = newMap(typeRef); @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) typeToken).getSupertype(Map.class); - TypeToken keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); - TypeToken keysType = TypeUtils.getCollectionType(keySetType); - TypeToken valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); + TypeRef supertype = ((TypeRef>) typeRef).getSupertype(Map.class); + TypeRef keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); + TypeRef keysType = TypeUtils.getCollectionType(keySetType); + TypeRef valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); Expression keyArray = new Invoke(mapData, "keyArray", binaryArrayTypeToken, false); Expression valueArray = new Invoke(mapData, "valueArray", binaryArrayTypeToken, false); Expression keyJavaArray; @@ -570,10 +561,10 @@ protected Expression deserializeForMap(Expression mapData, TypeToken typeToke } /** Returns an expression that deserialize arrayData as a java collection. */ - protected Expression deserializeForCollection(Expression arrayData, TypeToken typeToken) { - Expression collection = newCollection(typeToken); + protected Expression deserializeForCollection(Expression arrayData, TypeRef typeRef) { + Expression collection = newCollection(typeRef); try { - TypeToken elemType = TypeUtils.getElementType(typeToken); + TypeRef elemType = TypeUtils.getElementType(typeRef); ArrayDataForEach addElemsOp = new ArrayDataForEach( arrayData, @@ -591,19 +582,19 @@ protected Expression deserializeForCollection(Expression arrayData, TypeToken * of {@link ArrayList}; Create a {@link HashSet} if typeToken is super class of * {@link HashSet}; Create an instance of typeToken otherwise. */ - protected Expression newCollection(TypeToken typeToken) { - Class clazz = getRawType(typeToken); + protected Expression newCollection(TypeRef typeRef) { + Class clazz = getRawType(typeRef); Expression collection; - if (TypeToken.of(clazz).isSupertypeOf(TypeToken.of(ArrayList.class))) { - collection = new NewInstance(TypeToken.of(ArrayList.class)); - } else if (TypeToken.of(clazz).isSupertypeOf(TypeToken.of(HashSet.class))) { - collection = new NewInstance(TypeToken.of(HashSet.class)); + if (TypeRef.of(clazz).isSupertypeOf(TypeRef.of(ArrayList.class))) { + collection = new NewInstance(TypeRef.of(ArrayList.class)); + } else if (TypeRef.of(clazz).isSupertypeOf(TypeRef.of(HashSet.class))) { + collection = new NewInstance(TypeRef.of(HashSet.class)); } else { if (ReflectionUtils.isAbstract(clazz) || clazz.isInterface()) { String msg = String.format("class %s can't be abstract or interface", clazz); throw new UnsupportedOperationException(msg); } - collection = new NewInstance(typeToken); + collection = new NewInstance(typeRef); } return collection; } @@ -612,18 +603,18 @@ protected Expression newCollection(TypeToken typeToken) { * Create a java map. Create a {@link HashMap} if typeToken is super class of * HashMap; Create an instance of typeToken otherwise. */ - protected Expression newMap(TypeToken typeToken) { - Class clazz = getRawType(typeToken); + protected Expression newMap(TypeRef typeRef) { + Class clazz = getRawType(typeRef); Expression javaMap; // use TypeToken.of(clazz) rather typeToken to strip generics. - if (TypeToken.of(clazz).isSupertypeOf(TypeToken.of(HashMap.class))) { - javaMap = new NewInstance(TypeToken.of(HashMap.class)); + if (TypeRef.of(clazz).isSupertypeOf(TypeRef.of(HashMap.class))) { + javaMap = new NewInstance(TypeRef.of(HashMap.class)); } else { if (ReflectionUtils.isAbstract(clazz) || clazz.isInterface()) { String msg = String.format("class %s can't be abstract or interface", clazz); throw new UnsupportedOperationException(msg); } - javaMap = new NewInstance(typeToken); + javaMap = new NewInstance(typeRef); } return javaMap; } @@ -636,11 +627,11 @@ protected Expression deserializeForMultiDimensionArray( Expression arrayData, Expression rootJavaArray, int numDimensions, - TypeToken typeToken, + TypeRef typeRef, Expression[] indexes) { Preconditions.checkArgument(numDimensions > 1); - Preconditions.checkArgument(typeToken.isArray()); - TypeToken elemType = typeToken.getComponentType(); + Preconditions.checkArgument(typeRef.isArray()); + TypeRef elemType = typeRef.getComponentType(); if (numDimensions == 2) { return new ArrayDataForEach( arrayData, @@ -649,7 +640,7 @@ protected Expression deserializeForMultiDimensionArray( Expression[] newIndexes = Arrays.copyOf(indexes, indexes.length + 1); newIndexes[indexes.length] = i; Expression elemArr = - deserializeForArray(value, Objects.requireNonNull(typeToken.getComponentType())); + deserializeForArray(value, Objects.requireNonNull(typeRef.getComponentType())); return new AssignArrayElem(rootJavaArray, elemArr, newIndexes); }); } else { @@ -669,8 +660,8 @@ protected Expression deserializeForMultiDimensionArray( * Return an expression that deserialize arrayData. If array is multi-array, forward * to {@link BaseBinaryEncoderBuilder#deserializeForMultiDimensionArray} */ - protected Expression deserializeForArray(Expression arrayData, TypeToken typeToken) { - int numDimensions = TypeUtils.getArrayDimensions(typeToken); + protected Expression deserializeForArray(Expression arrayData, TypeRef typeRef) { + int numDimensions = TypeUtils.getArrayDimensions(typeRef); if (numDimensions > 1) { // If some dimension's elements is all null, we take outer-most array as null, // and don't create multi-array. return an no-ops expression or return null. @@ -679,16 +670,16 @@ protected Expression deserializeForArray(Expression arrayData, TypeToken type BinaryArray.class, "getDimensions", "dims", - TypeToken.of(int[].class), + TypeRef.of(int[].class), true, arrayData, new Literal(numDimensions, TypeUtils.INT_TYPE)); - TypeToken innerElemType = TypeUtils.getMultiDimensionArrayElementType(typeToken); + TypeRef innerElemType = TypeUtils.getMultiDimensionArrayElementType(typeRef); Class innerElemClass = getRawType(innerElemType); Expression rootJavaMultiDimArray = new NewArray(innerElemClass, numDimensions, dimensions); Expression op = deserializeForMultiDimensionArray( - arrayData, rootJavaMultiDimArray, numDimensions, typeToken, new Expression[0]); + arrayData, rootJavaMultiDimArray, numDimensions, typeRef, new Expression[0]); // although the value maybe null, we don't use this info, so we set nullability to false. return new If( ExpressionUtils.notNull(dimensions), @@ -696,7 +687,7 @@ protected Expression deserializeForArray(Expression arrayData, TypeToken type ExpressionUtils.nullValue(rootJavaMultiDimArray.type()), false); } else { - TypeToken elemType = typeToken.getComponentType(); + TypeRef elemType = typeRef.getComponentType(); Class innerElemClass = getRawType(Objects.requireNonNull(elemType)); if (byte.class == innerElemClass) { return new Invoke(arrayData, "toByteArray", TypeUtils.PRIMITIVE_BYTE_ARRAY_TYPE); @@ -731,9 +722,9 @@ protected Expression deserializeForArray(Expression arrayData, TypeToken type /** * Using fury to deserialize sliced MemoryBuffer. see {@link - * BinaryUtils#getElemAccessMethodName(TypeToken)}, {@link Getters#getBuffer(int)} + * BinaryUtils#getElemAccessMethodName(TypeRef)}, {@link Getters#getBuffer(int)} */ - protected Expression deserializeForObject(Expression value, TypeToken typeToken) { - return new Invoke(furyRef, "deserialize", typeToken, value); + protected Expression deserializeForObject(Expression value, TypeRef typeRef) { + return new Invoke(furyRef, "deserialize", typeRef, value); } } diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/Encoders.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/Encoders.java index df9090009e..ea2329dfb2 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/Encoders.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/Encoders.java @@ -21,7 +21,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.util.Collection; import java.util.HashSet; import java.util.Map; @@ -45,6 +44,7 @@ import org.apache.fury.logging.LoggerFactory; import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.MemoryUtils; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; /** @@ -191,27 +191,27 @@ public byte[] encode(T obj) { * @param T is a array type, can be a nested list type. * @return */ - public static ArrayEncoder arrayEncoder(TypeToken token) { + public static ArrayEncoder arrayEncoder(TypeRef token) { return arrayEncoder(token, (Fury) null); } - public static ArrayEncoder arrayEncoder(TypeToken token, Fury fury) { + public static ArrayEncoder arrayEncoder(TypeRef token, Fury fury) { Schema schema = TypeInference.inferSchema(token, false); Field field = DataTypes.fieldOfSchema(schema, 0); BinaryArrayWriter writer = new BinaryArrayWriter(field); - Set> set = new HashSet<>(); + Set> set = new HashSet<>(); findBeanToken(token, set); if (set.isEmpty()) { throw new IllegalArgumentException("can not find bean class."); } - TypeToken typeToken = null; - for (TypeToken tt : set) { - typeToken = set.iterator().next(); + TypeRef typeRef = null; + for (TypeRef tt : set) { + typeRef = set.iterator().next(); Encoders.loadOrGenRowCodecClass(getRawType(tt)); } - ArrayEncoder encoder = arrayEncoder(token, typeToken, writer, fury); + ArrayEncoder encoder = arrayEncoder(token, typeRef, writer, fury); return new ArrayEncoder() { @Override @@ -266,8 +266,8 @@ public static ArrayEncoder arrayEncoder( * java bean. */ public static ArrayEncoder arrayEncoder( - TypeToken arrayToken, - TypeToken elementType, + TypeRef arrayToken, + TypeRef elementType, BinaryArrayWriter writer, Fury fury) { Field field = writer.getField(); @@ -328,7 +328,7 @@ public byte[] encode(T obj) { * @param T is a array type, can be a nested list type. * @return */ - public static MapEncoder mapEncoder(TypeToken token) { + public static MapEncoder mapEncoder(TypeRef token) { return mapEncoder(token, (Fury) null); } @@ -346,21 +346,21 @@ public static MapEncoder mapEncoder( return (MapEncoder) mapEncoder(TypeUtils.mapOf(keyType, valueType), null); } - public static MapEncoder mapEncoder(TypeToken token, Fury fury) { + public static MapEncoder mapEncoder(TypeRef token, Fury fury) { Preconditions.checkNotNull(token); - Tuple2, TypeToken> tuple2 = TypeUtils.getMapKeyValueType(token); + Tuple2, TypeRef> tuple2 = TypeUtils.getMapKeyValueType(token); - Set> set1 = beanSet(tuple2.f0); - Set> set2 = beanSet(tuple2.f1); + Set> set1 = beanSet(tuple2.f0); + Set> set2 = beanSet(tuple2.f1); LOG.info("Find beans to load: {}, {}", set1, set2); if (set1.isEmpty() && set2.isEmpty()) { throw new IllegalArgumentException("can not find bean class."); } - TypeToken keyToken = token4BeanLoad(set1, tuple2.f0); - TypeToken valToken = token4BeanLoad(set2, tuple2.f1); + TypeRef keyToken = token4BeanLoad(set1, tuple2.f0); + TypeRef valToken = token4BeanLoad(set2, tuple2.f1); MapEncoder encoder = mapEncoder(token, keyToken, valToken, fury); return createMapEncoder(encoder); @@ -378,7 +378,7 @@ public static MapEncoder mapEncoder(TypeToken token, Fury * java bean. */ public static MapEncoder mapEncoder( - TypeToken mapToken, TypeToken keyToken, TypeToken valToken, Fury fury) { + TypeRef mapToken, TypeRef keyToken, TypeRef valToken, Fury fury) { Preconditions.checkNotNull(mapToken); Preconditions.checkNotNull(keyToken); Preconditions.checkNotNull(valToken); @@ -441,8 +441,8 @@ public byte[] encode(T obj) { } } - private static Set> beanSet(TypeToken token) { - Set> set = new HashSet<>(); + private static Set> beanSet(TypeRef token) { + Set> set = new HashSet<>(); if (TypeUtils.isBean(token)) { set.add(token); return set; @@ -451,9 +451,9 @@ private static Set> beanSet(TypeToken token) { return set; } - private static TypeToken token4BeanLoad(Set> set, TypeToken init) { - TypeToken keyToken = init; - for (TypeToken tt : set) { + private static TypeRef token4BeanLoad(Set> set, TypeRef init) { + TypeRef keyToken = init; + for (TypeRef tt : set) { keyToken = tt; Encoders.loadOrGenRowCodecClass(getRawType(tt)); LOG.info("bean {} load finished", getRawType(tt)); @@ -496,27 +496,27 @@ public byte[] encode(T obj) { }; } - private static void findBeanToken(TypeToken typeToken, java.util.Set> set) { - while (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeToken) - || TypeUtils.MAP_TYPE.isSupertypeOf(typeToken)) { - if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeToken)) { - typeToken = TypeUtils.getElementType(typeToken); - if (TypeUtils.isBean(typeToken)) { - set.add(typeToken); + private static void findBeanToken(TypeRef typeRef, java.util.Set> set) { + while (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef) + || TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) { + if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)) { + typeRef = TypeUtils.getElementType(typeRef); + if (TypeUtils.isBean(typeRef)) { + set.add(typeRef); } } else { - Tuple2, TypeToken> tuple2 = TypeUtils.getMapKeyValueType(typeToken); + Tuple2, TypeRef> tuple2 = TypeUtils.getMapKeyValueType(typeRef); if (TypeUtils.isBean(tuple2.f0)) { set.add(tuple2.f0); } else { - typeToken = tuple2.f0; + typeRef = tuple2.f0; findBeanToken(tuple2.f0, set); } if (TypeUtils.isBean(tuple2.f1)) { set.add(tuple2.f1); } else { - typeToken = tuple2.f1; + typeRef = tuple2.f1; findBeanToken(tuple2.f1, set); } } @@ -542,7 +542,7 @@ public static Class loadOrGenRowCodecClass(Class beanClass) { } private static Class loadOrGenArrayCodecClass( - TypeToken arrayCls, TypeToken elementType) { + TypeRef arrayCls, TypeRef elementType) { LOG.info("Create ArrayCodec for classes {}", elementType); Class cls = getRawType(elementType); // class name prefix @@ -559,11 +559,11 @@ private static Class loadOrGenArrayCodecClass( } private static Class loadOrGenMapCodecClass( - TypeToken mapCls, TypeToken keyToken, TypeToken valueToken) { + TypeRef mapCls, TypeRef keyToken, TypeRef valueToken) { LOG.info("Create MapCodec for classes {}, {}", keyToken, valueToken); boolean keyIsBean = TypeUtils.isBean(keyToken); boolean valIsBean = TypeUtils.isBean(valueToken); - TypeToken beanToken; + TypeRef beanToken; Class cls; if (keyIsBean) { cls = getRawType(keyToken); diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/MapEncoderBuilder.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/MapEncoderBuilder.java index c61a4ee4d5..cbd4fb526f 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/MapEncoderBuilder.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/MapEncoderBuilder.java @@ -22,7 +22,6 @@ import static org.apache.fury.type.TypeUtils.CLASS_TYPE; import static org.apache.fury.type.TypeUtils.getRawType; -import com.google.common.reflect.TypeToken; import java.util.Map; import org.apache.arrow.vector.types.pojo.Field; import org.apache.fury.Fury; @@ -36,6 +35,7 @@ import org.apache.fury.format.type.TypeInference; import org.apache.fury.logging.Logger; import org.apache.fury.logging.LoggerFactory; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.StringUtils; @@ -52,14 +52,14 @@ public class MapEncoderBuilder extends BaseBinaryEncoderBuilder { private static final String ROOT_KEY_WRITER_NAME = "keyArrayWriter"; private static final String ROOT_VALUE_WRITER_NAME = "valueArrayWriter"; - private static final TypeToken ARROW_FIELD_TYPE = TypeToken.of(Field.class); - private final TypeToken mapToken; + private static final TypeRef ARROW_FIELD_TYPE = TypeRef.of(Field.class); + private final TypeRef mapToken; public MapEncoderBuilder(Class mapCls, Class keyClass) { - this(TypeToken.of(mapCls), TypeToken.of(keyClass)); + this(TypeRef.of(mapCls), TypeRef.of(keyClass)); } - public MapEncoderBuilder(TypeToken clsType, TypeToken beanType) { + public MapEncoderBuilder(TypeRef clsType, TypeRef beanType) { super(new CodegenContext(), beanType); mapToken = clsType; ctx.reserveName(ROOT_KEY_WRITER_NAME); @@ -172,9 +172,9 @@ public Expression buildEncodeExpression() { directlySerializeMap(map, keyArrayWriter, valArrayWriter, keyFieldExpr, valFieldExpr); Expression.Invoke keyArray = - new Expression.Invoke(keyArrayWriter, "toArray", TypeToken.of(BinaryArray.class)); + new Expression.Invoke(keyArrayWriter, "toArray", TypeRef.of(BinaryArray.class)); Expression.Invoke valArray = - new Expression.Invoke(valArrayWriter, "toArray", TypeToken.of(BinaryArray.class)); + new Expression.Invoke(valArrayWriter, "toArray", TypeRef.of(BinaryArray.class)); expressions.add(map); expressions.add(listExpression); @@ -183,7 +183,7 @@ public Expression buildEncodeExpression() { expressions.add( new Expression.Return( new Expression.NewInstance( - TypeToken.of(BinaryMap.class), keyArray, valArray, fieldExpr))); + TypeRef.of(BinaryMap.class), keyArray, valArray, fieldExpr))); return expressions; } @@ -213,9 +213,9 @@ private Expression directlySerializeMap( Expression keyFieldExpr, Expression valFieldExpr) { @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) mapToken).getSupertype(Map.class); - TypeToken keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); - TypeToken valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); + TypeRef supertype = ((TypeRef>) mapToken).getSupertype(Map.class); + TypeRef keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); + TypeRef valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); Expression.Invoke keySet = new Expression.Invoke(map, "keySet", keySetType); Expression keySerializationExpr = @@ -231,10 +231,10 @@ private Expression directlySerializeMap( private Expression directlyDeserializeMap( Expression map, Expression keyArrayRef, Expression valArrayRef) { @SuppressWarnings("unchecked") - TypeToken supertype = ((TypeToken>) mapToken).getSupertype(Map.class); - TypeToken keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); - TypeToken keysType = TypeUtils.getCollectionType(keySetType); - TypeToken valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); + TypeRef supertype = ((TypeRef>) mapToken).getSupertype(Map.class); + TypeRef keySetType = supertype.resolveType(TypeUtils.KEY_SET_RETURN_TYPE); + TypeRef keysType = TypeUtils.getCollectionType(keySetType); + TypeRef valuesType = supertype.resolveType(TypeUtils.VALUES_RETURN_TYPE); Expression keyJavaArray; Expression valueJavaArray; if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(keysType)) { diff --git a/java/fury-format/src/main/java/org/apache/fury/format/encoder/RowEncoderBuilder.java b/java/fury-format/src/main/java/org/apache/fury/format/encoder/RowEncoderBuilder.java index 9c95b09769..6c71e00f73 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/encoder/RowEncoderBuilder.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/encoder/RowEncoderBuilder.java @@ -23,7 +23,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; import com.google.common.base.CaseFormat; -import com.google.common.reflect.TypeToken; import java.lang.reflect.Modifier; import java.util.SortedMap; import org.apache.arrow.vector.types.pojo.Field; @@ -48,6 +47,7 @@ import org.apache.fury.format.type.TypeInference; import org.apache.fury.logging.Logger; import org.apache.fury.logging.LoggerFactory; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.Descriptor; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.GraalvmSupport; @@ -68,10 +68,10 @@ public class RowEncoderBuilder extends BaseBinaryEncoderBuilder { protected Reference beanClassRef = new Reference(BEAN_CLASS_NAME, CLASS_TYPE); public RowEncoderBuilder(Class beanClass) { - this(TypeToken.of(beanClass)); + this(TypeRef.of(beanClass)); } - public RowEncoderBuilder(TypeToken beanType) { + public RowEncoderBuilder(TypeRef beanType) { super(new CodegenContext(), beanType); Preconditions.checkArgument(TypeUtils.isBean(beanType)); this.schema = TypeInference.inferSchema(getRawType(beanType)); @@ -164,7 +164,7 @@ public Expression buildEncodeExpression() { for (int i = 0; i < numFields; i++) { Descriptor d = getDescriptorByFieldName(schema.getFields().get(i).getName()); Preconditions.checkNotNull(d); - TypeToken fieldType = d.getTypeToken(); + TypeRef fieldType = d.getTypeRef(); Expression fieldValue = getFieldValue(bean, d); Literal ordinal = Literal.ofInt(i); Expression.StaticInvoke field = @@ -175,7 +175,7 @@ public Expression buildEncodeExpression() { } expressions.add( new Expression.Return( - new Expression.Invoke(writer, "getRow", TypeToken.of(BinaryRow.class)))); + new Expression.Invoke(writer, "getRow", TypeRef.of(BinaryRow.class)))); return expressions; } @@ -194,11 +194,11 @@ public Expression buildDecodeExpression() { for (int i = 0; i < numFields; i++) { Literal ordinal = Literal.ofInt(i); Descriptor d = getDescriptorByFieldName(schema.getFields().get(i).getName()); - TypeToken fieldType = d.getTypeToken(); + TypeRef fieldType = d.getTypeRef(); Expression.Invoke isNullAt = new Expression.Invoke(row, "isNullAt", TypeUtils.PRIMITIVE_BOOLEAN_TYPE, ordinal); String columnAccessMethodName = BinaryUtils.getElemAccessMethodName(fieldType); - TypeToken colType = BinaryUtils.getElemReturnType(fieldType); + TypeRef colType = BinaryUtils.getElemReturnType(fieldType); Expression.Invoke columnValue = new Expression.Invoke( row, diff --git a/java/fury-format/src/main/java/org/apache/fury/format/row/binary/BinaryUtils.java b/java/fury-format/src/main/java/org/apache/fury/format/row/binary/BinaryUtils.java index f3e0bb1b1c..84d1c616f0 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/row/binary/BinaryUtils.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/row/binary/BinaryUtils.java @@ -19,14 +19,14 @@ package org.apache.fury.format.row.binary; -import com.google.common.reflect.TypeToken; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.TypeUtils; /** Util class for building generated binary encoder. */ @SuppressWarnings("UnstableApiUsage") public class BinaryUtils { - public static String getElemAccessMethodName(TypeToken type) { + public static String getElemAccessMethodName(TypeRef type) { if (TypeUtils.PRIMITIVE_BYTE_TYPE.equals(type) || TypeUtils.BYTE_TYPE.equals(type)) { return "getByte"; } else if (TypeUtils.PRIMITIVE_BOOLEAN_TYPE.equals(type) @@ -66,7 +66,7 @@ public static String getElemAccessMethodName(TypeToken type) { } } - public static TypeToken getElemReturnType(TypeToken type) { + public static TypeRef getElemReturnType(TypeRef type) { if (TypeUtils.PRIMITIVE_BYTE_TYPE.equals(type) || TypeUtils.BYTE_TYPE.equals(type)) { return TypeUtils.PRIMITIVE_BYTE_TYPE; } else if (TypeUtils.PRIMITIVE_BOOLEAN_TYPE.equals(type) @@ -92,15 +92,15 @@ public static TypeToken getElemReturnType(TypeToken type) { return TypeUtils.STRING_TYPE; } else if (type.isArray() || TypeUtils.ITERABLE_TYPE.isSupertypeOf(type)) { // take BINARY_TYPE as array - return TypeToken.of(BinaryArray.class); + return TypeRef.of(BinaryArray.class); } else if (TypeUtils.MAP_TYPE.isSupertypeOf(type)) { - return TypeToken.of(BinaryMap.class); + return TypeRef.of(BinaryMap.class); } else if (TypeUtils.isBean(type)) { - return TypeToken.of(BinaryRow.class); + return TypeRef.of(BinaryRow.class); } else { // take unknown type as OBJECT_TYPE, return as sliced MemoryBuffer // slice MemoryBuffer, then deserialize in EncodeExpressionBuilder.deserializeFor - return TypeToken.of(MemoryBuffer.class); + return TypeRef.of(MemoryBuffer.class); } } } diff --git a/java/fury-format/src/main/java/org/apache/fury/format/type/TypeInference.java b/java/fury-format/src/main/java/org/apache/fury/format/type/TypeInference.java index 8024fae798..067d20bb9f 100644 --- a/java/fury-format/src/main/java/org/apache/fury/format/type/TypeInference.java +++ b/java/fury-format/src/main/java/org/apache/fury/format/type/TypeInference.java @@ -23,7 +23,6 @@ import static org.apache.fury.type.TypeUtils.getRawType; import com.google.common.base.CaseFormat; -import com.google.common.reflect.TypeToken; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; @@ -39,6 +38,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.types.pojo.Schema; import org.apache.fury.collection.Tuple2; +import org.apache.fury.reflect.TypeRef; import org.apache.fury.type.Descriptor; import org.apache.fury.type.TypeUtils; import org.apache.fury.util.DecimalUtils; @@ -49,25 +49,25 @@ public class TypeInference { public static Schema inferSchema(java.lang.reflect.Type type) { - return inferSchema(TypeToken.of(type)); + return inferSchema(TypeRef.of(type)); } public static Schema inferSchema(Class clz) { - return inferSchema(TypeToken.of(clz)); + return inferSchema(TypeRef.of(clz)); } /** * Infer the schema for class. * - * @param typeToken bean class type + * @param typeRef bean class type * @return schema of a class */ - public static Schema inferSchema(TypeToken typeToken) { - return inferSchema(typeToken, true); + public static Schema inferSchema(TypeRef typeRef) { + return inferSchema(typeRef, true); } - public static Schema inferSchema(TypeToken typeToken, boolean forStruct) { - Field field = inferField(typeToken); + public static Schema inferSchema(TypeRef typeRef, boolean forStruct) { + Field field = inferField(typeRef); if (forStruct) { Preconditions.checkArgument(field.getType().getTypeID() == ArrowType.ArrowTypeID.Struct); return new Schema(field.getChildren()); @@ -77,54 +77,54 @@ public static Schema inferSchema(TypeToken typeToken, boolean forStruct) { } public static Optional getDataType(Class cls) { - return getDataType(TypeToken.of(cls)); + return getDataType(TypeRef.of(cls)); } - public static Optional getDataType(TypeToken typeToken) { + public static Optional getDataType(TypeRef typeRef) { try { - return Optional.of(inferDataType(typeToken)); + return Optional.of(inferDataType(typeRef)); } catch (UnsupportedOperationException e) { return Optional.empty(); } } - public static ArrowType inferDataType(TypeToken typeToken) { - return inferField(typeToken).getType(); + public static ArrowType inferDataType(TypeRef typeRef) { + return inferField(typeRef).getType(); } public static Field arrayInferField( java.lang.reflect.Type arrayType, java.lang.reflect.Type type) { - return arrayInferField(TypeToken.of(arrayType), TypeToken.of(type)); + return arrayInferField(TypeRef.of(arrayType), TypeRef.of(type)); } public static Field arrayInferField(Class arrayClz, Class clz) { - return arrayInferField(TypeToken.of(arrayClz), TypeToken.of(clz)); + return arrayInferField(TypeRef.of(arrayClz), TypeRef.of(clz)); } /** * Infer the field of the list. * - * @param typeToken bean class type + * @param typeRef bean class type * @return field of the list */ - public static Field arrayInferField(TypeToken arrayTypeToken, TypeToken typeToken) { - Field field = inferField(arrayTypeToken, typeToken); + public static Field arrayInferField(TypeRef arrayTypeRef, TypeRef typeRef) { + Field field = inferField(arrayTypeRef, typeRef); Preconditions.checkArgument(field.getType().getTypeID() == ArrowType.ArrowTypeID.List); return field; } - private static Field inferField(TypeToken typeToken) { - return inferField(null, typeToken); + private static Field inferField(TypeRef typeRef) { + return inferField(null, typeRef); } - private static Field inferField(TypeToken arrayTypeToken, TypeToken typeToken) { + private static Field inferField(TypeRef arrayTypeRef, TypeRef typeRef) { LinkedHashSet> seenTypeSet = new LinkedHashSet<>(); String name = ""; - if (arrayTypeToken != null) { - Field f = inferField(DataTypes.ARRAY_ITEM_NAME, typeToken, seenTypeSet); + if (arrayTypeRef != null) { + Field f = inferField(DataTypes.ARRAY_ITEM_NAME, typeRef, seenTypeSet); return DataTypes.arrayField(name, f); } else { - return inferField("", typeToken, seenTypeSet); + return inferField("", typeRef, seenTypeSet); } } @@ -135,8 +135,8 @@ private static Field inferField(TypeToken arrayTypeToken, TypeToken typeTo * @return DataType of a typeToken */ private static Field inferField( - String name, TypeToken typeToken, LinkedHashSet> seenTypeSet) { - Class rawType = getRawType(typeToken); + String name, TypeRef typeRef, LinkedHashSet> seenTypeSet) { + Class rawType = getRawType(typeRef); if (rawType == boolean.class) { return field(name, DataTypes.notNullFieldType(ArrowType.Bool.INSTANCE)); } else if (rawType == byte.class) { @@ -194,16 +194,16 @@ private static Field inferField( Field f = inferField( DataTypes.ARRAY_ITEM_NAME, - Objects.requireNonNull(typeToken.getComponentType()), + Objects.requireNonNull(typeRef.getComponentType()), seenTypeSet); return DataTypes.arrayField(name, f); - } else if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeToken)) { // iterable + } else if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)) { // iterable // when type is both iterable and bean, we take it as iterable in row-format Field f = - inferField(DataTypes.ARRAY_ITEM_NAME, TypeUtils.getElementType(typeToken), seenTypeSet); + inferField(DataTypes.ARRAY_ITEM_NAME, TypeUtils.getElementType(typeRef), seenTypeSet); return DataTypes.arrayField(name, f); - } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeToken)) { - Tuple2, TypeToken> kvType = TypeUtils.getMapKeyValueType(typeToken); + } else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) { + Tuple2, TypeRef> kvType = TypeUtils.getMapKeyValueType(typeRef); Field keyField = inferField(MapVector.KEY_NAME, kvType.f0, seenTypeSet); // Map's keys must be non-nullable FieldType keyFieldType = @@ -229,28 +229,27 @@ private static Field inferField( String n = CaseFormat.LOWER_CAMEL.to( CaseFormat.LOWER_UNDERSCORE, descriptor.getName()); - return inferField(n, descriptor.getTypeToken(), newSeenTypeSet); + return inferField(n, descriptor.getTypeRef(), newSeenTypeSet); }) .collect(Collectors.toList()); return DataTypes.structField(name, true, fields); } else { throw new UnsupportedOperationException( String.format( - "Unsupported type %s for field %s, seen type set is %s", - typeToken, name, seenTypeSet)); + "Unsupported type %s for field %s, seen type set is %s", typeRef, name, seenTypeSet)); } } - public static String inferTypeName(TypeToken token) { + public static String inferTypeName(TypeRef token) { StringBuilder sb = new StringBuilder(); - TypeToken arrayToken = token; + TypeRef arrayToken = token; while (TypeUtils.ITERABLE_TYPE.isSupertypeOf(arrayToken) || TypeUtils.MAP_TYPE.isSupertypeOf(arrayToken)) { if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(arrayToken)) { sb.append(getRawType(arrayToken).getSimpleName()); arrayToken = TypeUtils.getElementType(arrayToken); } else { - Tuple2, TypeToken> tuple2 = TypeUtils.getMapKeyValueType(arrayToken); + Tuple2, TypeRef> tuple2 = TypeUtils.getMapKeyValueType(arrayToken); sb.append("Map"); if (!TypeUtils.isBean(tuple2.f0)) { diff --git a/java/fury-format/src/test/java/org/apache/fury/format/encoder/ArrayEncoderTest.java b/java/fury-format/src/test/java/org/apache/fury/format/encoder/ArrayEncoderTest.java index 4d375e8480..0af1891a13 100644 --- a/java/fury-format/src/test/java/org/apache/fury/format/encoder/ArrayEncoderTest.java +++ b/java/fury-format/src/test/java/org/apache/fury/format/encoder/ArrayEncoderTest.java @@ -19,13 +19,13 @@ package org.apache.fury.format.encoder; -import com.google.common.reflect.TypeToken; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.fury.format.row.binary.BinaryArray; +import org.apache.fury.reflect.TypeRef; import org.testng.Assert; import org.testng.annotations.Test; @@ -74,7 +74,7 @@ public void testNestListEncoder() { } ArrayEncoder>>> encoder = - Encoders.arrayEncoder(new TypeToken>>>() {}); + Encoders.arrayEncoder(new TypeRef>>>() {}); BinaryArray array = encoder.toArray(bars); List>> newBars = encoder.fromArray(array); @@ -105,7 +105,7 @@ public void testNestArrayWithMapEncoder() { ArrayEncoder>>>> encoder = Encoders.arrayEncoder( - new TypeToken>>>>() {}); + new TypeRef>>>>() {}); BinaryArray array = encoder.toArray(lmap); List>>> newLmap = encoder.fromArray(array); diff --git a/java/fury-format/src/test/java/org/apache/fury/format/encoder/MapEncoderTest.java b/java/fury-format/src/test/java/org/apache/fury/format/encoder/MapEncoderTest.java index b9bf07f590..53ff55c40f 100644 --- a/java/fury-format/src/test/java/org/apache/fury/format/encoder/MapEncoderTest.java +++ b/java/fury-format/src/test/java/org/apache/fury/format/encoder/MapEncoderTest.java @@ -19,13 +19,13 @@ package org.apache.fury.format.encoder; -import com.google.common.reflect.TypeToken; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.fury.format.row.binary.BinaryMap; +import org.apache.fury.reflect.TypeRef; import org.testng.Assert; import org.testng.annotations.Test; @@ -72,7 +72,7 @@ public void testNestListEncoder() { } MapEncoder>>> encoder = - Encoders.mapEncoder(new TypeToken>>>() {}); + Encoders.mapEncoder(new TypeRef>>>() {}); BinaryMap array = encoder.toMap(bars); Map>> newBars = encoder.fromMap(array); @@ -101,8 +101,7 @@ public void testNestArrayWithMapEncoder() { MapEncoder>>>> encoder = Encoders.mapEncoder( - new TypeToken< - Map>>>>() {}); + new TypeRef>>>>() {}); BinaryMap array = encoder.toMap(lmap); Map>>> newLmap = encoder.fromMap(array); diff --git a/licenserc.toml b/licenserc.toml index 66c0cadfff..6ae262dfd4 100644 --- a/licenserc.toml +++ b/licenserc.toml @@ -43,6 +43,9 @@ excludes = [ "java/fury-core/src/main/java/org/apache/fury/collection/ObjectIntMap.java", "java/fury-core/src/main/java/org/apache/fury/io/ClassLoaderObjectInputStream.java", "java/fury-core/src/main/java/org/apache/fury/memory/MemoryBuffer.java", + "java/fury-core/src/main/java/org/apache/fury/reflect/TypeParameter.java", + "java/fury-core/src/main/java/org/apache/fury/reflect/TypeRef.java", + "java/fury-core/src/main/java/org/apache/fury/reflect/Types.java", "java/fury-core/src/main/java/org/apache/fury/type/Generics.java", "java/fury-core/src/main/java/org/apache/fury/util/MurmurHash3.java", "java/fury-core/src/main/java/org/apache/fury/memory/Platform.java",