
de.fraunhofer.iese.ind2uce.json.schema.JsonSchemaGenerator Maven / Gradle / Ivy
/*-
* =================================LICENSE_START=================================
* IND2UCE
* %%
* Copyright (C) 2016 Fraunhofer IESE (www.iese.fraunhofer.de)
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =================================LICENSE_END=================================
*/
package de.fraunhofer.iese.ind2uce.json.schema;
import de.fraunhofer.iese.ind2uce.api.component.description.ClassTypeDescription;
import de.fraunhofer.iese.ind2uce.api.component.description.JsonType;
import de.fraunhofer.iese.ind2uce.api.component.description.TypeDescription;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/***
*
*/
public class JsonSchemaGenerator {
public static final String MAP_FULL_QUALIFIED_CLASSNAME = "java.util.Map";
public static final String GENERIC_BEGIN = "<";
public static final String GENERIC_END = ">";
private static TypeDescription addArrayType(Map map, Class aClass) throws ClassNotFoundException {
final TypeDescription arrayTypeDescription = new TypeDescription();
arrayTypeDescription.setJsonType(JsonType.ARRAY);
arrayTypeDescription.setTypeName(aClass.getComponentType().getName());
if (!map.containsKey(aClass.getComponentType().getTypeName())) {
createMap(map, aClass.getComponentType(), aClass.getComponentType());
}
return arrayTypeDescription;
}
private static void addComplexType(Map map, Type type, Class aClass) throws ClassNotFoundException {
final ClassTypeDescription classTypeDescription = new ClassTypeDescription();
classTypeDescription.setJsonType(JsonType.OBJECT);
classTypeDescription.setTypeName(type.getTypeName());
// put in global map
map.put(type.getTypeName(), classTypeDescription);
final Field allComplexObjectFields[] = JavaReflectionUtils.getAllFields(aClass);
addFieldDescriptionOfComplexType(map, classTypeDescription, allComplexObjectFields);
}
private static void addDescriptionForField(Map map, ClassTypeDescription classTypeDescription, Field complexObjectFields) throws ClassNotFoundException {
final Class objectFieldClass = complexObjectFields.getType();
if (JavaReflectionUtils.isIterable(objectFieldClass)) {
final ParameterizedType parameterizedType = (ParameterizedType)complexObjectFields.getGenericType();
final Type iterableParametrizedTypes[] = parameterizedType.getActualTypeArguments();
if (iterableParametrizedTypes != null && iterableParametrizedTypes.length > 0) {
final Class iterableParametrizedClass = Class.forName(iterableParametrizedTypes[0].getTypeName());
if (!map.containsKey(iterableParametrizedTypes[0].getTypeName())) {
createMap(map, iterableParametrizedTypes[0], iterableParametrizedClass);
}
classTypeDescription.addFields(complexObjectFields.getName(), createReferenceTypeDescription(iterableParametrizedTypes[0].getTypeName(), JsonType.ARRAY));
} else {
// set type object
final TypeDescription objectTypeDescription = new TypeDescription();
objectTypeDescription.setJsonType(JsonType.PRIMITIVE);
objectTypeDescription.setTypeName(Object.class.getSimpleName());
classTypeDescription.addFields(complexObjectFields.getName(), objectTypeDescription);
}
} else if (objectFieldClass.isArray()) {
classTypeDescription.addFields(complexObjectFields.getName(), addArrayType(map, objectFieldClass));
} else if (JavaReflectionUtils.isInd2ucePrimitive(objectFieldClass)) {
classTypeDescription.addFields(complexObjectFields.getName(), addPrimitiveType(map, objectFieldClass));
} else if (JavaReflectionUtils.isMap(objectFieldClass)) {
if (complexObjectFields.getGenericType() instanceof ParameterizedType) {
final ClassTypeDescription mapTypeDescription = addMapType(map, complexObjectFields.getGenericType());
classTypeDescription.addFields(complexObjectFields.getName(), mapTypeDescription);
}
} else {
// nested Object
if (!map.containsKey(objectFieldClass.getName())) {
createMap(map, objectFieldClass, objectFieldClass);
}
classTypeDescription.addFields(complexObjectFields.getName(), createReferenceTypeDescription(objectFieldClass.getName(), JsonType.OBJECT));
}
}
private static void addFieldDescriptionOfComplexType(Map map, ClassTypeDescription classTypeDescription, Field[] allComplexObjectFields) throws ClassNotFoundException {
for (final Field complexObjectFields : allComplexObjectFields) {
addDescriptionForField(map, classTypeDescription, complexObjectFields);
}
}
private static void addIterableType(Map map, ParameterizedType type) {
final TypeDescription iterableTypeDescription = new TypeDescription();
iterableTypeDescription.setJsonType(JsonType.ARRAY);
final ParameterizedType parameterizedType = type;
final Type iterableParametrizedTypes[] = parameterizedType.getActualTypeArguments();
if (iterableParametrizedTypes != null && iterableParametrizedTypes.length > 0) {
try {
final Class iterableParametrizedClass = Class.forName(iterableParametrizedTypes[0].getTypeName());
if (!map.containsKey(iterableParametrizedTypes[0].getTypeName())) {
createMap(map, iterableParametrizedTypes[0], iterableParametrizedClass);
}
iterableTypeDescription.setTypeName(iterableParametrizedTypes[0].getTypeName());
map.put(iterableParametrizedTypes[0].getTypeName() + "List", iterableTypeDescription);
} catch (final Exception e) {
}
} else {
// set type object
iterableTypeDescription.setTypeName(Object.class.getSimpleName());
}
}
private static ClassTypeDescription addMapType(Map map, Type type) {
if (type instanceof ParameterizedType) {
final Type mapType = ((ParameterizedType)type).getActualTypeArguments()[1];
try {
return createMapTypeDescription(map, mapType);
} catch (final Exception e) {
}
}
return null;
}
private static TypeDescription addPrimitiveType(Map map, Class aClass) {
final TypeDescription primitiveTypeDescription = new TypeDescription();
primitiveTypeDescription.setJsonType(JsonType.PRIMITIVE);
primitiveTypeDescription.setTypeName(aClass.getName());
return primitiveTypeDescription;
}
private static void createMap(Map map, Type type, Class aClass) throws ClassNotFoundException {
if (JavaReflectionUtils.isIterable(aClass)) {
addIterableType(map, (ParameterizedType)type);
} else if (aClass.isArray()) {
map.put(aClass.getComponentType().getName(), addArrayType(map, aClass));
} else if (JavaReflectionUtils.isMap(aClass)) {
addMapType(map, type);
} else if (JavaReflectionUtils.isInd2ucePrimitive(aClass)) {
map.put(aClass.getName(), addPrimitiveType(map, aClass));
} else {
addComplexType(map, type, aClass);
}
}
private static ClassTypeDescription createMapTypeDescription(Map map, Type mapType) throws ClassNotFoundException {
final Class mapTypeClass = Class.forName(mapType.getTypeName());
if (!map.containsKey(MAP_FULL_QUALIFIED_CLASSNAME + GENERIC_BEGIN + mapType.getTypeName() + GENERIC_END)) {
createMap(map, mapType, mapTypeClass);
}
final ClassTypeDescription mapClassTypeDescription = new ClassTypeDescription();
mapClassTypeDescription.setJsonType(JsonType.OBJECT);
mapClassTypeDescription.setTypeName(MAP_FULL_QUALIFIED_CLASSNAME + GENERIC_BEGIN + mapType.getTypeName() + GENERIC_END);
if (JavaReflectionUtils.isInd2ucePrimitive(mapTypeClass)) {
mapClassTypeDescription.addFields("*", createReferenceTypeDescription(mapType.getTypeName(), JsonType.PRIMITIVE));
} else {
mapClassTypeDescription.addFields("*", createReferenceTypeDescription(mapType.getTypeName(), JsonType.OBJECT));
}
map.put(MAP_FULL_QUALIFIED_CLASSNAME + GENERIC_BEGIN + mapType.getTypeName() + GENERIC_END, mapClassTypeDescription);
return mapClassTypeDescription;
}
private static TypeDescription createReferenceTypeDescription(String typeName, JsonType jsonType) {
final TypeDescription typeDescription = new TypeDescription();
typeDescription.setTypeName(typeName);
typeDescription.setJsonType(jsonType);
return typeDescription;
}
/***
* Generates a list of {@link TypeDescription} for a given class.
*
* - For Primitive Types see
* {@link JavaReflectionUtils#isInd2ucePrimitive(Class)} this Method returns a
* singleton list with a {@link TypeDescription} containing the name of the
* primitive like java.lang.Long and JsonType.PRIMITIVE
* - For Iterable Types (Collections) this Method returns a list with a
* {@link TypeDescription} containing the name of the generic content of the
* list (e.g. for List<String> name will be java.lang.String) and
* JsonType.ARRAY. If the generic Type of the list is a non primitive type,
* this method also adds the description for this type (recursively).
* - Array types are handled in the same manner as iterable types.
* - Array types are handled in the same manner as iterable types.
* - For Maps this Method returns a list with a {@link TypeDescription}
* containing the name Map < SOME_TYPE > and JsonType.OBJECT. If the
* generic Type (SOME_TYPE) of the map is a non primitive type, this method
* also adds the description for this type (recursively).
*
*
* @param type Type
* @param typeClass Class
* @return List of TypeDescription
* @throws ClassNotFoundException class not found
*/
public static List createTypeDescription(Type type, Class typeClass) throws ClassNotFoundException {
final Map typeNameAndTypeDescriptionMap = new HashMap<>();
createMap(typeNameAndTypeDescriptionMap, type, typeClass);
return new LinkedList<>(typeNameAndTypeDescriptionMap.values());
}
/**
* Returns a jsonType for a given class.
*
* - All Primitives including the wrapper types, enums, date and string are
* mapped to Primitive
* - All Iterables and primitive arrays are mapped to JsonType.ARRAY
* - The rest is JsonType.OBJECT
*
*
* @param type Class
* @return JsonType
*/
public static JsonType getJsonType(Class type) {
if (JavaReflectionUtils.isInd2ucePrimitive(type)) {
return JsonType.PRIMITIVE;
} else if (JavaReflectionUtils.isIterable(type) || type.isArray()) {
return JsonType.ARRAY;
} else {
return JsonType.OBJECT;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy