Search in sources :

Example 1 with TypeResolver

use of co.cask.cdap.etl.common.guice.TypeResolver in project cdap by caskdata.

the class PipelineTypeValidator method validateTypes.

/**
   * Takes in an unresolved type list and resolves the types and verifies if the types are assignable.
   * Ex: An unresolved type could be : String, T, List<T>, List<String>
   *     The above will resolve to   : String, String, List<String>, List<String>
   *     And the assignability will be checked : String --> String && List<String> --> List<String>
   *     which is true in the case above.
   */
@VisibleForTesting
static void validateTypes(List<Type> unresTypeList) {
    Preconditions.checkArgument(unresTypeList.size() % 2 == 0, "ETL Stages validation expects even number of types");
    List<Type> resTypeList = Lists.newArrayListWithCapacity(unresTypeList.size());
    // Add the source output to resolved type list as the first resolved type.
    resTypeList.add(unresTypeList.get(0));
    try {
        // Resolve the second type using just the first resolved type.
        Type nType = (new TypeResolver()).where(unresTypeList.get(1), resTypeList.get(0)).resolveType(unresTypeList.get(1));
        resTypeList.add(nType);
    } catch (IllegalArgumentException e) {
        // If unable to resolve type, add the second type as is, to the resolved list.
        resTypeList.add(unresTypeList.get(1));
    }
    for (int i = 2; i < unresTypeList.size(); i++) {
        // ActualType is previous resolved type; FormalType is previous unresolved type;
        // ToResolveType is current unresolved type;
        // Ex: Actual = String; Formal = T; ToResolve = List<T>;  ==> newType = List<String>
        Type actualType = resTypeList.get(i - 1);
        Type formalType = unresTypeList.get(i - 1);
        Type toResolveType = unresTypeList.get(i);
        try {
            Type newType;
            // newType should be List<String>. Hence resolve only from the previous resolved type (Actual)
            if ((toResolveType instanceof TypeVariable) || (toResolveType instanceof GenericArrayType)) {
                newType = (new TypeResolver()).where(toResolveType, actualType).resolveType(toResolveType);
            } else {
                newType = (new TypeResolver()).where(formalType, actualType).resolveType(toResolveType);
            }
            resTypeList.add(newType);
        } catch (IllegalArgumentException e) {
            // If resolution failed, add the type as is to the resolved list.
            resTypeList.add(toResolveType);
        }
    }
    // transform (which takes in type on its left and emits the type on its right).
    for (int i = 0; i < resTypeList.size(); i += 2) {
        Type firstType = resTypeList.get(i);
        Type secondType = resTypeList.get(i + 1);
        // Check if secondType can accept firstType
        Preconditions.checkArgument(TypeToken.of(secondType).isAssignableFrom(firstType), "Types between stages didn't match. Mismatch between %s -> %s", firstType, secondType);
    }
}
Also used : GenericArrayType(java.lang.reflect.GenericArrayType) Type(java.lang.reflect.Type) TypeVariable(java.lang.reflect.TypeVariable) TypeResolver(co.cask.cdap.etl.common.guice.TypeResolver) GenericArrayType(java.lang.reflect.GenericArrayType) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

TypeResolver (co.cask.cdap.etl.common.guice.TypeResolver)1 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 GenericArrayType (java.lang.reflect.GenericArrayType)1 Type (java.lang.reflect.Type)1 TypeVariable (java.lang.reflect.TypeVariable)1