@Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    TYPES = processingEnv.getTypeUtils();
    ELEMENTS = processingEnv.getElementUtils();

    processingEnv
        .getMessager()
        .printMessage(Diagnostic.Kind.NOTE, "Running " + getClass().getSimpleName());

    if (roundEnv.processingOver() || annotations.size() == 0) {
      return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
    }

    if (roundEnv.getRootElements() == null || roundEnv.getRootElements().isEmpty()) {
      processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "No sources to process");
      return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
    }

    conf = createConfiguration(roundEnv);
    context = new Context();
    Set<Class<? extends Annotation>> entityAnnotations = conf.getEntityAnnotations();
    TypeMappings typeMappings = conf.getTypeMappings();
    QueryTypeFactory queryTypeFactory = conf.getQueryTypeFactory();
    this.typeFactory =
        new ExtendedTypeFactory(
            processingEnv, conf, entityAnnotations, typeMappings, queryTypeFactory);
    elementHandler = new TypeElementHandler(conf, typeFactory, typeMappings, queryTypeFactory);
    this.roundEnv = roundEnv;

    // process annotations
    processAnnotations();

    validateMetaTypes();

    // serialize created types
    serializeMetaTypes();

    return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
  }