private ITypeModel processTypeReference(CtTypeReference<?> typeReference) {
    String qualifiedName = typeReference.getQualifiedName();
    ITypeModel existingType = registry.getType(qualifiedName);
    if (existingType != null) {
      return new ProxyType(registry, qualifiedName);
    }

    CtClass<Object> ctClass = factory.Class().get(qualifiedName);
    if (ctClass != null) {
      return processType(ctClass);
    }

    CtType<Object> ctType = factory.Type().get(qualifiedName);
    if (ctType != null) {
      return processType(ctType);
    }

    TypeModel type = new TypeModel();
    type.setFullyQualifiedName(qualifiedName);
    registry.registerType(type);

    fillReference(type, typeReference);

    Collection<CtExecutableReference<?>> methods = typeReference.getDeclaredExecutables();
    for (CtExecutableReference<?> m : methods) {
      IMethodModel methodModel = processMethodReference(m);
      type.addMethod(methodModel);
    }
    Collection<CtFieldReference<?>> fields = typeReference.getDeclaredFields();
    for (CtFieldReference<?> m : fields) {
      IFieldModel methodModel = processFieldReference(m);
      type.addField(methodModel);
    }
    return new ProxyType(registry, qualifiedName);
  }
  private IMethodModel processMethod(CtMethod<?> m, TypeModel ownerType) {

    MethodModel methodModel = new MethodModel();
    fillBasic(methodModel, m);
    fillTypeParameters(methodModel, m);
    CtTypeReference<?> returnedType = m.getType();
    ITypeModel returnedTypeModel = processTypeReference(returnedType);
    methodModel.setReturnedType(returnedTypeModel);
    fillJAXBType(methodModel, returnedType);

    List<CtParameter<?>> parameters = m.getParameters();
    for (CtParameter<?> p : parameters) {
      IParameterModel parameterModel = processParameter(p);
      methodModel.addParameter(parameterModel);
    }
    String returnedTypeSimpleName = returnedType.getSimpleName();
    String returnedTypeQualifiedname = returnedType.getQualifiedName();
    if (returnedTypeSimpleName.equalsIgnoreCase(returnedTypeQualifiedname)) {
      for (ITypeParameter tp : ownerType.getTypeParameters()) {
        if (returnedType.getSimpleName().equals(tp.getName())) {
          methodModel.setHasGenericReturnType(true);
        }
      }
      for (ITypeParameter tp : methodModel.getTypeParameters()) {
        if (returnedType.getSimpleName().equals(tp.getName())) {
          methodModel.setHasGenericReturnType(true);
        }
      }
    }
    return methodModel;
  }
  private IFieldModel processField(CtField<?> m, TypeModel ownerType) {
    FieldModel fm = new FieldModel();
    fillBasic(fm, m);
    CtTypeReference<?> type = m.getType();
    fillJAXBType(fm, type);

    String typeSimpleName = type.getSimpleName();
    String typeQualifiedname = type.getQualifiedName();
    if (typeSimpleName.equalsIgnoreCase(typeQualifiedname)) {
      for (ITypeParameter tp : ownerType.getTypeParameters()) {
        if (typeSimpleName.equals(tp.getName())) {
          fm.setGeneric(true);
        }
      }
    }
    return fm;
  }
  private ITypeModel processType(CtType<?> classElement) {
    String qualifiedName = classElement.getQualifiedName();
    TypeModel type = (TypeModel) registry.getType(qualifiedName);
    if (type == null) {
      type = new TypeModel();
      type.setFullyQualifiedName(qualifiedName);
    }
    registry.registerType(type);

    fillBasic(type, classElement);

    fillTypeParameters(type, classElement);

    if (classElement instanceof CtType) {
      CtTypeReference<?> superClass = classElement.getSuperclass();
      if (superClass != null) {
        ITypeModel superType = processTypeReference(superClass);
        type.setSuperClass(superType);
      }
      Set<CtTypeReference<?>> interfaces = classElement.getSuperInterfaces();
      if (interfaces != null) {
        ArrayList<ITypeModel> list = new ArrayList<ITypeModel>();
        for (CtTypeReference<?> ref : interfaces) {
          ITypeModel tm = this.processTypeReference(ref);
          if (tm != null) {
            list.add(tm);
          }
        }
        type.setImplementedInterfaces(list.toArray(new ITypeModel[list.size()]));
      }
      Set<CtMethod<?>> methods = ((CtType<?>) classElement).getMethods();
      for (CtMethod<?> m : methods) {
        IMethodModel methodModel = processMethod(m, type);
        type.addMethod(methodModel);
      }
      Collection<CtField<?>> fields = ((CtType<?>) classElement).getFields();
      for (CtField<?> m : fields) {
        IFieldModel methodModel = processField(m, type);
        type.addField(methodModel);
      }
    }
    return type;
  }