All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebean.querybean.generator.SimpleQueryBeanWriter Maven / Gradle / Ivy

There is a newer version: 15.8.1
Show newest version
package io.ebean.querybean.generator;


import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.persistence.Entity;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import static io.ebean.querybean.generator.Constants.AT_GENERATED;
import static io.ebean.querybean.generator.Constants.AT_TYPEQUERYBEAN;
import static io.ebean.querybean.generator.Constants.EBEANSERVER;
import static io.ebean.querybean.generator.Constants.GENERATED;
import static io.ebean.querybean.generator.Constants.TQROOTBEAN;
import static io.ebean.querybean.generator.Constants.TYPEQUERYBEAN;

/**
 * A simple implementation that generates and writes query beans.
 */
class SimpleQueryBeanWriter {

  static final String NEWLINE = "\n";

  private final Set importTypes = new TreeSet<>();

  private final List properties = new ArrayList<>();

  private final TypeElement element;

  private final ProcessingContext processingContext;

  private final String beanFullName;
  private boolean writingAssocBean;

  private String destPackage;
  private String origDestPackage;

  private String shortName;
  private String origShortName;

  private Append writer;


  SimpleQueryBeanWriter(TypeElement element, ProcessingContext processingContext) {
    this.element = element;
    this.processingContext = processingContext;

    this.beanFullName = element.getQualifiedName().toString();
    this.destPackage = derivePackage(beanFullName)+".query";
    this.shortName = deriveShortName(beanFullName);
  }

  private void gatherPropertyDetails() {

    importTypes.add(beanFullName);
    if (processingContext.isGeneratedAvailable()) {
      importTypes.add(GENERATED);
    }
    importTypes.add(TQROOTBEAN);
    importTypes.add(TYPEQUERYBEAN);
    importTypes.add(EBEANSERVER);

    addClassProperties();
  }

  /**
   * Recursively add properties from the inheritance hierarchy.
   * 

* Includes properties from mapped super classes and usual inheritance. *

*/ private void addClassProperties() { List fields = processingContext.allFields(element); for (VariableElement field : fields) { PropertyType type = processingContext.getPropertyType(field); if (type != null) { type.addImports(importTypes); properties.add(new PropertyMeta(field.getSimpleName().toString(), type)); } } } /** * Write the type query bean (root bean). */ void writeRootBean() throws IOException { gatherPropertyDetails(); if (isEntity()) { writer = new Append(createFileWriter()); writePackage(); writeImports(); writeClass(); writeAlias(); writeFields(); writeConstructors(); writeStaticAliasClass(); writeClassEnd(); writer.close(); } } private boolean isEntity() { return element.getAnnotation(Entity.class) != null; } /** * Write the type query assoc bean. */ void writeAssocBean() throws IOException { writingAssocBean = true; origDestPackage = destPackage; destPackage = destPackage+".assoc"; origShortName = shortName; shortName = "Assoc"+shortName; prepareAssocBeanImports(); writer = new Append(createFileWriter()); writePackage(); writeImports(); writeClass(); writeFields(); writeConstructors(); writeClassEnd(); writer.close(); } /** * Prepare the imports for writing assoc bean. */ private void prepareAssocBeanImports() { importTypes.remove("io.ebean.typequery.TQRootBean"); importTypes.remove("io.ebean.EbeanServer"); importTypes.add("io.ebean.typequery.TQAssocBean"); if (isEntity()) { importTypes.add("io.ebean.typequery.TQProperty"); importTypes.add(origDestPackage + ".Q" + origShortName); } // remove imports for the same package Iterator importsIterator = importTypes.iterator(); String checkImportStart = destPackage + ".QAssoc"; while (importsIterator.hasNext()){ String importType = importsIterator.next(); if (importType.startsWith(checkImportStart)) { importsIterator.remove(); } } } /** * Write constructors. */ private void writeConstructors() throws IOException { if (writingAssocBean) { writeAssocBeanFetch(); writeAssocBeanConstructor(); } else { writeRootBeanConstructor(); } } /** * Write the constructors for 'root' type query bean. */ private void writeRootBeanConstructor() throws IOException { writer.eol(); writer.append(" /**").eol(); writer.append(" * Construct with a given EbeanServer.").eol(); writer.append(" */").eol(); writer.append(" public Q%s(EbeanServer server) {", shortName).eol(); writer.append(" super(%s.class, server);", shortName).eol(); writer.append(" }").eol(); writer.eol(); writer.append(" /**").eol(); writer.append(" * Construct using the default EbeanServer.").eol(); writer.append(" */").eol(); writer.append(" public Q%s() {", shortName).eol(); writer.append(" super(%s.class);", shortName).eol(); writer.append(" }").eol(); writer.eol(); writer.append(" /**").eol(); writer.append(" * Construct for Alias.").eol(); writer.append(" */").eol(); writer.append(" private Q%s(boolean dummy) {", shortName).eol(); writer.append(" super(dummy);").eol(); writer.append(" }").eol(); } private void writeAssocBeanFetch() { if (isEntity()) { writeAssocBeanFetch("", "Eagerly fetch this association loading the specified properties."); writeAssocBeanFetch("Query", "Eagerly fetch this association using a 'query join' loading the specified properties."); writeAssocBeanFetch("Lazy", "Use lazy loading for this association loading the specified properties."); } } private void writeAssocBeanFetch(String fetchType, String comment) { writer.append(" /**").eol(); writer.append(" * ").append(comment).eol(); writer.append(" */").eol(); writer.append(" @SafeVarargs").eol(); writer.append(" public final R fetch%s(TQProperty... properties) {", fetchType, origShortName).eol(); writer.append(" return fetch%sProperties(properties);", fetchType).eol(); writer.append(" }").eol(); writer.eol(); } /** * Write constructor for 'assoc' type query bean. */ private void writeAssocBeanConstructor() { writer.append(" public Q%s(String name, R root) {", shortName).eol(); writer.append(" super(name, root);").eol(); writer.append(" }").eol(); } /** * Write all the fields. */ private void writeFields() throws IOException { for (PropertyMeta property : properties) { property.writeFieldDefn(writer, shortName, writingAssocBean); writer.eol(); } writer.eol(); } /** * Write the class definition. */ private void writeClass() { if (writingAssocBean) { writer.append("/**").eol(); writer.append(" * Association query bean for %s.", shortName).eol(); writer.append(" * ").eol(); writer.append(" * THIS IS A GENERATED OBJECT, DO NOT MODIFY THIS CLASS.").eol(); writer.append(" */").eol(); if (processingContext.isGeneratedAvailable()) { writer.append(AT_GENERATED).eol(); } writer.append(AT_TYPEQUERYBEAN).eol(); writer.append("public class Q%s extends TQAssocBean<%s,R> {", shortName, origShortName).eol(); } else { writer.append("/**").eol(); writer.append(" * Query bean for %s.", shortName).eol(); writer.append(" * ").eol(); writer.append(" * THIS IS A GENERATED OBJECT, DO NOT MODIFY THIS CLASS.").eol(); writer.append(" */").eol(); if (processingContext.isGeneratedAvailable()) { writer.append(AT_GENERATED).eol(); } writer.append(AT_TYPEQUERYBEAN).eol(); writer.append("public class Q%s extends TQRootBean<%1$s,Q%1$s> {", shortName).eol(); } writer.eol(); } private void writeAlias() throws IOException { if (!writingAssocBean) { writer.append(" private static final Q%s _alias = new Q%1$s(true);", shortName).eol().eol(); writer.append(" /**").eol(); writer.append(" * Return the shared 'Alias' instance used to provide properties to ").eol(); writer.append(" * select() and fetch() ").eol(); writer.append(" */").eol(); writer.append(" public static Q%s alias() {", shortName).eol(); writer.append(" return _alias;").eol(); writer.append(" }").eol(); writer.eol(); } } private void writeStaticAliasClass() throws IOException { writer.eol(); writer.append(" /**").eol(); writer.append(" * Provides static properties to use in select() and fetch() ").eol(); writer.append(" * clauses of a query. Typically referenced via static imports. ").eol(); writer.append(" */").eol(); writer.append(" public static class Alias {").eol(); for (PropertyMeta property : properties) { property.writeFieldAliasDefn(writer, shortName); writer.eol(); } writer.append(" }").eol(); } private void writeClassEnd() { writer.append("}").eol(); } /** * Write all the imports. */ private void writeImports() { for (String importType : importTypes) { writer.append("import %s;", importType).eol(); } writer.eol(); } private void writePackage() { writer.append("package %s;", destPackage).eol().eol(); } private Writer createFileWriter() throws IOException { JavaFileObject jfo = processingContext.createWriter(destPackage + "." + "Q" + shortName, element); return jfo.openWriter(); } private String derivePackage(String name) { int pos = name.lastIndexOf('.'); if (pos == -1) { return ""; } return name.substring(0, pos); } private String deriveShortName(String name) { int pos = name.lastIndexOf('.'); if (pos == -1) { return name; } return name.substring(pos+1); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy