Search in sources :

Example 1 with BasicTypeInfo

use of org.apache.flink.api.common.typeinfo.BasicTypeInfo in project flink by apache.

the class TypeInfoParser method parse.

@SuppressWarnings({ "rawtypes", "unchecked" })
private static TypeInformation<?> parse(StringBuilder sb) throws ClassNotFoundException {
    String infoString = sb.toString();
    final Matcher tupleMatcher = tuplePattern.matcher(infoString);
    final Matcher writableMatcher = writablePattern.matcher(infoString);
    final Matcher enumMatcher = enumPattern.matcher(infoString);
    final Matcher basicTypeMatcher = basicTypePattern.matcher(infoString);
    final Matcher basicTypeDateMatcher = basicTypeDatePattern.matcher(infoString);
    final Matcher basicTypeBigIntMatcher = basicTypeBigIntPattern.matcher(infoString);
    final Matcher basicTypeBigDecMatcher = basicTypeBigDecPattern.matcher(infoString);
    final Matcher primitiveTypeMatcher = primitiveTypePattern.matcher(infoString);
    final Matcher valueTypeMatcher = valueTypePattern.matcher(infoString);
    final Matcher pojoGenericMatcher = pojoGenericObjectPattern.matcher(infoString);
    if (infoString.length() == 0) {
        return null;
    }
    TypeInformation<?> returnType = null;
    boolean isPrimitiveType = false;
    // tuples
    if (tupleMatcher.find()) {
        boolean isGenericTuple = true;
        String className = tupleMatcher.group(3);
        if (className == null) {
            // matched Tuple0
            isGenericTuple = false;
            className = tupleMatcher.group(2);
            sb.delete(0, className.length());
        } else {
            // +1 for "<"
            sb.delete(0, className.length() + 1);
        }
        if (infoString.startsWith(TUPLE_PACKAGE)) {
            // +1 for trailing "."
            sb.delete(0, TUPLE_PACKAGE.length() + 1);
        }
        int arity = Integer.parseInt(className.replaceAll("\\D", ""));
        Class<?> clazz = loadClass(TUPLE_PACKAGE + "." + className);
        TypeInformation<?>[] types = new TypeInformation<?>[arity];
        for (int i = 0; i < arity; i++) {
            types[i] = parse(sb);
            if (types[i] == null) {
                throw new IllegalArgumentException("Tuple arity does not match given parameters.");
            }
        }
        if (isGenericTuple) {
            if (sb.charAt(0) != '>') {
                throw new IllegalArgumentException("Tuple arity does not match given parameters.");
            }
            // remove '>'
            sb.deleteCharAt(0);
        }
        returnType = new TupleTypeInfo(clazz, types);
    } else // writable types
    if (writableMatcher.find()) {
        String className = writableMatcher.group(1);
        String fullyQualifiedName = writableMatcher.group(3);
        sb.delete(0, className.length() + 1 + fullyQualifiedName.length() + 1);
        Class<?> clazz = loadClass(fullyQualifiedName);
        returnType = TypeExtractor.createHadoopWritableTypeInfo(clazz);
    } else // enum types
    if (enumMatcher.find()) {
        String className = enumMatcher.group(1);
        String fullyQualifiedName = enumMatcher.group(3);
        sb.delete(0, className.length() + 1 + fullyQualifiedName.length() + 1);
        Class<?> clazz = loadClass(fullyQualifiedName);
        returnType = new EnumTypeInfo(clazz);
    } else // basic types
    if (basicTypeMatcher.find()) {
        String className = basicTypeMatcher.group(1);
        sb.delete(0, className.length());
        Class<?> clazz;
        // check if fully qualified
        if (className.startsWith("java.lang")) {
            clazz = loadClass(className);
        } else {
            clazz = loadClass("java.lang." + className);
        }
        returnType = BasicTypeInfo.getInfoFor(clazz);
    } else // special basic type "Date"
    if (basicTypeDateMatcher.find()) {
        String className = basicTypeDateMatcher.group(1);
        sb.delete(0, className.length());
        Class<?> clazz;
        // check if fully qualified
        if (className.startsWith("java.util")) {
            clazz = loadClass(className);
        } else {
            clazz = loadClass("java.util." + className);
        }
        returnType = BasicTypeInfo.getInfoFor(clazz);
    } else // special basic type "BigInteger"
    if (basicTypeBigIntMatcher.find()) {
        String className = basicTypeBigIntMatcher.group(1);
        sb.delete(0, className.length());
        Class<?> clazz;
        // check if fully qualified
        if (className.startsWith("java.math")) {
            clazz = loadClass(className);
        } else {
            clazz = loadClass("java.math." + className);
        }
        returnType = BasicTypeInfo.getInfoFor(clazz);
    } else // special basic type "BigDecimal"
    if (basicTypeBigDecMatcher.find()) {
        String className = basicTypeBigDecMatcher.group(1);
        sb.delete(0, className.length());
        Class<?> clazz;
        // check if fully qualified
        if (className.startsWith("java.math")) {
            clazz = loadClass(className);
        } else {
            clazz = loadClass("java.math." + className);
        }
        returnType = BasicTypeInfo.getInfoFor(clazz);
    } else // primitive types
    if (primitiveTypeMatcher.find()) {
        String keyword = primitiveTypeMatcher.group(1);
        sb.delete(0, keyword.length());
        Class<?> clazz = null;
        if (keyword.equals("int")) {
            clazz = int.class;
        } else if (keyword.equals("byte")) {
            clazz = byte.class;
        } else if (keyword.equals("short")) {
            clazz = short.class;
        } else if (keyword.equals("char")) {
            clazz = char.class;
        } else if (keyword.equals("double")) {
            clazz = double.class;
        } else if (keyword.equals("float")) {
            clazz = float.class;
        } else if (keyword.equals("long")) {
            clazz = long.class;
        } else if (keyword.equals("boolean")) {
            clazz = boolean.class;
        } else if (keyword.equals("void")) {
            clazz = void.class;
        }
        returnType = BasicTypeInfo.getInfoFor(clazz);
        isPrimitiveType = true;
    } else // values
    if (valueTypeMatcher.find()) {
        String className = valueTypeMatcher.group(1);
        sb.delete(0, className.length() + 5);
        Class<?> clazz;
        // check if fully qualified
        if (className.startsWith(VALUE_PACKAGE)) {
            clazz = loadClass(className + "Value");
        } else {
            clazz = loadClass(VALUE_PACKAGE + "." + className + "Value");
        }
        returnType = ValueTypeInfo.getValueTypeInfo((Class<Value>) clazz);
    } else // pojo objects or generic types
    if (pojoGenericMatcher.find()) {
        String fullyQualifiedName = pojoGenericMatcher.group(1);
        sb.delete(0, fullyQualifiedName.length());
        boolean isPojo = pojoGenericMatcher.group(2) != null;
        // pojo
        if (isPojo) {
            sb.deleteCharAt(0);
            Class<?> clazz = loadClass(fullyQualifiedName);
            ArrayList<PojoField> fields = new ArrayList<PojoField>();
            while (sb.charAt(0) != '>') {
                final Matcher fieldMatcher = fieldPattern.matcher(sb);
                if (!fieldMatcher.find()) {
                    throw new IllegalArgumentException("Field name missing.");
                }
                String fieldName = fieldMatcher.group(1);
                sb.delete(0, fieldName.length() + 1);
                Field field = TypeExtractor.getDeclaredField(clazz, fieldName);
                if (field == null) {
                    throw new IllegalArgumentException("Field '" + fieldName + "'could not be accessed.");
                }
                fields.add(new PojoField(field, parse(sb)));
            }
            // remove '>'
            sb.deleteCharAt(0);
            returnType = new PojoTypeInfo(clazz, fields);
        } else // generic type
        {
            returnType = new GenericTypeInfo(loadClass(fullyQualifiedName));
        }
    }
    if (returnType == null) {
        throw new IllegalArgumentException("Error at '" + infoString + "'");
    }
    // arrays
    int arrayDimensionCount = 0;
    while (sb.length() > 1 && sb.charAt(0) == '[' && sb.charAt(1) == ']') {
        arrayDimensionCount++;
        sb.delete(0, 2);
    }
    if (sb.length() > 0 && sb.charAt(0) == '[') {
        throw new IllegalArgumentException("Closing square bracket missing.");
    }
    // construct multidimension array
    if (arrayDimensionCount > 0) {
        TypeInformation<?> arrayInfo = null;
        // primitive array
        if (isPrimitiveType) {
            if (returnType == BasicTypeInfo.INT_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.INT_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.BYTE_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.BYTE_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.SHORT_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.SHORT_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.CHAR_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.CHAR_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.DOUBLE_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.DOUBLE_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.FLOAT_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.FLOAT_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.LONG_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.LONG_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.BOOLEAN_TYPE_INFO) {
                arrayInfo = PrimitiveArrayTypeInfo.BOOLEAN_PRIMITIVE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.VOID_TYPE_INFO) {
                throw new IllegalArgumentException("Can not create an array of void.");
            }
        } else // basic array
        if (returnType instanceof BasicTypeInfo && returnType != BasicTypeInfo.DATE_TYPE_INFO) {
            if (returnType == BasicTypeInfo.INT_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.INT_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.BYTE_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.BYTE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.SHORT_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.SHORT_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.CHAR_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.CHAR_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.DOUBLE_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.DOUBLE_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.FLOAT_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.FLOAT_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.LONG_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.LONG_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.BOOLEAN_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.BOOLEAN_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.STRING_TYPE_INFO) {
                arrayInfo = BasicArrayTypeInfo.STRING_ARRAY_TYPE_INFO;
            } else if (returnType == BasicTypeInfo.VOID_TYPE_INFO) {
                throw new IllegalArgumentException("Can not create an array of void.");
            }
        } else // object array
        {
            arrayInfo = ObjectArrayTypeInfo.getInfoFor(loadClass("[L" + returnType.getTypeClass().getName() + ";"), returnType);
        }
        // further dimensions
        if (arrayDimensionCount > 1) {
            String arrayPrefix = "[";
            for (int i = 1; i < arrayDimensionCount; i++) {
                arrayPrefix += "[";
                arrayInfo = ObjectArrayTypeInfo.getInfoFor(loadClass(arrayPrefix + "L" + returnType.getTypeClass().getName() + ";"), arrayInfo);
            }
        }
        returnType = arrayInfo;
    }
    // remove possible ','
    if (sb.length() > 0 && sb.charAt(0) == ',') {
        sb.deleteCharAt(0);
    }
    // check if end 
    return returnType;
}
Also used : Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) TypeInformation(org.apache.flink.api.common.typeinfo.TypeInformation) Field(java.lang.reflect.Field) BasicTypeInfo(org.apache.flink.api.common.typeinfo.BasicTypeInfo)

Example 2 with BasicTypeInfo

use of org.apache.flink.api.common.typeinfo.BasicTypeInfo in project flink by apache.

the class PojoTypeExtractionTest method checkWCPojoAsserts.

@SuppressWarnings({ "unchecked", "rawtypes" })
private void checkWCPojoAsserts(TypeInformation<?> typeInfo) {
    Assert.assertFalse(typeInfo.isBasicType());
    Assert.assertFalse(typeInfo.isTupleType());
    Assert.assertEquals(10, typeInfo.getTotalFields());
    Assert.assertTrue(typeInfo instanceof PojoTypeInfo);
    PojoTypeInfo<?> pojoType = (PojoTypeInfo<?>) typeInfo;
    List<FlatFieldDescriptor> ffd = new ArrayList<FlatFieldDescriptor>();
    String[] fields = { "count", "complex.date", "complex.collection", "complex.nothing", "complex.someFloat", "complex.someNumberWithÜnicödeNäme", "complex.valueType", "complex.word.f0", "complex.word.f1", "complex.word.f2" };
    int[] positions = { 9, 1, 0, 2, 3, 4, 5, 6, 7, 8 };
    Assert.assertEquals(fields.length, positions.length);
    for (int i = 0; i < fields.length; i++) {
        pojoType.getFlatFields(fields[i], 0, ffd);
        Assert.assertEquals("Too many keys returned", 1, ffd.size());
        Assert.assertEquals("position of field " + fields[i] + " wrong", positions[i], ffd.get(0).getPosition());
        ffd.clear();
    }
    pojoType.getFlatFields("complex.word.*", 0, ffd);
    Assert.assertEquals(3, ffd.size());
    // check if it returns 5,6,7
    for (FlatFieldDescriptor ffdE : ffd) {
        final int pos = ffdE.getPosition();
        Assert.assertTrue(pos <= 8);
        Assert.assertTrue(6 <= pos);
        if (pos == 6) {
            Assert.assertEquals(Long.class, ffdE.getType().getTypeClass());
        }
        if (pos == 7) {
            Assert.assertEquals(Long.class, ffdE.getType().getTypeClass());
        }
        if (pos == 8) {
            Assert.assertEquals(String.class, ffdE.getType().getTypeClass());
        }
    }
    ffd.clear();
    // scala style full tuple selection for pojos
    pojoType.getFlatFields("complex.word._", 0, ffd);
    Assert.assertEquals(3, ffd.size());
    ffd.clear();
    pojoType.getFlatFields("complex.*", 0, ffd);
    Assert.assertEquals(9, ffd.size());
    // check if it returns 0-7
    for (FlatFieldDescriptor ffdE : ffd) {
        final int pos = ffdE.getPosition();
        Assert.assertTrue(ffdE.getPosition() <= 8);
        Assert.assertTrue(0 <= ffdE.getPosition());
        if (pos == 0) {
            Assert.assertEquals(List.class, ffdE.getType().getTypeClass());
        }
        if (pos == 1) {
            Assert.assertEquals(Date.class, ffdE.getType().getTypeClass());
        }
        if (pos == 2) {
            Assert.assertEquals(Object.class, ffdE.getType().getTypeClass());
        }
        if (pos == 3) {
            Assert.assertEquals(Float.class, ffdE.getType().getTypeClass());
        }
        if (pos == 4) {
            Assert.assertEquals(Integer.class, ffdE.getType().getTypeClass());
        }
        if (pos == 5) {
            Assert.assertEquals(MyValue.class, ffdE.getType().getTypeClass());
        }
        if (pos == 6) {
            Assert.assertEquals(Long.class, ffdE.getType().getTypeClass());
        }
        if (pos == 7) {
            Assert.assertEquals(Long.class, ffdE.getType().getTypeClass());
        }
        if (pos == 8) {
            Assert.assertEquals(String.class, ffdE.getType().getTypeClass());
        }
        if (pos == 9) {
            Assert.assertEquals(Integer.class, ffdE.getType().getTypeClass());
        }
    }
    ffd.clear();
    pojoType.getFlatFields("*", 0, ffd);
    Assert.assertEquals(10, ffd.size());
    // check if it returns 0-8
    for (FlatFieldDescriptor ffdE : ffd) {
        Assert.assertTrue(ffdE.getPosition() <= 9);
        Assert.assertTrue(0 <= ffdE.getPosition());
        if (ffdE.getPosition() == 9) {
            Assert.assertEquals(Integer.class, ffdE.getType().getTypeClass());
        }
    }
    ffd.clear();
    // ComplexNestedClass complex
    TypeInformation<?> typeComplexNested = pojoType.getTypeAt(0);
    Assert.assertTrue(typeComplexNested instanceof PojoTypeInfo);
    Assert.assertEquals(7, typeComplexNested.getArity());
    Assert.assertEquals(9, typeComplexNested.getTotalFields());
    PojoTypeInfo<?> pojoTypeComplexNested = (PojoTypeInfo<?>) typeComplexNested;
    boolean dateSeen = false, intSeen = false, floatSeen = false, tupleSeen = false, objectSeen = false, writableSeen = false, collectionSeen = false;
    for (int i = 0; i < pojoTypeComplexNested.getArity(); i++) {
        PojoField field = pojoTypeComplexNested.getPojoFieldAt(i);
        String name = field.getField().getName();
        if (name.equals("date")) {
            if (dateSeen) {
                Assert.fail("already seen");
            }
            dateSeen = true;
            Assert.assertEquals(BasicTypeInfo.DATE_TYPE_INFO, field.getTypeInformation());
            Assert.assertEquals(Date.class, field.getTypeInformation().getTypeClass());
        } else if (name.equals("someNumberWithÜnicödeNäme")) {
            if (intSeen) {
                Assert.fail("already seen");
            }
            intSeen = true;
            Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, field.getTypeInformation());
            Assert.assertEquals(Integer.class, field.getTypeInformation().getTypeClass());
        } else if (name.equals("someFloat")) {
            if (floatSeen) {
                Assert.fail("already seen");
            }
            floatSeen = true;
            Assert.assertEquals(BasicTypeInfo.FLOAT_TYPE_INFO, field.getTypeInformation());
            Assert.assertEquals(Float.class, field.getTypeInformation().getTypeClass());
        } else if (name.equals("word")) {
            if (tupleSeen) {
                Assert.fail("already seen");
            }
            tupleSeen = true;
            Assert.assertTrue(field.getTypeInformation() instanceof TupleTypeInfo<?>);
            Assert.assertEquals(Tuple3.class, field.getTypeInformation().getTypeClass());
            // do some more advanced checks on the tuple
            TupleTypeInfo<?> tupleTypeFromComplexNested = (TupleTypeInfo<?>) field.getTypeInformation();
            Assert.assertEquals(BasicTypeInfo.LONG_TYPE_INFO, tupleTypeFromComplexNested.getTypeAt(0));
            Assert.assertEquals(BasicTypeInfo.LONG_TYPE_INFO, tupleTypeFromComplexNested.getTypeAt(1));
            Assert.assertEquals(BasicTypeInfo.STRING_TYPE_INFO, tupleTypeFromComplexNested.getTypeAt(2));
        } else if (name.equals("nothing")) {
            if (objectSeen) {
                Assert.fail("already seen");
            }
            objectSeen = true;
            Assert.assertEquals(new GenericTypeInfo<Object>(Object.class), field.getTypeInformation());
            Assert.assertEquals(Object.class, field.getTypeInformation().getTypeClass());
        } else if (name.equals("valueType")) {
            if (writableSeen) {
                Assert.fail("already seen");
            }
            writableSeen = true;
            Assert.assertEquals(new ValueTypeInfo<>(MyValue.class), field.getTypeInformation());
            Assert.assertEquals(MyValue.class, field.getTypeInformation().getTypeClass());
        } else if (name.equals("collection")) {
            if (collectionSeen) {
                Assert.fail("already seen");
            }
            collectionSeen = true;
            Assert.assertEquals(new GenericTypeInfo(List.class), field.getTypeInformation());
        } else {
            Assert.fail("field " + field + " is not expected");
        }
    }
    Assert.assertTrue("Field was not present", dateSeen);
    Assert.assertTrue("Field was not present", intSeen);
    Assert.assertTrue("Field was not present", floatSeen);
    Assert.assertTrue("Field was not present", tupleSeen);
    Assert.assertTrue("Field was not present", objectSeen);
    Assert.assertTrue("Field was not present", writableSeen);
    Assert.assertTrue("Field was not present", collectionSeen);
    // int count
    TypeInformation<?> typeAtOne = pojoType.getTypeAt(1);
    Assert.assertTrue(typeAtOne instanceof BasicTypeInfo);
    Assert.assertEquals(typeInfo.getTypeClass(), WC.class);
    Assert.assertEquals(typeInfo.getArity(), 2);
}
Also used : MyValue(org.apache.flink.api.java.typeutils.TypeInfoParserTest.MyValue) ArrayList(java.util.ArrayList) FlatFieldDescriptor(org.apache.flink.api.common.typeutils.CompositeType.FlatFieldDescriptor) Tuple3(org.apache.flink.api.java.tuple.Tuple3) BasicTypeInfo(org.apache.flink.api.common.typeinfo.BasicTypeInfo) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with BasicTypeInfo

use of org.apache.flink.api.common.typeinfo.BasicTypeInfo 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);
        }
    }
}
Also used : TypeInformation(org.apache.flink.api.common.typeinfo.TypeInformation) ParameterizedType(java.lang.reflect.ParameterizedType) TypeVariable(java.lang.reflect.TypeVariable) BasicTypeInfo(org.apache.flink.api.common.typeinfo.BasicTypeInfo) InvalidTypesException(org.apache.flink.api.common.functions.InvalidTypesException) GenericArrayType(java.lang.reflect.GenericArrayType) SqlTimeTypeInfo(org.apache.flink.api.common.typeinfo.SqlTimeTypeInfo) GenericArrayType(java.lang.reflect.GenericArrayType) TypeExtractionUtils.isClassType(org.apache.flink.api.java.typeutils.TypeExtractionUtils.isClassType) Type(java.lang.reflect.Type) CompositeType(org.apache.flink.api.common.typeutils.CompositeType) ParameterizedType(java.lang.reflect.ParameterizedType) Value(org.apache.flink.types.Value) PrimitiveArrayTypeInfo(org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo) TypeExtractionUtils.typeToClass(org.apache.flink.api.java.typeutils.TypeExtractionUtils.typeToClass) Tuple(org.apache.flink.api.java.tuple.Tuple) BasicArrayTypeInfo(org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo)

Example 4 with BasicTypeInfo

use of org.apache.flink.api.common.typeinfo.BasicTypeInfo in project flink by apache.

the class TypeExtractorTest method testTupleWithBasicTypes.

@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testTupleWithBasicTypes() throws Exception {
    // use getMapReturnTypes()
    RichMapFunction<?, ?> function = new RichMapFunction<Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte>, Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte>>() {

        private static final long serialVersionUID = 1L;

        @Override
        public Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte> map(Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte> value) throws Exception {
            return null;
        }
    };
    TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(function, (TypeInformation) TypeInfoParser.parse("Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte>"));
    Assert.assertTrue(ti.isTupleType());
    Assert.assertEquals(9, ti.getArity());
    Assert.assertTrue(ti instanceof TupleTypeInfo);
    List<FlatFieldDescriptor> ffd = new ArrayList<FlatFieldDescriptor>();
    ((TupleTypeInfo) ti).getFlatFields("f3", 0, ffd);
    Assert.assertTrue(ffd.size() == 1);
    Assert.assertEquals(3, ffd.get(0).getPosition());
    TupleTypeInfo<?> tti = (TupleTypeInfo<?>) ti;
    Assert.assertEquals(Tuple9.class, tti.getTypeClass());
    for (int i = 0; i < 9; i++) {
        Assert.assertTrue(tti.getTypeAt(i) instanceof BasicTypeInfo);
    }
    Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, tti.getTypeAt(0));
    Assert.assertEquals(BasicTypeInfo.LONG_TYPE_INFO, tti.getTypeAt(1));
    Assert.assertEquals(BasicTypeInfo.DOUBLE_TYPE_INFO, tti.getTypeAt(2));
    Assert.assertEquals(BasicTypeInfo.FLOAT_TYPE_INFO, tti.getTypeAt(3));
    Assert.assertEquals(BasicTypeInfo.BOOLEAN_TYPE_INFO, tti.getTypeAt(4));
    Assert.assertEquals(BasicTypeInfo.STRING_TYPE_INFO, tti.getTypeAt(5));
    Assert.assertEquals(BasicTypeInfo.CHAR_TYPE_INFO, tti.getTypeAt(6));
    Assert.assertEquals(BasicTypeInfo.SHORT_TYPE_INFO, tti.getTypeAt(7));
    Assert.assertEquals(BasicTypeInfo.BYTE_TYPE_INFO, tti.getTypeAt(8));
    // use getForObject()
    Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte> t = new Tuple9<Integer, Long, Double, Float, Boolean, String, Character, Short, Byte>(1, 1L, 1.0, 1.0F, false, "Hello World", 'w', (short) 1, (byte) 1);
    Assert.assertTrue(TypeExtractor.getForObject(t) instanceof TupleTypeInfo);
    TupleTypeInfo<?> tti2 = (TupleTypeInfo<?>) TypeExtractor.getForObject(t);
    Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, tti2.getTypeAt(0));
    Assert.assertEquals(BasicTypeInfo.LONG_TYPE_INFO, tti2.getTypeAt(1));
    Assert.assertEquals(BasicTypeInfo.DOUBLE_TYPE_INFO, tti2.getTypeAt(2));
    Assert.assertEquals(BasicTypeInfo.FLOAT_TYPE_INFO, tti2.getTypeAt(3));
    Assert.assertEquals(BasicTypeInfo.BOOLEAN_TYPE_INFO, tti2.getTypeAt(4));
    Assert.assertEquals(BasicTypeInfo.STRING_TYPE_INFO, tti2.getTypeAt(5));
    Assert.assertEquals(BasicTypeInfo.CHAR_TYPE_INFO, tti2.getTypeAt(6));
    Assert.assertEquals(BasicTypeInfo.SHORT_TYPE_INFO, tti2.getTypeAt(7));
    Assert.assertEquals(BasicTypeInfo.BYTE_TYPE_INFO, tti2.getTypeAt(8));
    // test that getForClass does not work
    try {
        TypeExtractor.getForClass(Tuple9.class);
        Assert.fail("Exception expected here");
    } catch (InvalidTypesException e) {
    // that is correct
    }
}
Also used : ArrayList(java.util.ArrayList) Tuple9(org.apache.flink.api.java.tuple.Tuple9) FlatFieldDescriptor(org.apache.flink.api.common.typeutils.CompositeType.FlatFieldDescriptor) TypeHint(org.apache.flink.api.common.typeinfo.TypeHint) BigInteger(java.math.BigInteger) RichMapFunction(org.apache.flink.api.common.functions.RichMapFunction) BasicTypeInfo(org.apache.flink.api.common.typeinfo.BasicTypeInfo) InvalidTypesException(org.apache.flink.api.common.functions.InvalidTypesException) Test(org.junit.Test)

