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 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;
  }
  /**
   * process.
   *
   * @param packages a {@link java.util.Collection} object.
   */
  public void process(Collection<CtPackage> packages) {
    if (packages == null) {
      return;
    }
    for (CtPackage package_ : packages) {
      processPackage(package_);
    }

    for (ITypeModel type : registry.getTypes()) {

      boolean hasGlobalConsumes = hasGlobalConsumes(type);
      for (IMethodModel method : type.getMethods()) {
        adjustReturnedAndBodyType(method, hasGlobalConsumes);
      }
    }
  }
  private IMethodModel processMethodReference(CtExecutableReference<?> methodElement) {

    MethodModel methodModel = new MethodModel();
    fillReference(methodModel, methodElement);
    List<CtTypeReference<?>> parameters = methodElement.getParameters();
    Method actualMethod = methodElement.getActualMethod();
    if (actualMethod != null) {
      String canonicalName = actualMethod.getReturnType().getCanonicalName();
      ITypeModel existingType = registry.getType(canonicalName);
      if (existingType != null) {
        methodModel.setReturnedType(existingType);
      }
      if (existingType != null) {
        methodModel.setReturnedType(new ProxyType(registry, canonicalName));
      }
      adjustModifiers(methodModel, actualMethod);
    }
    for (CtTypeReference<?> p : parameters) {
      IParameterModel parameterModel = processParameterReference(p);
      methodModel.addParameter(parameterModel);
    }
    return methodModel;
  }
  /**
   * process.
   *
   * @param classElement a {@link spoon.reflect.declaration.CtType} object.
   */
  public void process(CtType<?> classElement) {

    ITypeModel type = processType(classElement);
    registry.registerTargetType(type);
  }
  private void adjustReturnedAndBodyType(IMethodModel method_, boolean hasGlobalConsumes) {

    if (!(method_ instanceof MethodModel)) {
      return;
    }
    MethodModel method = (MethodModel) method_;

    ITypeModel returnedType = method.getReturnedType();
    if (returnedType != null) {
      if (returnedType instanceof ProxyType) {
        ITypeModel rt = registry.getType(returnedType.getFullyQualifiedName());
        method.setReturnedType(rt);
      }
    }

    boolean hasConsumes = hasGlobalConsumes;

    IAnnotationModel apiOperation = method.getAnnotation(API_OPERATION);
    if (apiOperation != null) {
      IAnnotationModel[] subAnn = apiOperation.getSubAnnotations(JAVAX_CONSUMES.toLowerCase());
      if (subAnn != null) {
        hasConsumes = true;
      }
    }

    IAnnotationModel consumes = method.getAnnotation(JAVAX_CONSUMES);
    if (consumes != null) {
      hasConsumes = true;
    }
    if (!hasConsumes) {
      return;
    }

    IParameterModel[] parameters = method.getParameters();
    for (IParameterModel param_ : parameters) {

      String paramType = param_.getParameterType();
      //			if(paramType.startsWith("java.")){
      //				continue;
      //			}
      if (isPrimitive(paramType)) {
        continue;
      }
      if (param_.hasAnnotation("QueryParam")) {
        continue;
      }
      if (param_.hasAnnotation("HeaderParam")) {
        continue;
      }
      if (param_.hasAnnotation("PathParam")) {
        continue;
      }
      if (param_.hasAnnotation("FormParam")) {
        continue;
      }
      if (param_.hasAnnotation("Context")) {
        continue;
      }

      ITypeModel type = registry.getType(paramType);
      if (type == null) {
        continue;
      }
      //			IAnnotationModel typeAnnotation = type.getAnnotation(JAVAX_XML_TYPE);
      //			if(typeAnnotation==null){
      //				continue;
      //			}
      method.setBodyType(type);
      if (registry.isTargetType(paramType)) {
        break;
      }
    }
  }