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

org.jsonschema2pojo.util.ReflectionHelper Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
/**
 * Copyright © 2010-2020 Nokia
 *
 * 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.
 */

package org.jsonschema2pojo.util;

import static org.jsonschema2pojo.util.TypeUtil.*;

import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.StreamSupport;

import org.jsonschema2pojo.Schema;
import org.jsonschema2pojo.rules.RuleFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JPackage;
import com.sun.codemodel.JType;

public class ReflectionHelper {

  private RuleFactory ruleFactory;

  public ReflectionHelper(RuleFactory ruleFactory) {
    this.ruleFactory = ruleFactory;
  }

  public JType getSuperType(String nodeName, JsonNode node, JPackage jPackage, Schema schema) {
    if (node.has("extends") && node.has("extendsJavaClass")) {
      throw new IllegalStateException("'extends' and 'extendsJavaClass' defined simultaneously");
    }

    JType superType = jPackage.owner().ref(Object.class);
    Schema superTypeSchema = getSuperSchema(node, schema, false);
    if (superTypeSchema != null) {
      superType = ruleFactory.getSchemaRule().apply(nodeName + "Parent", node.get("extends"), node, jPackage, superTypeSchema);
    } else if (node.has("extendsJavaClass")) {
      superType = resolveType(jPackage, node.get("extendsJavaClass").asText());
    }

    return superType;
  }

  public Schema getSuperSchema(JsonNode node, Schema schema, boolean followRefs) {
    if (node.has("extends")) {
      String path;
      if (schema.getId().getFragment() == null) {
        path = "#/extends";
      } else {
        path = "#" + schema.getId().getFragment() + "/extends";
      }

      Schema superSchema = ruleFactory.getSchemaStore().create(schema, path, ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters());

      if (followRefs) {
        superSchema = resolveSchemaRefsRecursive(superSchema);
      }

      return superSchema;
    }
    return null;
  }

  /**
   * This is recursive with searchClassAndSuperClassesForField
   */
  public JFieldVar searchSuperClassesForField(String property, JDefinedClass jclass) {
    JClass superClass = jclass._extends();
    JDefinedClass definedSuperClass = definedClassOrNullFromType(superClass);
    if (definedSuperClass == null) {
      return null;
    }
    return searchClassAndSuperClassesForField(property, definedSuperClass);
  }

  public JDefinedClass getConcreteBuilderClass(JDefinedClass instanceClass) {
    String builderClassname = ruleFactory.getNameHelper().getBuilderClassName(instanceClass);

    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(instanceClass.classes(), Spliterator.ORDERED), false)
            .filter(definedClass -> definedClass.name().equals(builderClassname)).findFirst().orElse(null);
  }

  public JDefinedClass getConcreteBuilderClass(JClass target) {
    String builderClassname = ruleFactory.getNameHelper().getBuilderClassName(target);
    return getAllPackageClasses(target._package()).stream().filter(definedClass -> definedClass.name().equals(builderClassname)).findFirst()
            .orElse(null);
  }

  public JDefinedClass getBaseBuilderClass(JDefinedClass target) {
    String builderClassname = ruleFactory.getNameHelper().getBaseBuilderClassName(target);

    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(target.classes(), Spliterator.ORDERED), false)
        .filter(definedClass -> definedClass.name().equals(builderClassname)).findFirst().orElse(null);
  }

  public JDefinedClass getBaseBuilderClass(JClass target) {
    String builderClassname = ruleFactory.getNameHelper().getBaseBuilderClassName(target);
    return getAllPackageClasses(target._package()).stream().filter(definedClass -> definedClass.name().equals(builderClassname)).findFirst()
        .orElse(null);
  }

  public boolean isFinal(JType superType) {
    try {
      Class javaClass = Class.forName(superType.fullName());
      return Modifier.isFinal(javaClass.getModifiers());
    } catch (ClassNotFoundException e) {
      return false;
    }
  }

  public JFieldVar searchClassAndSuperClassesForField(String property, JDefinedClass jclass) {
    Map fields = jclass.fields();
    JFieldVar field = fields.get(property);
    if (field == null) {
      return searchSuperClassesForField(property, jclass);
    }
    return field;
  }

  private JDefinedClass definedClassOrNullFromType(JType type) {
    if (type == null || type.isPrimitive()) {
      return null;
    }
    JClass fieldClass = type.boxify();
    JPackage jPackage = fieldClass._package();
    try
    {
      return this._getClass(fieldClass.name(), jPackage);
    } catch (NoClassDefFoundError error) {
      String name = fieldClass.name();
      String erasureName = fieldClass.erasure().name();

      if(!Objects.equals(name, erasureName)) {
        ruleFactory.getLogger().debug("Could not get class for type with name: " + name + " trying " + erasureName + " instead.");
        return this._getClass(erasureName, jPackage);
      } else {
        throw error;
      }
    }
  }

  private JDefinedClass _getClass(String name, JPackage _package) {
    return getAllPackageClasses(_package).stream().filter(definedClass -> definedClass.name().equals(name)).findFirst()
        .orElseThrow(() -> new NoClassDefFoundError(name));
  }

  private Collection getAllPackageClasses(JPackage _package) {
    LinkedList result = new LinkedList<>();
    StreamSupport.stream(Spliterators.spliteratorUnknownSize(_package.classes(), Spliterator.ORDERED), false)
        .forEach(_class -> result.addAll(getAllClassClasses(_class)));
    return result;
  }

  private Collection getAllClassClasses(JDefinedClass _class) {
    LinkedList result = new LinkedList<>();
    result.add(_class);

    _class.classes().forEachRemaining(result::add);
    return result;
  }

  private Schema resolveSchemaRefsRecursive(Schema schema) {
    JsonNode schemaNode = schema.getContent();
    if (schemaNode.has("$ref")) {
      schema = ruleFactory.getSchemaStore()
          .create(schema, schemaNode.get("$ref").asText(), ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters());
      return resolveSchemaRefsRecursive(schema);
    }
    return schema;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy