Add Query bean filterMany() taking a closure

Query beans also generate a "Assoc" query bean that is used
for the relationships. Previously these were generated into a
.query.assoc package and with this they are generated as an
inner class of the query bean.

This then allows the change where an additional filterMany()
is generated on the "Assoc" bean that takes a closure. This
simplifies the use of query beans for filterMany.

This change to the generated query beans needs a change to the
ebean-agent enhancement.
This commit is contained in:
Rob Bygrave
2023-08-18 22:12:30 +12:00
parent eb0812df16
commit ded4b94e54
12 changed files with 196 additions and 239 deletions
@@ -36,6 +36,11 @@ import java.util.Map;
*/
public interface ExpressionFactory {
/**
* Return a new ExpressionList.
*/
<T> ExpressionList<T> expressionList();
/**
* Path exists - for the given path in a JSON document.
*/
@@ -36,6 +36,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return "sql";
}
@Override
public <T> ExpressionList<T> expressionList() {
return new DefaultExpressionList<>(this);
}
@Override
public Expression textMatch(String propertyName, String search, Match options) {
return new TextMatchExpression(propertyName, search, options);
@@ -56,6 +56,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
this.parentExprList = parentExprList;
}
protected DefaultExpressionList(ExpressionFactory expr) {
this(null, expr, null, new ArrayList<>());
}
private DefaultExpressionList() {
this(null, null, null, new ArrayList<>());
}
@@ -112,10 +116,8 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
* <p>
* If this is the Top level "text" expressions then it detects if explicit or implicit Bool Should, Must etc is required
* to wrap the expressions.
* </p>
* <p>
* If implicit Bool is required SHOULD is used.
* </p>
*/
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
+1 -1
View File
@@ -107,7 +107,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:13.17.1</tile>
<tile>io.ebean.tile:enhancement:13.21.1-beta</tile>
</tiles>
</configuration>
</plugin>
@@ -136,6 +136,13 @@ public abstract class TQRootBean<T, R> {
this.query = null;
}
/** Construct for FilterMany */
protected TQRootBean(ExpressionList<T> filter) {
this.query = null;
this.whereStack = new ArrayStack<>();
whereStack.push(filter);
}
/**
* Return the fetch group.
*/
@@ -4,10 +4,11 @@ import io.ebean.*;
import io.ebean.annotation.Transactional;
import io.ebean.test.LoggedSql;
import io.ebean.types.Inet;
import org.example.domain.*;
import org.example.domain.Address;
import org.example.domain.Country;
import org.example.domain.Customer;
import org.example.domain.otherpackage.PhoneNumber;
import org.example.domain.otherpackage.ValidEmail;
import org.example.domain.query.QAnimal;
import org.example.domain.query.QContact;
import org.example.domain.query.QCustomer;
import org.junit.jupiter.api.Disabled;
@@ -26,7 +27,9 @@ import static io.ebean.StdOperators.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.example.domain.query.QAddress.Alias.country;
import static org.example.domain.query.QAddress.Alias.line1;
import static org.example.domain.query.QContact.Alias.firstName;
import static org.example.domain.query.QContact.Alias.lastName;
import static org.example.domain.query.QCustomer.Alias.*;
import static org.example.domain.query.QCustomer.Alias.billingAddress;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -161,8 +164,8 @@ public class QCustomerTest {
@Test
void equalTo_byProperty() {
Query<Customer> query = new QCustomer()
.select(QCustomer.Alias.id)
.billingAddress.city.eq(QCustomer.Alias.shippingAddress.city)
.select(id)
.billingAddress.city.eq(shippingAddress.city)
.query();
query.findList();
@@ -178,8 +181,8 @@ public class QCustomerTest {
@Test
void notEqual_byProperty() {
Query<Customer> query = new QCustomer()
.select(QCustomer.Alias.id)
.billingAddress.city.ne(QCustomer.Alias.shippingAddress.city)
.select(id)
.billingAddress.city.ne(shippingAddress.city)
.query();
query.findList();
@@ -246,6 +249,37 @@ public class QCustomerTest {
.findList();
}
static final FetchGroup<Customer> FGCustomerContacts = QCustomer.forFetchGroup()
.select(name)
.contacts.fetch(firstName, lastName)
.buildFetchGroup();
@Test
void filterMany() {
var q = new QCustomer()
.select(FGCustomerContacts)
.contacts.filterMany(contacts -> contacts
.firstName.startsWith("r")
.email.isNotNull())
.query();
q.findList();
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' and t1.email is not null order by t0.id");
}
@Test
void filterManySingle() {
var q = new QCustomer()
.select(FGCustomerContacts)
.contacts.filterMany(c -> c.firstName.startsWith("r"))
.query();
q.findList();
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' order by t0.id");
}
@Test
public void testIdIn() {
@@ -277,10 +311,10 @@ public class QCustomerTest {
@Test
public void usingMaster() {
new QCustomer()
.registered.isNull()
.usingMaster()
.findList();
new QCustomer()
.registered.isNull()
.usingMaster()
.findList();
}
@Test
@@ -555,7 +589,7 @@ public class QCustomerTest {
assertContains(new QCustomer().registered.lt(new Date()).query(), " where t0.registered < ?");
assertContains(new QCustomer().registered.before(new Date()).query(), " where t0.registered < ?");
assertContains(new QCustomer().registered.lessThan(new Date()).query(), " where t0.registered < ?");
assertContains(new QCustomer().whenCreated.lt(QCustomer.Alias.whenUpdated).query(), " where t0.when_created < t0.when_updated");
assertContains(new QCustomer().whenCreated.lt(whenUpdated).query(), " where t0.when_created < t0.when_updated");
}
@Test
@@ -563,7 +597,7 @@ public class QCustomerTest {
assertContains(new QCustomer().registered.le(new Date()).query(), " where t0.registered <= ?");
assertContains(new QCustomer().registered.lessOrEqualTo(new Date()).query(), " where t0.registered <= ?");
assertContains(new QCustomer().whenCreated.le(QCustomer.Alias.whenUpdated).query(), " where t0.when_created <= t0.when_updated");
assertContains(new QCustomer().whenCreated.le(whenUpdated).query(), " where t0.when_created <= t0.when_updated");
}
@Test
@@ -571,7 +605,7 @@ public class QCustomerTest {
assertContains(new QCustomer().registered.after(new Date()).query(), " where t0.registered > ?");
assertContains(new QCustomer().registered.gt(new Date()).query(), " where t0.registered > ?");
assertContains(new QCustomer().whenCreated.gt(QCustomer.Alias.whenUpdated).query(), " where t0.when_created > t0.when_updated");
assertContains(new QCustomer().whenCreated.gt(whenUpdated).query(), " where t0.when_created > t0.when_updated");
assertContains(new QCustomer().registered.greaterThan(new Date()).query(), " where t0.registered > ?");
}
@@ -581,7 +615,7 @@ public class QCustomerTest {
assertContains(new QCustomer().registered.ge(new Date()).query(), " where t0.registered >= ?");
assertContains(new QCustomer().registered.greaterOrEqualTo(new Date()).query(), " where t0.registered >= ?");
assertContains(new QCustomer().whenCreated.ge(QCustomer.Alias.whenUpdated).query(), " where t0.when_created >= t0.when_updated");
assertContains(new QCustomer().whenCreated.ge(whenUpdated).query(), " where t0.when_created >= t0.when_updated");
}
private void assertContains(Query<Customer> query, String match) {
@@ -598,8 +632,6 @@ public class QCustomerTest {
.findList();
}
@Test
public void select_assocManyToOne() {
@@ -788,16 +820,16 @@ public class QCustomerTest {
.findList();
new QCustomer()
.add(in(QCustomer.Alias.name, List.of("foo", "bar")))
.add(eq(QCustomer.Alias.currentInet, Inet.of("127.0.0.1")))
.add(in(name, List.of("foo", "bar")))
.add(eq(currentInet, Inet.of("127.0.0.1")))
.findList();
new QCustomer()
//.add(gt(sum(QCustomer.Alias.version), 45))
.add(eq(QCustomer.Alias.version, 45L))
.add(eq(QCustomer.Alias.name, "junk"))
.add(eq(QCustomer.Alias.registered, new Date()))
.add(eq(QCustomer.Alias.whenUpdated, new Timestamp(System.currentTimeMillis())))
.add(eq(version, 45L))
.add(eq(name, "junk"))
.add(eq(registered, new Date()))
.add(eq(whenUpdated, new Timestamp(System.currentTimeMillis())))
.findList();
}
@@ -21,9 +21,7 @@ interface Constants {
String DBNAME = "io.ebean.annotation.DbName";
String TQROOTBEAN = "io.ebean.typequery.TQRootBean";
String TQASSOC = "io.ebean.typequery.TQAssoc";
String TQASSOCBEAN = "io.ebean.typequery.TQAssocBean";
String TQPROPERTY = "io.ebean.typequery.TQProperty";
String TYPEQUERYBEAN = "io.ebean.typequery.TypeQueryBean";
String DATABASE = "io.ebean.Database";
String DB = "io.ebean.DB";
@@ -37,4 +35,7 @@ interface Constants {
String AVAJE_LANG_NULLABLE = "io.avaje.lang.Nullable";
String JAVA_COLLECTION = "java.util.Collection";
String EXPRESSIONLIST = "io.ebean.ExpressionList";
String EXPR = "io.ebean.Expr";
String CONSUMER = "java.util.function.Consumer";
}
@@ -361,20 +361,8 @@ class ProcessingContext implements Constants {
*/
private PropertyType createPropertyTypeAssoc(String fullName) {
String[] split = Split.split(fullName);
String propertyName = "QAssoc" + split[1];
String packageName = packageAppend(split[0]);
return new PropertyTypeAssoc(propertyName, packageName);
}
/**
* Prepend the package to the suffix taking null into account.
*/
private String packageAppend(String origPackage) {
if (origPackage == null) {
return "query.assoc";
} else {
return origPackage + "." + "query.assoc";
}
String propertyName = "Q" + split[1] + ".Assoc";
return new PropertyTypeAssoc(propertyName);
}
/**
@@ -114,7 +114,6 @@ public class Processor extends AbstractProcessor implements Constants {
try {
SimpleQueryBeanWriter beanWriter = new SimpleQueryBeanWriter((TypeElement) element, processingContext);
beanWriter.writeRootBean();
beanWriter.writeAssocBean();
} catch (Throwable e) {
e.printStackTrace();
processingContext.logError(element, "Error generating query beans: " + e);
@@ -31,14 +31,12 @@ class PropertyMeta {
}
void writeFieldDefn(Append writer, String shortName, boolean assoc) {
writer.append(" public ");
writer.append(getTypeDefn(shortName, assoc));
writer.append(" ").append(name).append(";");
}
void writeFieldAliasDefn(Append writer, String shortName) {
writer.append(" public static ");
writer.append(getTypeDefn(shortName, false));
writer.append(" ").append(name).append(" = _alias.").append(name).append(";");
@@ -7,20 +7,13 @@ import java.util.Set;
*/
class PropertyTypeAssoc extends PropertyType {
/**
* The package name for this associated query bean.
*/
private final String assocPackage;
/**
* Construct given the associated bean type name and package.
*
* @param qAssocTypeName the associated bean type name.
* @param assocPackage the associated bean package.
*/
PropertyTypeAssoc(String qAssocTypeName, String assocPackage) {
PropertyTypeAssoc(String qAssocTypeName) {
super(qAssocTypeName);
this.assocPackage = assocPackage;
}
/**
@@ -28,7 +21,7 @@ class PropertyTypeAssoc extends PropertyType {
*/
@Override
void addImports(Set<String> allImports) {
allImports.add(assocPackage + "." + propertyType);
// do nothing
}
}
@@ -8,7 +8,6 @@ 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;
@@ -29,10 +28,8 @@ class SimpleQueryBeanWriter {
private final String beanFullName;
private final boolean isEntity;
private final boolean embeddable;
private boolean writingAssocBean;
private String destPackage;
private String origDestPackage;
private String shortName;
private final String shortInnerName;
private final String origShortName;
@@ -80,16 +77,24 @@ class SimpleQueryBeanWriter {
private void gatherPropertyDetails() {
importTypes.add(Constants.GENERATED);
importTypes.add(beanFullName);
importTypes.add(Constants.TQASSOCBEAN);
importTypes.add(Constants.TQROOTBEAN);
importTypes.add(Constants.TYPEQUERYBEAN);
importTypes.add(Constants.DATABASE);
importTypes.add(Constants.FETCHGROUP);
importTypes.add(Constants.QUERY);
importTypes.add(Constants.TRANSACTION);
importTypes.add(Constants.CONSUMER);
importTypes.add(Constants.EXPR);
importTypes.add(Constants.EXPRESSIONLIST);
if (implementsInterface != null) {
implementsInterfaceFullName = implementsInterface.getQualifiedName().toString();
boolean nested = implementsInterface.getNestingKind().isNested();
implementsInterfaceShortName = Util.shortName(nested, implementsInterfaceFullName);
importTypes.add(Constants.AVAJE_LANG_NULLABLE);
importTypes.add(Constants.JAVA_COLLECTION);
importTypes.add(implementsInterfaceFullName);
}
if (dbName != null) {
importTypes.add(Constants.DB);
@@ -101,7 +106,6 @@ class SimpleQueryBeanWriter {
* Recursively add properties from the inheritance hierarchy.
* <p>
* Includes properties from mapped super classes and usual inheritance.
* </p>
*/
private void addClassProperties() {
for (VariableElement field : processingContext.allFields(element)) {
@@ -131,87 +135,17 @@ class SimpleQueryBeanWriter {
writeFields();
writeConstructors();
writeStaticAliasClass();
writeAssocClass();
writeClassEnd();
writer.close();
}
}
/**
* Write the type query assoc bean.
*/
void writeAssocBean() throws IOException {
writingAssocBean = true;
origDestPackage = destPackage;
destPackage = destPackage + ".assoc";
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(Constants.DB);
importTypes.remove(Constants.TQROOTBEAN);
importTypes.remove(Constants.DATABASE);
importTypes.remove(Constants.FETCHGROUP);
importTypes.remove(Constants.QUERY);
if (embeddable) {
importTypes.add(Constants.TQASSOC);
} else {
importTypes.add(Constants.TQASSOCBEAN);
}
if (isEntity()) {
importTypes.add(Constants.TQPROPERTY);
importTypes.add(origDestPackage + ".Q" + origShortName);
if (implementsInterface != null) {
importTypes.add(Constants.AVAJE_LANG_NULLABLE);
importTypes.add(Constants.JAVA_COLLECTION);
importTypes.add(implementsInterfaceFullName);
}
}
// remove imports for the same package
Iterator<String> 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() {
if (writingAssocBean) {
writeAssocBeanFetch();
writeAssocBeanConstructor();
} else {
writeRootBeanConstructor();
}
}
/**
* Write the constructors for 'root' type query bean.
*/
private void writeRootBeanConstructor() {
writer.eol();
writer.append(" /**").eol();
writer.append(" * Return a query bean used to build a FetchGroup.").eol();
@@ -240,9 +174,7 @@ class SimpleQueryBeanWriter {
writer.eol();
String name = (dbName == null) ? "default" : dbName;
writer.append(" /**").eol();
writer.append(" * Construct using the %s Database.", name).eol();
writer.append(" */").eol();
writer.append(" /** Construct using the %s Database */", name).eol();
writer.append(" public Q%s() {", shortName).eol();
if (dbName == null) {
writer.append(" super(%s.class);", shortName).eol();
@@ -252,9 +184,7 @@ class SimpleQueryBeanWriter {
writer.append(" }").eol();
writer.eol();
writer.append(" /**").eol();
writer.append(" * Construct with a given transaction.", name).eol();
writer.append(" */").eol();
writer.append(" /** Construct with a given transaction */").eol();
writer.append(" public Q%s(Transaction transaction) {", shortName).eol();
if (dbName == null) {
writer.append(" super(%s.class, transaction);", shortName).eol();
@@ -264,29 +194,122 @@ class SimpleQueryBeanWriter {
writer.append(" }").eol();
writer.eol();
writer.append(" /**").eol();
writer.append(" * Construct with a given Database.").eol();
writer.append(" */").eol();
writer.append(" /** Construct with a given Database */").eol();
writer.append(" public Q%s(Database database) {", shortName).eol();
writer.append(" super(%s.class, database);", shortName).eol();
writer.append(" }").eol();
writer.eol();
writer.eol();
writer.append(" /**").eol();
writer.append(" * Construct for Alias.").eol();
writer.append(" */").eol();
writer.append(" /** Private constructor for Alias */").eol();
writer.append(" private Q%s(boolean dummy) {", shortName).eol();
writer.append(" super(dummy);").eol();
writer.append(" }").eol();
writer.eol();
writer.append(" /**").eol();
writer.append(" * Private constructor for FetchGroup building.").eol();
writer.append(" */").eol();
writer.append(" /** Private constructor for FetchGroup building */").eol();
writer.append(" private Q%s(Query<%s> fetchGroupQuery) {", shortName, shortName).eol();
writer.append(" super(fetchGroupQuery);").eol();
writer.append(" }").eol();
writer.eol();
writer.append(" /** Private constructor for filterMany */").eol();
writer.append(" private Q%s(ExpressionList<%s> filter) {", shortName, shortName).eol();
writer.append(" super(filter);").eol();
writer.append(" }").eol();
}
/**
* Write all the fields.
*/
private void writeFields() {
for (PropertyMeta property : properties) {
property.writeFieldDefn(writer, shortName, false);
writer.eol();
}
writer.eol();
}
private void writeClass() {
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();
writer.append(Constants.AT_GENERATED).eol();
writer.append(Constants.AT_TYPEQUERYBEAN).eol();
writer.append("public final class Q%s extends TQRootBean<%1$s,Q%1$s> {", shortName).eol();
writer.eol();
}
private void writeAlias() {
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(" * <code>select()</code> and <code>fetch()</code> ").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() {
writer.eol();
writer.append(" /**").eol();
writer.append(" * Provides static properties to use in <em> select() and fetch() </em>").eol();
writer.append(" * clauses of a query. Typically referenced via static imports. ").eol();
writer.append(" */").eol();
writer.append(" ").append(Constants.AT_GENERATED).eol();
writer.append(" public static final class Alias {").eol();
for (PropertyMeta property : properties) {
property.writeFieldAliasDefn(writer, shortName);
writer.eol();
}
writer.append(" }").eol();
}
private void writeAssocClass() {
writer.eol();
writer.append(" /** Association query bean */").eol();
writer.append(" ").append(Constants.AT_GENERATED).eol();
writer.append(" ").append(Constants.AT_TYPEQUERYBEAN).eol();
if (embeddable) {
writer.append(" public static final class Assoc<R> extends TQAssoc<%s,R> {", shortName, shortInnerName).eol();
} else {
writer.append(" public static final class Assoc<R> extends TQAssocBean<%s,R,Q%s> {", shortName, shortInnerName, origShortName).eol();
}
for (PropertyMeta property : properties) {
writer.append(" ");
property.writeFieldDefn(writer, shortName, true);
writer.eol();
}
writer.eol();
writeAssocBeanConstructor();
writeAssocFilterMany();
writeAssocBeanFetch();
writer.append(" }").eol();
}
private void writeAssocFilterMany() {
writer.append(" public final R filterMany(Consumer<Q%s> apply) {", shortName).eol();
writer.append(" final ExpressionList list = Expr.factory().expressionList();", shortName).eol();
writer.append(" final var qb = new Q%s(list);", shortName).eol();
writer.append(" apply.accept(qb);").eol();
writer.append(" expr().filterMany(_name).addAll(list);").eol();
writer.append(" return _root;").eol();
writer.append(" }").eol();
}
private void writeAssocBeanConstructor() {
writer.append(" public Assoc(String name, R root) {").eol();
writer.append(" super(name, root);").eol();
writer.append(" }").eol().eol();
writer.append(" public Assoc(String name, R root, String prefix) {").eol();
writer.append(" super(name, root, prefix);").eol();
writer.append(" }").eol();
}
private void writeAssocBeanFetch() {
@@ -320,101 +343,6 @@ class SimpleQueryBeanWriter {
writer.eol();
}
private void writeAssocBeanFetch(String fetchType, String comment) {
writer.append(" /**").eol();
writer.append(" * ").append(comment).eol();
writer.append(" */").eol();
writer.append(" @SafeVarargs @SuppressWarnings(\"varargs\")").eol();
writer.append(" public final R fetch%s(TQProperty<Q%s,?>... 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().eol();
writer.append(" public Q%s(String name, R root, String prefix) {", shortName).eol();
writer.append(" super(name, root, prefix);").eol();
writer.append(" }").eol();
}
/**
* Write all the fields.
*/
private void writeFields() {
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();
writer.append(Constants.AT_GENERATED).eol();
writer.append(Constants.AT_TYPEQUERYBEAN).eol();
if (embeddable) {
writer.append("public final class Q%s<R> extends TQAssoc<%s,R> {", shortName, shortInnerName).eol();
} else {
writer.append("public final class Q%s<R> extends TQAssocBean<%s,R,Q%s> {", shortName, shortInnerName, 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();
writer.append(Constants.AT_GENERATED).eol();
writer.append(Constants.AT_TYPEQUERYBEAN).eol();
writer.append("public final class Q%s extends TQRootBean<%1$s,Q%1$s> {", shortName).eol();
}
writer.eol();
}
private void writeAlias() {
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(" * <code>select()</code> and <code>fetch()</code> ").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() {
writer.eol();
writer.append(" /**").eol();
writer.append(" * Provides static properties to use in <em> select() and fetch() </em>").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();
}
@@ -433,7 +361,6 @@ class SimpleQueryBeanWriter {
writer.append("package %s;", destPackage).eol().eol();
}
private Writer createFileWriter() throws IOException {
JavaFileObject jfo = processingContext.createWriter(destPackage + "." + "Q" + shortName, element);
return jfo.openWriter();