protected Set<TypeElement> collectElements() {
    Set<TypeElement> elements = new HashSet<TypeElement>();

    // from delegate methods
    elements.addAll(processDelegateMethods());

    // from class annotations
    for (Class<? extends Annotation> annotation : conf.getEntityAnnotations()) {
      for (Element element : getElements(annotation)) {
        if (element instanceof TypeElement) {
          elements.add((TypeElement) element);
        }
      }
    }

    // from package annotations
    if (conf.getEntitiesAnnotation() != null) {
      for (Element element : getElements(conf.getEntitiesAnnotation())) {
        AnnotationMirror mirror =
            TypeUtils.getAnnotationMirrorOfType(element, conf.getEntitiesAnnotation());
        elements.addAll(TypeUtils.getAnnotationValuesAsElements(mirror, "value"));
      }
    }

    // from embedded annotations
    if (conf.getEmbeddedAnnotation() != null) {
      elements.addAll(getEmbeddedTypes());
    }

    // from embedded
    if (conf.isUnknownAsEmbedded()) {
      elements.addAll(getTypeFromProperties(elements));
    }

    // from annotation less supertypes
    elements.addAll(getAnnotationlessSupertypes(elements));

    // register possible embedded types of non-tracked supertypes
    if (conf.getEmbeddedAnnotation() != null) {
      Class<? extends Annotation> embedded = conf.getEmbeddedAnnotation();
      Set<TypeElement> embeddedElements = new HashSet<TypeElement>();
      for (TypeElement element : elements) {
        TypeMirror superTypeMirror = element.getSuperclass();
        while (superTypeMirror != null) {
          TypeElement superTypeElement =
              (TypeElement) processingEnv.getTypeUtils().asElement(superTypeMirror);
          if (superTypeElement != null) {
            List<? extends Element> enclosed = superTypeElement.getEnclosedElements();
            for (Element child : enclosed) {
              if (child.getAnnotation(embedded) != null) {
                handleEmbeddedType(child, embeddedElements);
              }
            }
            superTypeMirror = superTypeElement.getSuperclass();
            if (superTypeMirror instanceof NoType) {
              superTypeMirror = null;
            }
          } else {
            superTypeMirror = null;
          }
        }
      }

      // register found elements
      for (TypeElement element : embeddedElements) {
        if (!elements.contains(element)) {
          elementHandler.handleEntityType(element);
        }
      }
    }

    return elements;
  }