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

com.mangofactory.swagger.readers.operation.parameter.ModelAttributeParameterExpander Maven / Gradle / Ivy

There is a newer version: 1.0.2
Show newest version
package com.mangofactory.swagger.readers.operation.parameter;

import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.mangofactory.swagger.models.alternates.AlternateTypeProvider;
import com.mangofactory.swagger.models.dto.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.mangofactory.swagger.models.ResolvedTypes.*;
import static com.mangofactory.swagger.models.Types.*;
import static java.lang.reflect.Modifier.*;

class ModelAttributeParameterExpander {
  private static final Logger LOGGER = LoggerFactory.getLogger(ModelAttributeParameterExpander.class);
  private AlternateTypeProvider alternateTypeProvider;
  private TypeResolver resolver = new TypeResolver();

  public ModelAttributeParameterExpander(AlternateTypeProvider alternateTypeProvider) {
    this.alternateTypeProvider = alternateTypeProvider;
  }

  public void expand(final String parentName, final Class paramType,
                     final List parameters) {

    Set beanPropNames = getBeanPropertyNames(paramType);
    List fields = getAllFields(paramType);
    LOGGER.debug("Expanding parameter type: {}", paramType);
    for (Field field : fields) {
      LOGGER.debug("Attempting to expanding field: {}", field);

      if (isStatic(field.getModifiers()) || field.isSynthetic() || !beanPropNames.contains(field.getName())) {
        LOGGER.debug("Skipping expansion of field: {}, not a valid bean property", field);
        continue;
      }
      Class resolvedType = getResolvedType(field);
      if (!typeBelongsToJavaPackage(resolvedType) && !field.getType().isEnum()) {
        if (!field.getType().equals(paramType)) {
          LOGGER.debug("Expanding complex field: {} with type: {}", field, resolvedType);
          expand(field.getName(), field.getType(), parameters);
          continue;
        } else {
          LOGGER.warn("Skipping expanding complex field: {} with type: {} as it is recursively defined", field,
                  resolvedType);
        }
      }

      String dataTypeName = typeNameFor(resolvedType);

      if (dataTypeName == null) {
        dataTypeName = resolvedType.getSimpleName();
      }
      LOGGER.debug("Building parameter for field: {}, with type: ", field, resolvedType);
      parameters.add(new ParameterBuilder()
              .forField(field)
              .withDataTypeName(dataTypeName)
              .withParentName(parentName)
              .build());

    }
  }

  private Class getResolvedType(Field field) {
    Class type = field.getType();
    ResolvedType resolvedType = asResolved(resolver, type);
    ResolvedType alternativeType = alternateTypeProvider.alternateFor(resolvedType);
    Class erasedType = alternativeType.getErasedType();
    if (type != erasedType) {
      LOGGER.debug("Found alternative type [{}] for field: [{}-{}]", erasedType, field, type);
    }
    return erasedType;
  }

  private boolean typeBelongsToJavaPackage(Class type) {
    return type.getPackage() == null
            || type.getPackage().getName().startsWith("java")
            || Collection.class.isAssignableFrom(type)
            || Map.class.isAssignableFrom(type);
  }

  private List getAllFields(final Class type) {

    List result = new ArrayList();

    Class i = type;
    while (i != null && i != Object.class) {
      result.addAll(Arrays.asList(i.getDeclaredFields()));
      i = i.getSuperclass();
    }

    return result;
  }

  private Set getBeanPropertyNames(final Class clazz) {

    try {
      Set beanProps = new HashSet();
      PropertyDescriptor[] propDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();

      for (int i = 0; i < propDescriptors.length; i++) {

        if (propDescriptors[i].getReadMethod() != null && propDescriptors[i].getWriteMethod() != null) {
          beanProps.add(propDescriptors[i].getName());
        }
      }

      return beanProps;

    } catch (IntrospectionException e) {
      throw new RuntimeException(new StringBuilder("Failed to get bean properties on ").append(clazz).toString(), e);
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy