All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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