private void serialize(Serializer serializer, Collection<EntityType> models) {
    for (EntityType model : models) {
      try {
        Type type = conf.getTypeMappings().getPathType(model, model, true);
        String packageName = type.getPackageName();
        String className =
            !packageName.isEmpty()
                ? (packageName + "." + type.getSimpleName())
                : type.getSimpleName();

        // skip if type is excluded class or in excluded package
        if (conf.isExcludedPackage(model.getPackageName())
            || conf.isExcludedClass(model.getFullName())) {
          continue;
        }

        Set<TypeElement> elements = context.typeElements.get(model.getFullName());

        if (elements == null) {
          elements = new HashSet<TypeElement>();
        }
        for (Property property : model.getProperties()) {
          if (property.getType().getCategory() == TypeCategory.CUSTOM) {
            Set<TypeElement> customElements =
                context.typeElements.get(property.getType().getFullName());
            if (customElements != null) {
              elements.addAll(customElements);
            }
          }
        }

        processingEnv
            .getMessager()
            .printMessage(Kind.NOTE, "Generating " + className + " for " + elements);
        JavaFileObject fileObject =
            processingEnv
                .getFiler()
                .createSourceFile(className, elements.toArray(new Element[elements.size()]));
        Writer writer = fileObject.openWriter();
        try {
          SerializerConfig serializerConfig = conf.getSerializerConfig(model);
          serializer.serialize(model, serializerConfig, new JavaWriter(writer));
        } finally {
          if (writer != null) {
            writer.close();
          }
        }

      } catch (IOException e) {
        System.err.println(e.getMessage());
        processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage());
      }
    }
  }
  @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;
  }