private <X> TypeInformation<X> privateGetForClass(Class<X> clazz, ArrayList<Type> typeHierarchy, ParameterizedType clazzTypeHint) {
Validate.notNull(clazz);
// check for abstract classes or interfaces
if (!clazz.isPrimitive() && (Modifier.isInterface(clazz.getModifiers()) || (Modifier.isAbstract(clazz.getModifiers()) && !clazz.isArray()))) {
throw new InvalidTypesException("Interfaces and abstract classes are not valid types: " + clazz);
}
if (clazz.equals(Object.class)) {
// TODO (merging): better throw an exception here. the runtime does not support it yet
return new GenericTypeInfo<X>(clazz);
}
// check for arrays
if (clazz.isArray()) {
// primitive arrays: int[], byte[], ...
PrimitiveArrayTypeInfo<X> primitiveArrayInfo = PrimitiveArrayTypeInfo.getInfoFor(clazz);
if (primitiveArrayInfo != null) {
return primitiveArrayInfo;
}
// basic type arrays: String[], Integer[], Double[]
BasicArrayTypeInfo<X, ?> basicArrayInfo = BasicArrayTypeInfo.getInfoFor(clazz);
if (basicArrayInfo != null) {
return basicArrayInfo;
}
// object arrays
else {
return ObjectArrayTypeInfo.getInfoFor(clazz);
}
}
// check for writable types
if(Writable.class.isAssignableFrom(clazz)) {
return (TypeInformation<X>) WritableTypeInfo.getWritableTypeInfo((Class<? extends Writable>) clazz);
}
// check for basic types
TypeInformation<X> basicTypeInfo = BasicTypeInfo.getInfoFor(clazz);
if (basicTypeInfo != null) {
return basicTypeInfo;
}
// check for subclasses of Value
if (Value.class.isAssignableFrom(clazz)) {
Class<? extends Value> valueClass = clazz.asSubclass(Value.class);
return (TypeInformation<X>) ValueTypeInfo.getValueTypeInfo(valueClass);
}
// check for subclasses of Tuple
if (Tuple.class.isAssignableFrom(clazz)) {
throw new InvalidTypesException("Type information extraction for tuples cannot be done based on the class.");
}
if (alreadySeen.contains(clazz)) {
return new GenericTypeInfo<X>(clazz);