private Set<TypeElement> processDelegateMethods() {
    Set<Element> delegateMethods = (Set) getElements(QueryDelegate.class);
    Set<TypeElement> typeElements = new HashSet<TypeElement>();

    for (Element delegateMethod : delegateMethods) {
      ExecutableElement method = (ExecutableElement) delegateMethod;
      Element element = delegateMethod.getEnclosingElement();
      String name = method.getSimpleName().toString();
      Type delegateType = typeFactory.getType(element.asType(), true);
      Type returnType = typeFactory.getType(method.getReturnType(), true);
      List<Parameter> parameters = elementHandler.transformParams(method.getParameters());
      // remove first element
      parameters = parameters.subList(1, parameters.size());

      EntityType entityType = null;
      for (AnnotationMirror annotation : delegateMethod.getAnnotationMirrors()) {
        if (TypeUtils.isAnnotationMirrorOfType(annotation, QueryDelegate.class)) {
          TypeMirror type = TypeUtils.getAnnotationValueAsTypeMirror(annotation, "value");
          if (type != null) {
            entityType = typeFactory.getEntityType(type, true);
          }
        }
      }

      if (entityType != null) {
        registerTypeElement(entityType.getFullName(), (TypeElement) element);
        entityType.addDelegate(
            new Delegate(entityType, delegateType, name, parameters, returnType));
        TypeElement typeElement =
            processingEnv.getElementUtils().getTypeElement(entityType.getFullName());
        boolean isAnnotated = false;
        for (Class<? extends Annotation> ann : conf.getEntityAnnotations()) {
          if (typeElement.getAnnotation(ann) != null) {
            isAnnotated = true;
          }
        }
        if (isAnnotated) {
          // handle also properties of entity type
          typeElements.add(
              processingEnv.getElementUtils().getTypeElement(entityType.getFullName()));
        } else {
          // skip handling properties
          context.extensionTypes.put(entityType.getFullName(), entityType);
          context.allTypes.put(entityType.getFullName(), entityType);
        }
      }
    }

    return typeElements;
  }
  private void processAnnotations() {
    processExclusions();

    Set<TypeElement> elements = collectElements();

    // create meta models
    for (Element element : elements) {
      typeFactory.getEntityType(element.asType(), false);
    }
    for (Element element : elements) {
      typeFactory.getEntityType(element.asType(), true);
    }

    // add properties
    boolean embeddableAnn = conf.getEmbeddableAnnotation() != null;
    boolean altEntityAnn = conf.getAlternativeEntityAnnotation() != null;
    boolean superAnn = conf.getSuperTypeAnnotation() != null;
    for (TypeElement element : elements) {
      EntityType entityType = elementHandler.handleEntityType(element);
      registerTypeElement(entityType.getFullName(), element);
      if (element.getAnnotation(conf.getEntityAnnotation()) != null) {
        context.entityTypes.put(entityType.getFullName(), entityType);
      } else if (altEntityAnn
          && element.getAnnotation(conf.getAlternativeEntityAnnotation()) != null) {
        context.entityTypes.put(entityType.getFullName(), entityType);
      } else if (embeddableAnn && element.getAnnotation(conf.getEmbeddableAnnotation()) != null) {
        context.embeddableTypes.put(entityType.getFullName(), entityType);
      } else if (superAnn && element.getAnnotation(conf.getSuperTypeAnnotation()) != null) {
        context.supertypes.put(entityType.getFullName(), entityType);
      } else if (!entityType.getDelegates().isEmpty()) {
        context.extensionTypes.put(entityType.getFullName(), entityType);
      } else {
        context.embeddableTypes.put(entityType.getFullName(), entityType);
      }
      context.allTypes.put(entityType.getFullName(), entityType);
    }

    // track also methods from external entity types
    for (EntityType entityType : new ArrayList<EntityType>(typeFactory.getEntityTypes())) {
      String fullName = entityType.getFullName();
      if (!context.allTypes.keySet().contains(fullName)) {
        // System.err.println(fullName);
        TypeElement element = processingEnv.getElementUtils().getTypeElement(fullName);
        if (element != null) {
          elementHandler.handleEntityType(element);
        }
      }
    }

    // add external parents
    for (Element element : elements) {
      EntityType entityType = typeFactory.getEntityType(element.asType(), false);
      addExternalParents(entityType);
    }

    // add properties from parents
    Set<EntityType> handled = new HashSet<EntityType>();
    for (EntityType entityType : context.allTypes.values()) {
      addSupertypeFields(entityType, handled);
    }

    processProjectionTypes(elements);

    // extend entity types
    typeFactory.extendTypes();

    context.clean();
  }