use of org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo in project flink by apache.
the class TypeExtractor method validateInfo.
@SuppressWarnings("unchecked")
private static void validateInfo(ArrayList<Type> typeHierarchy, Type type, TypeInformation<?> typeInfo) {
if (type == null) {
throw new InvalidTypesException("Unknown Error. Type is null.");
}
if (typeInfo == null) {
throw new InvalidTypesException("Unknown Error. TypeInformation is null.");
}
if (!(type instanceof TypeVariable<?>)) {
// check for Java Basic Types
if (typeInfo instanceof BasicTypeInfo) {
TypeInformation<?> actual;
// check if basic type at all
if (!(type instanceof Class<?>) || (actual = BasicTypeInfo.getInfoFor((Class<?>) type)) == null) {
throw new InvalidTypesException("Basic type expected.");
}
// check if correct basic type
if (!typeInfo.equals(actual)) {
throw new InvalidTypesException("Basic type '" + typeInfo + "' expected but was '" + actual + "'.");
}
} else // check for Java SQL time types
if (typeInfo instanceof SqlTimeTypeInfo) {
TypeInformation<?> actual;
// check if SQL time type at all
if (!(type instanceof Class<?>) || (actual = SqlTimeTypeInfo.getInfoFor((Class<?>) type)) == null) {
throw new InvalidTypesException("SQL time type expected.");
}
// check if correct SQL time type
if (!typeInfo.equals(actual)) {
throw new InvalidTypesException("SQL time type '" + typeInfo + "' expected but was '" + actual + "'.");
}
} else // check for Java Tuples
if (typeInfo instanceof TupleTypeInfo) {
// check if tuple at all
if (!(isClassType(type) && Tuple.class.isAssignableFrom(typeToClass(type)))) {
throw new InvalidTypesException("Tuple type expected.");
}
// do not allow usage of Tuple as type
if (isClassType(type) && typeToClass(type).equals(Tuple.class)) {
throw new InvalidTypesException("Concrete subclass of Tuple expected.");
}
// go up the hierarchy until we reach immediate child of Tuple (with or without generics)
while (!(isClassType(type) && typeToClass(type).getSuperclass().equals(Tuple.class))) {
typeHierarchy.add(type);
type = typeToClass(type).getGenericSuperclass();
}
if (type == Tuple0.class) {
return;
}
// check if immediate child of Tuple has generics
if (type instanceof Class<?>) {
throw new InvalidTypesException("Parameterized Tuple type expected.");
}
TupleTypeInfo<?> tti = (TupleTypeInfo<?>) typeInfo;
Type[] subTypes = ((ParameterizedType) type).getActualTypeArguments();
if (subTypes.length != tti.getArity()) {
throw new InvalidTypesException("Tuple arity '" + tti.getArity() + "' expected but was '" + subTypes.length + "'.");
}
for (int i = 0; i < subTypes.length; i++) {
validateInfo(new ArrayList<Type>(typeHierarchy), subTypes[i], tti.getTypeAt(i));
}
} else // check for primitive array
if (typeInfo instanceof PrimitiveArrayTypeInfo) {
Type component;
// check if array at all
if (!(type instanceof Class<?> && ((Class<?>) type).isArray() && (component = ((Class<?>) type).getComponentType()) != null) && !(type instanceof GenericArrayType && (component = ((GenericArrayType) type).getGenericComponentType()) != null)) {
throw new InvalidTypesException("Array type expected.");
}
if (component instanceof TypeVariable<?>) {
component = materializeTypeVariable(typeHierarchy, (TypeVariable<?>) component);
if (component instanceof TypeVariable) {
return;
}
}
if (!(component instanceof Class<?> && ((Class<?>) component).isPrimitive())) {
throw new InvalidTypesException("Primitive component expected.");
}
} else // check for basic array
if (typeInfo instanceof BasicArrayTypeInfo<?, ?>) {
Type component;
// check if array at all
if (!(type instanceof Class<?> && ((Class<?>) type).isArray() && (component = ((Class<?>) type).getComponentType()) != null) && !(type instanceof GenericArrayType && (component = ((GenericArrayType) type).getGenericComponentType()) != null)) {
throw new InvalidTypesException("Array type expected.");
}
if (component instanceof TypeVariable<?>) {
component = materializeTypeVariable(typeHierarchy, (TypeVariable<?>) component);
if (component instanceof TypeVariable) {
return;
}
}
validateInfo(typeHierarchy, component, ((BasicArrayTypeInfo<?, ?>) typeInfo).getComponentInfo());
} else // check for object array
if (typeInfo instanceof ObjectArrayTypeInfo<?, ?>) {
// check if array at all
if (!(type instanceof Class<?> && ((Class<?>) type).isArray()) && !(type instanceof GenericArrayType)) {
throw new InvalidTypesException("Object array type expected.");
}
// check component
Type component;
if (type instanceof Class<?>) {
component = ((Class<?>) type).getComponentType();
} else {
component = ((GenericArrayType) type).getGenericComponentType();
}
if (component instanceof TypeVariable<?>) {
component = materializeTypeVariable(typeHierarchy, (TypeVariable<?>) component);
if (component instanceof TypeVariable) {
return;
}
}
validateInfo(typeHierarchy, component, ((ObjectArrayTypeInfo<?, ?>) typeInfo).getComponentInfo());
} else // check for value
if (typeInfo instanceof ValueTypeInfo<?>) {
// check if value at all
if (!(type instanceof Class<?> && Value.class.isAssignableFrom((Class<?>) type))) {
throw new InvalidTypesException("Value type expected.");
}
TypeInformation<?> actual;
// check value type contents
if (!((ValueTypeInfo<?>) typeInfo).equals(actual = ValueTypeInfo.getValueTypeInfo((Class<? extends Value>) type))) {
throw new InvalidTypesException("Value type '" + typeInfo + "' expected but was '" + actual + "'.");
}
} else // check for POJO
if (typeInfo instanceof PojoTypeInfo) {
Class<?> clazz = null;
if (!(isClassType(type) && ((PojoTypeInfo<?>) typeInfo).getTypeClass() == (clazz = typeToClass(type)))) {
throw new InvalidTypesException("POJO type '" + ((PojoTypeInfo<?>) typeInfo).getTypeClass().getCanonicalName() + "' expected but was '" + clazz.getCanonicalName() + "'.");
}
} else // check for Enum
if (typeInfo instanceof EnumTypeInfo) {
if (!(type instanceof Class<?> && Enum.class.isAssignableFrom((Class<?>) type))) {
throw new InvalidTypesException("Enum type expected.");
}
// check enum type contents
if (!(typeInfo.getTypeClass() == type)) {
throw new InvalidTypesException("Enum type '" + typeInfo.getTypeClass().getCanonicalName() + "' expected but was '" + typeToClass(type).getCanonicalName() + "'.");
}
} else // check for generic object
if (typeInfo instanceof GenericTypeInfo<?>) {
Class<?> clazz = null;
if (!(isClassType(type) && (clazz = typeToClass(type)).isAssignableFrom(((GenericTypeInfo<?>) typeInfo).getTypeClass()))) {
throw new InvalidTypesException("Generic type '" + ((GenericTypeInfo<?>) typeInfo).getTypeClass().getCanonicalName() + "' or a subclass of it expected but was '" + clazz.getCanonicalName() + "'.");
}
} else // check for Writable
{
validateIfWritable(typeInfo, type);
}
} else {
type = materializeTypeVariable(typeHierarchy, (TypeVariable<?>) type);
if (!(type instanceof TypeVariable)) {
validateInfo(typeHierarchy, type, typeInfo);
}
}
}
use of org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo in project flink by apache.
the class TypeExtractor method createTypeInfoFromInput.
/**
* Finds the type information to a type variable.
*
* It solve the following:
*
* Return the type information for "returnTypeVar" given that "inType" has type information "inTypeInfo".
* Thus "inType" must contain "returnTypeVar" in a "inputTypeHierarchy", otherwise null is returned.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private <IN1> TypeInformation<?> createTypeInfoFromInput(TypeVariable<?> returnTypeVar, ArrayList<Type> inputTypeHierarchy, Type inType, TypeInformation<IN1> inTypeInfo) {
TypeInformation<?> info = null;
// use a factory to find corresponding type information to type variable
final ArrayList<Type> factoryHierarchy = new ArrayList<>(inputTypeHierarchy);
final TypeInfoFactory<?> factory = getClosestFactory(factoryHierarchy, inType);
if (factory != null) {
// the type that defines the factory is last in factory hierarchy
final Type factoryDefiningType = factoryHierarchy.get(factoryHierarchy.size() - 1);
// defining type has generics, the factory need to be asked for a mapping of subtypes to type information
if (factoryDefiningType instanceof ParameterizedType) {
final Type[] typeParams = typeToClass(factoryDefiningType).getTypeParameters();
final Type[] actualParams = ((ParameterizedType) factoryDefiningType).getActualTypeArguments();
// go thru all elements and search for type variables
for (int i = 0; i < actualParams.length; i++) {
final Map<String, TypeInformation<?>> componentInfo = inTypeInfo.getGenericParameters();
final String typeParamName = typeParams[i].toString();
if (!componentInfo.containsKey(typeParamName) || componentInfo.get(typeParamName) == null) {
throw new InvalidTypesException("TypeInformation '" + inTypeInfo.getClass().getSimpleName() + "' does not supply a mapping of TypeVariable '" + typeParamName + "' to corresponding TypeInformation. " + "Input type inference can only produce a result with this information. " + "Please implement method 'TypeInformation.getGenericParameters()' for this.");
}
info = createTypeInfoFromInput(returnTypeVar, factoryHierarchy, actualParams[i], componentInfo.get(typeParamName));
if (info != null) {
break;
}
}
}
} else // the input is a type variable
if (sameTypeVars(inType, returnTypeVar)) {
return inTypeInfo;
} else if (inType instanceof TypeVariable) {
Type resolvedInType = materializeTypeVariable(inputTypeHierarchy, (TypeVariable<?>) inType);
if (resolvedInType != inType) {
info = createTypeInfoFromInput(returnTypeVar, inputTypeHierarchy, resolvedInType, inTypeInfo);
}
} else // input is an array
if (inType instanceof GenericArrayType) {
TypeInformation<?> componentInfo = null;
if (inTypeInfo instanceof BasicArrayTypeInfo) {
componentInfo = ((BasicArrayTypeInfo<?, ?>) inTypeInfo).getComponentInfo();
} else if (inTypeInfo instanceof PrimitiveArrayTypeInfo) {
componentInfo = BasicTypeInfo.getInfoFor(inTypeInfo.getTypeClass().getComponentType());
} else if (inTypeInfo instanceof ObjectArrayTypeInfo) {
componentInfo = ((ObjectArrayTypeInfo<?, ?>) inTypeInfo).getComponentInfo();
}
info = createTypeInfoFromInput(returnTypeVar, inputTypeHierarchy, ((GenericArrayType) inType).getGenericComponentType(), componentInfo);
} else // the input is a tuple
if (inTypeInfo instanceof TupleTypeInfo && isClassType(inType) && Tuple.class.isAssignableFrom(typeToClass(inType))) {
ParameterizedType tupleBaseClass;
// get tuple from possible tuple subclass
while (!(isClassType(inType) && typeToClass(inType).getSuperclass().equals(Tuple.class))) {
inputTypeHierarchy.add(inType);
inType = typeToClass(inType).getGenericSuperclass();
}
inputTypeHierarchy.add(inType);
// we can assume to be parameterized since we
// already did input validation
tupleBaseClass = (ParameterizedType) inType;
Type[] tupleElements = tupleBaseClass.getActualTypeArguments();
// go thru all tuple elements and search for type variables
for (int i = 0; i < tupleElements.length; i++) {
info = createTypeInfoFromInput(returnTypeVar, inputTypeHierarchy, tupleElements[i], ((TupleTypeInfo<?>) inTypeInfo).getTypeAt(i));
if (info != null) {
break;
}
}
} else // the input is a pojo
if (inTypeInfo instanceof PojoTypeInfo && isClassType(inType)) {
// build the entire type hierarchy for the pojo
getTypeHierarchy(inputTypeHierarchy, inType, Object.class);
// determine a field containing the type variable
List<Field> fields = getAllDeclaredFields(typeToClass(inType), false);
for (Field field : fields) {
Type fieldType = field.getGenericType();
if (fieldType instanceof TypeVariable && sameTypeVars(returnTypeVar, materializeTypeVariable(inputTypeHierarchy, (TypeVariable<?>) fieldType))) {
return getTypeOfPojoField(inTypeInfo, field);
} else if (fieldType instanceof ParameterizedType || fieldType instanceof GenericArrayType) {
ArrayList<Type> typeHierarchyWithFieldType = new ArrayList<>(inputTypeHierarchy);
typeHierarchyWithFieldType.add(fieldType);
TypeInformation<?> foundInfo = createTypeInfoFromInput(returnTypeVar, typeHierarchyWithFieldType, fieldType, getTypeOfPojoField(inTypeInfo, field));
if (foundInfo != null) {
return foundInfo;
}
}
}
}
return info;
}
use of org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo in project flink by apache.
the class FieldAccessorFactory method getAccessor.
/**
* Creates a {@link FieldAccessor} for the field that is given by a field expression,
* which can be used to get and set the specified field on instances of this type.
*
* @param field The field expression
* @param config Configuration object
* @param <F> The type of the field to access
* @return The created FieldAccessor
*/
@Internal
public static <T, F> FieldAccessor<T, F> getAccessor(TypeInformation<T> typeInfo, String field, ExecutionConfig config) {
// In case of arrays
if (typeInfo instanceof BasicArrayTypeInfo || typeInfo instanceof PrimitiveArrayTypeInfo) {
try {
return new FieldAccessor.ArrayFieldAccessor<>(Integer.parseInt(field), typeInfo);
} catch (NumberFormatException ex) {
throw new CompositeType.InvalidFieldReferenceException("A field expression on an array must be an integer index (that might be given as a string).");
}
// In case of basic types
} else if (typeInfo instanceof BasicTypeInfo) {
try {
int pos = field.equals(Keys.ExpressionKeys.SELECT_ALL_CHAR) ? 0 : Integer.parseInt(field);
return FieldAccessorFactory.getAccessor(typeInfo, pos, config);
} catch (NumberFormatException ex) {
throw new CompositeType.InvalidFieldReferenceException("You tried to select the field \"" + field + "\" on a " + typeInfo.toString() + ". A field expression on a basic type can only be \"*\" or \"0\"" + " (both of which mean selecting the entire basic type).");
}
// In case of Pojos
} else if (typeInfo instanceof PojoTypeInfo) {
FieldExpression decomp = decomposeFieldExpression(field);
PojoTypeInfo<?> pojoTypeInfo = (PojoTypeInfo) typeInfo;
int fieldIndex = pojoTypeInfo.getFieldIndex(decomp.head);
if (fieldIndex == -1) {
throw new CompositeType.InvalidFieldReferenceException("Unable to find field \"" + decomp.head + "\" in type " + typeInfo + ".");
} else {
PojoField pojoField = pojoTypeInfo.getPojoFieldAt(fieldIndex);
TypeInformation<?> fieldType = pojoTypeInfo.getTypeAt(fieldIndex);
if (decomp.tail == null) {
@SuppressWarnings("unchecked") FieldAccessor<F, F> innerAccessor = new FieldAccessor.SimpleFieldAccessor<>((TypeInformation<F>) fieldType);
return new FieldAccessor.PojoFieldAccessor<>(pojoField.getField(), innerAccessor);
} else {
@SuppressWarnings("unchecked") FieldAccessor<Object, F> innerAccessor = FieldAccessorFactory.getAccessor((TypeInformation<Object>) fieldType, decomp.tail, config);
return new FieldAccessor.PojoFieldAccessor<>(pojoField.getField(), innerAccessor);
}
}
// In case of case classes
} else if (typeInfo.isTupleType() && ((TupleTypeInfoBase) typeInfo).isCaseClass()) {
TupleTypeInfoBase tupleTypeInfo = (TupleTypeInfoBase) typeInfo;
FieldExpression decomp = decomposeFieldExpression(field);
int fieldPos = tupleTypeInfo.getFieldIndex(decomp.head);
if (fieldPos < 0) {
throw new CompositeType.InvalidFieldReferenceException("Invalid field selected: " + field);
}
if (decomp.tail == null) {
return new FieldAccessor.SimpleProductFieldAccessor<>(fieldPos, typeInfo, config);
} else {
@SuppressWarnings("unchecked") FieldAccessor<Object, F> innerAccessor = getAccessor(tupleTypeInfo.getTypeAt(fieldPos), decomp.tail, config);
return new FieldAccessor.RecursiveProductFieldAccessor<>(fieldPos, typeInfo, innerAccessor, config);
}
// In case of tuples
} else if (typeInfo.isTupleType()) {
TupleTypeInfo tupleTypeInfo = (TupleTypeInfo) typeInfo;
FieldExpression decomp = decomposeFieldExpression(field);
int fieldPos = tupleTypeInfo.getFieldIndex(decomp.head);
if (fieldPos == -1) {
try {
fieldPos = Integer.parseInt(decomp.head);
} catch (NumberFormatException ex) {
throw new CompositeType.InvalidFieldReferenceException("Tried to select field \"" + decomp.head + "\" on " + typeInfo.toString() + " . Only integer values are allowed here.");
}
}
if (decomp.tail == null) {
@SuppressWarnings("unchecked") FieldAccessor<T, F> result = new FieldAccessor.SimpleTupleFieldAccessor(fieldPos, tupleTypeInfo);
return result;
} else {
@SuppressWarnings("unchecked") FieldAccessor<?, F> innerAccessor = getAccessor(tupleTypeInfo.getTypeAt(fieldPos), decomp.tail, config);
@SuppressWarnings("unchecked") FieldAccessor<T, F> result = new FieldAccessor.RecursiveTupleFieldAccessor(fieldPos, innerAccessor, tupleTypeInfo);
return result;
}
// Default statement
} else {
throw new CompositeType.InvalidFieldReferenceException("Cannot reference field by field expression on " + typeInfo.toString() + "Field expressions are only supported on POJO types, tuples, and case classes. " + "(See the Flink documentation on what is considered a POJO.)");
}
}
use of org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo in project flink by apache.
the class FieldAccessorFactory method getAccessor.
/**
* Creates a {@link FieldAccessor} for the given field position, which can be used to get and set
* the specified field on instances of this type.
*
* @param pos The field position (zero-based)
* @param config Configuration object
* @param <F> The type of the field to access
* @return The created FieldAccessor
*/
@Internal
public static <T, F> FieldAccessor<T, F> getAccessor(TypeInformation<T> typeInfo, int pos, ExecutionConfig config) {
// In case of arrays
if (typeInfo instanceof BasicArrayTypeInfo || typeInfo instanceof PrimitiveArrayTypeInfo) {
return new FieldAccessor.ArrayFieldAccessor<>(pos, typeInfo);
// In case of basic types
} else if (typeInfo instanceof BasicTypeInfo) {
if (pos != 0) {
throw new CompositeType.InvalidFieldReferenceException("The " + ((Integer) pos).toString() + ". field selected on a " + "basic type (" + typeInfo.toString() + "). A field expression on a basic type can only select " + "the 0th field (which means selecting the entire basic type).");
}
@SuppressWarnings("unchecked") FieldAccessor<T, F> result = (FieldAccessor<T, F>) new FieldAccessor.SimpleFieldAccessor<>(typeInfo);
return result;
// In case of case classes
} else if (typeInfo.isTupleType() && ((TupleTypeInfoBase) typeInfo).isCaseClass()) {
TupleTypeInfoBase tupleTypeInfo = (TupleTypeInfoBase) typeInfo;
@SuppressWarnings("unchecked") TypeInformation<F> fieldTypeInfo = (TypeInformation<F>) tupleTypeInfo.getTypeAt(pos);
return new FieldAccessor.RecursiveProductFieldAccessor<>(pos, typeInfo, new FieldAccessor.SimpleFieldAccessor<>(fieldTypeInfo), config);
// In case of tuples
} else if (typeInfo.isTupleType()) {
@SuppressWarnings("unchecked") FieldAccessor<T, F> result = new FieldAccessor.SimpleTupleFieldAccessor(pos, typeInfo);
return result;
// Default case, PojoType is directed to this statement
} else {
throw new CompositeType.InvalidFieldReferenceException("Cannot reference field by position on " + typeInfo.toString() + "Referencing a field by position is supported on tuples, case classes, and arrays. " + "Additionally, you can select the 0th field of a primitive/basic type (e.g. int).");
}
}
Aggregations