Example 5 with BasicTypeInfo

use of org.apache.flink.api.common.typeinfo.BasicTypeInfo 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.)");
    }
}
Also used : PojoTypeInfo(org.apache.flink.api.java.typeutils.PojoTypeInfo) TupleTypeInfoBase(org.apache.flink.api.java.typeutils.TupleTypeInfoBase) BasicTypeInfo(org.apache.flink.api.common.typeinfo.BasicTypeInfo) TupleTypeInfo(org.apache.flink.api.java.typeutils.TupleTypeInfo) PrimitiveArrayTypeInfo(org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo) PojoField(org.apache.flink.api.java.typeutils.PojoField) BasicArrayTypeInfo(org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo) CompositeType(org.apache.flink.api.common.typeutils.CompositeType) Internal(org.apache.flink.annotation.Internal)

Aggregations

BasicTypeInfo (org.apache.flink.api.common.typeinfo.BasicTypeInfo)6 ArrayList (java.util.ArrayList)3 BasicArrayTypeInfo (org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo)3 PrimitiveArrayTypeInfo (org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo)3 TypeInformation (org.apache.flink.api.common.typeinfo.TypeInformation)3 CompositeType (org.apache.flink.api.common.typeutils.CompositeType)3 Internal (org.apache.flink.annotation.Internal)2 InvalidTypesException (org.apache.flink.api.common.functions.InvalidTypesException)2 FlatFieldDescriptor (org.apache.flink.api.common.typeutils.CompositeType.FlatFieldDescriptor)2 TupleTypeInfoBase (org.apache.flink.api.java.typeutils.TupleTypeInfoBase)2 Field (java.lang.reflect.Field)1 GenericArrayType (java.lang.reflect.GenericArrayType)1 ParameterizedType (java.lang.reflect.ParameterizedType)1 Type (java.lang.reflect.Type)1 TypeVariable (java.lang.reflect.TypeVariable)1 BigInteger (java.math.BigInteger)1 List (java.util.List)1 Matcher (java.util.regex.Matcher)1 RichMapFunction (org.apache.flink.api.common.functions.RichMapFunction)1 SqlTimeTypeInfo (org.apache.flink.api.common.typeinfo.SqlTimeTypeInfo)1