in java/fury-format/src/main/java/org/apache/fury/format/type/TypeInference.java [136:238]
private static Field inferField(
String name, TypeRef<?> typeRef, LinkedHashSet<Class<?>> seenTypeSet) {
Class<?> rawType = getRawType(typeRef);
if (rawType == boolean.class) {
return field(name, DataTypes.notNullFieldType(ArrowType.Bool.INSTANCE));
} else if (rawType == byte.class) {
return field(name, DataTypes.notNullFieldType(new ArrowType.Int(8, true)));
} else if (rawType == short.class) {
return field(name, DataTypes.notNullFieldType(new ArrowType.Int(16, true)));
} else if (rawType == int.class) {
return field(name, DataTypes.notNullFieldType(new ArrowType.Int(32, true)));
} else if (rawType == long.class) {
return field(name, DataTypes.notNullFieldType(new ArrowType.Int(64, true)));
} else if (rawType == float.class) {
return field(
name,
DataTypes.notNullFieldType(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE)));
} else if (rawType == double.class) {
return field(
name,
DataTypes.notNullFieldType(new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)));
} else if (rawType == Boolean.class) {
return field(name, FieldType.nullable((ArrowType.Bool.INSTANCE)));
} else if (rawType == Byte.class) {
return field(name, FieldType.nullable((new ArrowType.Int(8, true))));
} else if (rawType == Short.class) {
return field(name, FieldType.nullable((new ArrowType.Int(16, true))));
} else if (rawType == Integer.class) {
return field(name, FieldType.nullable((new ArrowType.Int(32, true))));
} else if (rawType == Long.class) {
return field(name, FieldType.nullable((new ArrowType.Int(64, true))));
} else if (rawType == Float.class) {
return field(
name, FieldType.nullable(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE)));
} else if (rawType == Double.class) {
return field(
name, FieldType.nullable(new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)));
} else if (rawType == java.math.BigDecimal.class) {
return field(
name,
FieldType.nullable(
new ArrowType.Decimal(DecimalUtils.MAX_PRECISION, DecimalUtils.MAX_SCALE)));
} else if (rawType == java.math.BigInteger.class) {
return field(name, FieldType.nullable(new ArrowType.Decimal(DecimalUtils.MAX_PRECISION, 0)));
} else if (rawType == java.time.LocalDate.class) {
return field(name, FieldType.nullable(new ArrowType.Date(DateUnit.DAY)));
} else if (rawType == java.sql.Date.class) {
return field(name, FieldType.nullable(new ArrowType.Date(DateUnit.DAY)));
} else if (rawType == java.sql.Timestamp.class) {
return field(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.MICROSECOND, null)));
} else if (rawType == java.time.Instant.class) {
return field(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.MICROSECOND, null)));
} else if (rawType == String.class) {
return field(name, FieldType.nullable(ArrowType.Utf8.INSTANCE));
} else if (rawType.isEnum()) {
return field(name, FieldType.nullable(ArrowType.Utf8.INSTANCE));
} else if (rawType.isArray()) { // array
Field f =
inferField(
DataTypes.ARRAY_ITEM_NAME,
Objects.requireNonNull(typeRef.getComponentType()),
seenTypeSet);
return DataTypes.arrayField(name, f);
} 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(typeRef), seenTypeSet);
return DataTypes.arrayField(name, f);
} else if (TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) {
Tuple2<TypeRef<?>, TypeRef<?>> kvType = TypeUtils.getMapKeyValueType(typeRef);
Field keyField = inferField(MapVector.KEY_NAME, kvType.f0, seenTypeSet);
// Map's keys must be non-nullable
FieldType keyFieldType =
new FieldType(
false, keyField.getType(), keyField.getDictionary(), keyField.getMetadata());
keyField = DataTypes.field(keyField.getName(), keyFieldType, keyField.getChildren());
Field valueField = inferField(MapVector.VALUE_NAME, kvType.f1, seenTypeSet);
return DataTypes.mapField(name, keyField, valueField);
} else if (TypeUtils.isBean(rawType)) { // bean field
if (seenTypeSet.contains(rawType)) {
String msg =
String.format(
"circular references in bean class is not allowed, but got " + "%s in %s",
rawType, seenTypeSet);
throw new UnsupportedOperationException(msg);
}
List<Field> fields =
Descriptor.getDescriptors(rawType).stream()
.map(
descriptor -> {
LinkedHashSet<Class<?>> newSeenTypeSet = new LinkedHashSet<>(seenTypeSet);
newSeenTypeSet.add(rawType);
String n = StringUtils.lowerCamelToLowerUnderscore(descriptor.getName());
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", typeRef, name, seenTypeSet));
}
}