Package net.karneim.pojobuilder.analysis

Source Code of net.karneim.pojobuilder.analysis.TypeMFactory

package net.karneim.pojobuilder.analysis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;

import net.karneim.pojobuilder.model.ArrayTypeM;
import net.karneim.pojobuilder.model.PrimitiveTypeM;
import net.karneim.pojobuilder.model.TypeM;
import net.karneim.pojobuilder.model.TypeVariableM;

public class TypeMFactory {

  private final JavaModelAnalyzerUtil javaModelAnalyzerUtil;
  /*
   * This cache prevents an infinite loop when generic type parameters are defined recursivly e.g. A in Pair<A extends
   * Comparable<A>, B>
   */
  private final Map<TypeParameterElement, TypeVariableM> typeVarCache =
      new HashMap<TypeParameterElement, TypeVariableM>();

  public TypeMFactory(JavaModelAnalyzerUtil javaModelAnalyzerUtil) {
    this.javaModelAnalyzerUtil = javaModelAnalyzerUtil;
  }

  public TypeM getTypeM(TypeElement typeElem) {
    String packageName = javaModelAnalyzerUtil.getPackage(typeElem);
    String classname = javaModelAnalyzerUtil.getClassname(typeElem);
    TypeM result = new TypeM(packageName, classname).withTypeParameter(getTypeMArray(typeElem.getTypeParameters()));
    return result;
  }

  public TypeM getTypeM(TypeMirror typeMirror) {
    TypeKind kind = typeMirror.getKind();
    switch (kind) {
      case BOOLEAN:
        return PrimitiveTypeM.BOOLEAN;
      case CHAR:
        return PrimitiveTypeM.CHAR;
      case BYTE:
        return PrimitiveTypeM.BYTE;
      case SHORT:
        return PrimitiveTypeM.SHORT;
      case INT:
        return PrimitiveTypeM.INT;
      case LONG:
        return PrimitiveTypeM.LONG;
      case FLOAT:
        return PrimitiveTypeM.FLOAT;
      case DOUBLE:
        return PrimitiveTypeM.DOUBLE;
      case DECLARED:
        DeclaredType dt = (DeclaredType) typeMirror;
        return getTypeM(dt);
      case VOID:
        return PrimitiveTypeM.VOID;
      case ARRAY:
        ArrayType arrayType = (ArrayType) typeMirror;
        return new ArrayTypeM(getTypeM(arrayType.getComponentType()));
      case TYPEVAR:
        if (typeMirror instanceof TypeVariable) {
          TypeVariable typeVar = (TypeVariable) typeMirror;
          return getTypeVariableM((TypeParameterElement) typeVar.asElement());
        } else {
          throw new UnresolvedTypeException(String.format("Expected TypeVariable for %s (%s)", typeMirror, typeMirror
              .getClass().getName()));
        }
      case ERROR:
        String message =
            String
                .format(
                    "%s could not be resolved! Possibly this class is not compiled, not imported, or not part of the classpath.",
                    typeMirror);
        throw new IllegalArgumentException(message);
      default:
        throw new UnsupportedOperationException(String.format("Unexpected kind %s for typeMirror %s", kind, typeMirror
            .getClass().getName()));
    }
  }

  public TypeM getTypeM(DeclaredType type) {
    TypeElement typeElem = (TypeElement) type.asElement();
    String packageName = javaModelAnalyzerUtil.getPackage(typeElem);
    String classname = javaModelAnalyzerUtil.getClassname(typeElem);
    TypeM result = new TypeM(packageName, classname);

    if (type.getTypeArguments().isEmpty() == false) {
      for (TypeMirror typeArg : type.getTypeArguments()) {
        if (typeArg.getKind() == TypeKind.DECLARED) {
          TypeM typeArgElemTypeM = getTypeM(typeArg);
          result.withTypeParameter(typeArgElemTypeM);
        } else if (typeArg.getKind() == TypeKind.TYPEVAR) {
          TypeVariable typeVar = (TypeVariable) typeArg;
          TypeParameterElement typeParamElem = (TypeParameterElement) typeVar.asElement();
          TypeVariableM var = getTypeVariableM(typeParamElem);
          result.withTypeParameter(var);
        }
      }
    }
    return result;
  }

  public TypeM[] getTypeMArray(List<? extends TypeParameterElement> typeParams) {
    if (typeParams == null) {
      return new TypeM[0];
    }
    TypeM[] result = new TypeM[typeParams.size()];
    for (int i = 0; i < result.length; ++i) {
      TypeParameterElement typeParameterElement = typeParams.get(i);
      TypeVariableM var = getTypeVariableM(typeParameterElement);
      result[i] = var;
    }
    return result;
  }

  private TypeVariableM getTypeVariableM(TypeParameterElement typeParameterElement) {
    TypeVariableM var = typeVarCache.get(typeParameterElement);
    if (var == null) {
      var = new TypeVariableM(typeParameterElement.getSimpleName().toString());
      typeVarCache.put(typeParameterElement, var);
      List<? extends TypeMirror> bounds = typeParameterElement.getBounds();
      for (TypeMirror bound : bounds) {
        TypeM typeM = getTypeM(bound);
        var.whichExtends(typeM);
      }
    }
    return var;
  }

}
TOP

Related Classes of net.karneim.pojobuilder.analysis.TypeMFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.