private static ValueType newValueType( Map<Type, ValueType> typeMap, Type type, Class declaringClass, Class compositeType) { ValueType valueType = null; if (CollectionType.isCollection(type)) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Type collectionType = pt.getActualTypeArguments()[0]; if (collectionType instanceof TypeVariable) { TypeVariable collectionTypeVariable = (TypeVariable) collectionType; collectionType = Classes.resolveTypeVariable(collectionTypeVariable, declaringClass, compositeType); } ValueType collectedType = newValueType(typeMap, collectionType, declaringClass, compositeType); valueType = new CollectionType(nameOf(type), collectedType); } else { valueType = new CollectionType( nameOf(type), newValueType(typeMap, Object.class, declaringClass, compositeType)); } } else if (ValueCompositeType.isValueComposite(type)) { if (typeMap != null) { valueType = typeMap.get(type); } if (valueType == null) { Class valueTypeClass = Classes.getRawClass(type); List<PropertyType> types = new ArrayList<PropertyType>(); valueType = new ValueCompositeType(nameOf(valueTypeClass), types); if (typeMap == null) { typeMap = new HashMap<Type, ValueType>(); } typeMap.put(type, valueType); addProperties(typeMap, valueTypeClass, compositeType, types); Collections.sort(types); // Sort by property name } } else if (EnumType.isEnum(type)) { valueType = new EnumType(nameOf(type)); } else if (StringType.isString(type)) { valueType = new StringType(); } else if (NumberType.isNumber(type)) { valueType = new NumberType(nameOf(type)); } else if (BooleanType.isBoolean(type)) { valueType = new BooleanType(); } else if (DateType.isDate(type)) { valueType = new DateType(); } else if (EntityReferenceType.isEntityReference(type)) { valueType = new EntityReferenceType(nameOf(type)); } else { // TODO: shouldn't we check that the type is a Serializable? valueType = new SerializableType(nameOf(type)); } return valueType; }