package org.jooq.codegen;
import static java.util.Arrays.asList;
import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SortOrder.DESC;
import static org.jooq.codegen.AbstractGenerator.Language.JAVA;
import static org.jooq.codegen.AbstractGenerator.Language.KOTLIN;
import static org.jooq.codegen.AbstractGenerator.Language.SCALA;
import static org.jooq.codegen.GenerationUtil.convertToIdentifier;
import static org.jooq.impl.DSL.name;
import static org.jooq.meta.AbstractTypedElementDefinition.getDataType;
import static org.jooq.tools.StringUtils.isBlank;
import java.beans.ConstructorProperties;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import org.jooq.AggregateFunction;
import org.jooq.Catalog;
import org.jooq.Check;
import org.jooq.Configuration;
import org.jooq.Constants;
import org.jooq.DataType;
import org.jooq.Domain;
import org.jooq.EnumType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.Index;
import org.jooq.Name;
import org.jooq.OrderField;
import org.jooq.Parameter;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.Row;
import org.jooq.Schema;
import org.jooq.Sequence;
import org.jooq.SortOrder;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableOptions;
import org.jooq.UDT;
import org.jooq.UDTField;
import org.jooq.UniqueKey;
import org.jooq.codegen.GeneratorStrategy.Mode;
import org.jooq.codegen.GeneratorWriter.CloseResult;
import org.jooq.exception.SQLDialectNotSupportedException;
import org.jooq.impl.AbstractRoutine;
import org.jooq.impl.CatalogImpl;
import org.jooq.impl.DAOImpl;
import org.jooq.impl.DSL;
import org.jooq.impl.DefaultDataType;
import org.jooq.impl.EmbeddableRecordImpl;
import org.jooq.impl.Internal;
import org.jooq.impl.LazySchema;
import org.jooq.impl.LazySupplier;
import org.jooq.impl.PackageImpl;
import org.jooq.impl.SQLDataType;
import org.jooq.impl.SchemaImpl;
import org.jooq.impl.TableImpl;
import org.jooq.impl.TableRecordImpl;
import org.jooq.impl.UDTImpl;
import org.jooq.impl.UDTRecordImpl;
import org.jooq.impl.UpdatableRecordImpl;
import org.jooq.meta.AbstractTypedElementDefinition;
import org.jooq.meta.ArrayDefinition;
import org.jooq.meta.AttributeDefinition;
import org.jooq.meta.CatalogDefinition;
import org.jooq.meta.CheckConstraintDefinition;
import org.jooq.meta.ColumnDefinition;
import org.jooq.meta.ConstraintDefinition;
import org.jooq.meta.DataTypeDefinition;
import org.jooq.meta.Database;
import org.jooq.meta.DefaultDataTypeDefinition;
import org.jooq.meta.Definition;
import org.jooq.meta.DomainDefinition;
import org.jooq.meta.EmbeddableColumnDefinition;
import org.jooq.meta.EmbeddableDefinition;
import org.jooq.meta.EnumDefinition;
import org.jooq.meta.ForeignKeyDefinition;
import org.jooq.meta.IdentityDefinition;
import org.jooq.meta.IndexColumnDefinition;
import org.jooq.meta.IndexDefinition;
import org.jooq.meta.JavaTypeResolver;
import org.jooq.meta.PackageDefinition;
import org.jooq.meta.ParameterDefinition;
import org.jooq.meta.RoutineDefinition;
import org.jooq.meta.SchemaDefinition;
import org.jooq.meta.SequenceDefinition;
import org.jooq.meta.TableDefinition;
import org.jooq.meta.TypedElementDefinition;
import org.jooq.meta.UDTDefinition;
import org.jooq.meta.UniqueKeyDefinition;
import org.jooq.meta.jaxb.GeneratedAnnotationType;
import org.jooq.meta.postgres.PostgresDatabase;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.StopWatch;
import org.jooq.tools.StringUtils;
import org.jooq.tools.reflect.Reflect;
import org.jooq.tools.reflect.ReflectException;
public class JavaGenerator extends AbstractGenerator {
private static final JooqLogger log = JooqLogger.getLogger(JavaGenerator.class);
private static final String NO_FURTHER_INSTANCES_ALLOWED = "No further instances allowed";
private static final Map<DataType<?>, String> SQLDATATYPE_LITERAL_LOOKUP;
private static final Set<String> SQLDATATYPE_WITH_LENGTH;
private static final Set<String> SQLDATATYPE_WITH_PRECISION;
private static final String KLIST = "kotlin.collections.List";
private static final String KMUTABLELIST = "kotlin.collections.MutableList";
private static final Set<String> PRIMITIVE_WRAPPERS = new HashSet<>(Arrays.asList(
Byte.class.getName(),
Short.class.getName(),
Integer.class.getName(),
Long.class.getName(),
Float.class.getName(),
Double.class.getName(),
Boolean.class.getName(),
Character.class.getName(),
"kotlin.Byte",
"kotlin.Short",
"kotlin.Int",
"kotlin.Long",
"kotlin.Float",
"kotlin.Double",
"kotlin.Boolean",
"kotlin.Char"
));
private final StopWatch watch = new StopWatch();
private Database database;
private String isoDate;
private Map<SchemaDefinition, String> schemaVersions;
private Map<CatalogDefinition, String> catalogVersions;
private Set<File> affectedFiles = new LinkedHashSet<>();
private Set<File> modifiedFiles = new LinkedHashSet<>();
private Set<File> directoriesNotForRemoval = new LinkedHashSet<>();
private final boolean java;
private final boolean scala;
private final boolean kotlin;
private final String semicolon;
private final String emptyparens;
private final String tokenVoid;
private final Files fileCache;
static {
SQLDATATYPE_LITERAL_LOOKUP = new IdentityHashMap<>();
SQLDATATYPE_WITH_LENGTH = new HashSet<>();
SQLDATATYPE_WITH_PRECISION = new HashSet<>();
try {
for (java.lang.reflect.Field f : SQLDataType.class.getFields()) {
if (Modifier.isPublic(f.getModifiers()) &&
Modifier.isStatic(f.getModifiers()) &&
Modifier.isFinal(f.getModifiers()))
SQLDATATYPE_LITERAL_LOOKUP.put((DataType<?>) f.get(SQLDataType.class), f.getName());
}
for (java.lang.reflect.Method m : SQLDataType.class.getMethods()) {
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isStatic(m.getModifiers()) &&
((DataType<?>) SQLDataType.class.getField(m.getName()).get(SQLDataType.class)).hasPrecision())
SQLDATATYPE_WITH_PRECISION.add(m.getName());
}
for (java.lang.reflect.Method m : SQLDataType.class.getMethods()) {
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isStatic(m.getModifiers()) &&
((DataType<?>) SQLDataType.class.getField(m.getName()).get(SQLDataType.class)).hasLength() &&
!SQLDATATYPE_WITH_PRECISION.contains(m.getName()))
SQLDATATYPE_WITH_LENGTH.add(m.getName());
}
}
catch (Exception e) {
log.warn(e);
}
}
public JavaGenerator() {
this(JAVA);
}
JavaGenerator(Language language) {
super(language);
this.scala = (language == SCALA);
this.kotlin = (language == KOTLIN);
this.java = (language == JAVA);
this.tokenVoid = (scala || kotlin ? "Unit" : "void");
this.semicolon = (scala || kotlin ? "" : ";");
this.emptyparens = (scala ? "" : "()");
this.fileCache = new Files();
}
@Override
public final void generate(Database db) {
this.isoDate = DatatypeConverter.printDateTime(Calendar.getInstance(TimeZone.getTimeZone("UTC")));
this.schemaVersions = new LinkedHashMap<>();
this.catalogVersions = new LinkedHashMap<>();
this.database = db;
this.database.addFilter(new AvoidAmbiguousClassesFilter());
this.database.setIncludeRelations(generateRelations());
this.database.setTableValuedFunctions(generateTableValuedFunctions());
logDatabaseParameters(db);
log.info("");
log.info("JavaGenerator parameters");
log.info("----------------------------------------------------------");
log.info(" annotations (generated)", generateGeneratedAnnotation()
+ ((!generateGeneratedAnnotation && (useSchemaVersionProvider || useCatalogVersionProvider)) ?
" (forced to true because of <schemaVersionProvider/> or <catalogVersionProvider/>)" : ""));
log.info(" annotations (JPA: any)", generateJPAAnnotations());
log.info(" annotations (JPA: version)", generateJPAVersion());
log.info(" annotations (validation)", generateValidationAnnotations());
log.info(" comments", generateComments());
log.info(" comments on attributes", generateCommentsOnAttributes());
log.info(" comments on catalogs", generateCommentsOnCatalogs());
log.info(" comments on columns", generateCommentsOnColumns());
log.info(" comments on keys", generateCommentsOnKeys());
log.info(" comments on links", generateCommentsOnLinks());
log.info(" comments on packages", generateCommentsOnPackages());
log.info(" comments on parameters", generateCommentsOnParameters());
log.info(" comments on queues", generateCommentsOnQueues());
log.info(" comments on routines", generateCommentsOnRoutines());
log.info(" comments on schemas", generateCommentsOnSchemas());
log.info(" comments on sequences", generateCommentsOnSequences());
log.info(" comments on tables", generateCommentsOnTables());
log.info(" comments on udts", generateCommentsOnUDTs());
log.info(" sources", generateSources());
log.info(" sources on views", generateSourcesOnViews());
log.info(" daos", generateDaos());
log.info(" deprecated code", generateDeprecated());
log.info(" global references (any)", generateGlobalObjectReferences());
log.info(" global references (catalogs)", generateGlobalCatalogReferences());
log.info(" global references (keys)", generateGlobalKeyReferences());
log.info(" global references (links)", generateGlobalLinkReferences());
log.info(" global references (queues)", generateGlobalQueueReferences());
log.info(" global references (routines)", generateGlobalRoutineReferences());
log.info(" global references (schemas)", generateGlobalSchemaReferences());
log.info(" global references (sequences)", generateGlobalSequenceReferences());
log.info(" global references (tables)", generateGlobalTableReferences());
log.info(" global references (udts)", generateGlobalUDTReferences());
log.info(" indexes", generateIndexes());
log.info(" instance fields", generateInstanceFields());
log.info(" interfaces", generateInterfaces()
+ ((!generateInterfaces && generateImmutableInterfaces) ? " (forced to true because of <immutableInterfaces/>)" : ""));
log.info(" interfaces (immutable)", generateInterfaces());
log.info(" javadoc", generateJavadoc());
log.info(" keys", generateKeys());
log.info(" links", generateLinks());
log.info(" pojos", generatePojos()
+ ((!generatePojos && generateDaos) ? " (forced to true because of <daos/>)" :
((!generatePojos && generateImmutablePojos) ? " (forced to true because of <immutablePojos/>)" : "")));
log.info(" pojos (immutable)", generateImmutablePojos());
log.info(" queues", generateQueues());
log.info(" records", generateRecords()
+ ((!generateRecords && generateDaos) ? " (forced to true because of <daos/>)" : ""));
log.info(" routines", generateRoutines());
log.info(" sequences", generateSequences());
log.info(" sequenceFlags", generateSequenceFlags());
log.info(" table-valued functions", generateTableValuedFunctions());
log.info(" tables", generateTables()
+ ((!generateTables && generateRecords) ? " (forced to true because of <records/>)" :
((!generateTables && generateDaos) ? " (forced to true because of <daos/>)" : "")));
log.info(" udts", generateUDTs());
log.info(" relations", generateRelations()
+ ((!generateRelations && generateTables) ? " (forced to true because of <tables/>)" :
((!generateRelations && generateDaos) ? " (forced to true because of <daos/>)" : "")));
log.info("----------------------------------------------------------");
if (!generateInstanceFields()) {
log.warn("");
log.warn("Deprecation warnings");
log.warn("----------------------------------------------------------");
log.warn(" <generateInstanceFields/> = false is deprecated! This feature is no longer maintained and will be removed in jOOQ 4.0. Please adapt your configuration.");
}
log.info("");
logGenerationRemarks(db);
log.info("");
log.info("----------------------------------------------------------");
log.info("Generating catalogs", "Total: " + database.getCatalogs().size());
StopWatch w = new StopWatch();
for (CatalogDefinition catalog : database.getCatalogs()) {
try {
if (generateCatalogIfEmpty(catalog))
generate(catalog);
else
log.info("Excluding empty catalog", catalog);
}
catch (Exception e) {
throw new GeneratorException("Error generating code for catalog " + catalog, e);
}
}
long time = w.split();
log.info("Affected files: " + affectedFiles.size());
log.info("Modified files: " + modifiedFiles.size());
if (modifiedFiles.isEmpty() && catalogVersions.isEmpty() && schemaVersions.isEmpty()) {
log.info(
"No modified files",
"This code generation run has not produced any file modifications.\n"
+ "This means, the schema has not changed, and no other parameters (jOOQ version, driver version, database version,\n"
+ "and any configuration elements) have not changed either.\n\n"
+ "In automated builds, it is recommended to prevent unnecessary code generation runs. This run took: " + StopWatch.format(time) + "\n"
+ "Possible means to prevent this:\n"
+ "- Use manual code generation and check in generated sources: https://www.jooq.org/doc/latest/manual/code-generation/codegen-version-control/\n"
+ "- Use schema version providers: https://www.jooq.org/doc/latest/manual/code-generation/codegen-advanced/codegen-config-database/codegen-database-version-providers/\n"
+ "- Use gradle tasks and inputs: https://github.com/etiennestuder/gradle-jooq-plugin/blob/master/README.md");
}
log.info("Removing excess files");
empty(getStrategy().getFileRoot(), (scala ? ".scala" : kotlin ? ".kt" : ".java"), affectedFiles, directoriesNotForRemoval);
directoriesNotForRemoval.clear();
affectedFiles.clear();
}
private boolean generateCatalogIfEmpty(CatalogDefinition catalog) {
if (generateEmptyCatalogs())
return true;
List<SchemaDefinition> schemas = catalog.getSchemata();
if (schemas.isEmpty())
return false;
for (SchemaDefinition schema : schemas)
if (generateSchemaIfEmpty(schema))
return true;
return false;
}
private final boolean generateSchemaIfEmpty(SchemaDefinition schema) {
if (generateEmptySchemas())
return true;
if (database.getArrays(schema).isEmpty()
&& database.getDomains(schema).isEmpty()
&& database.getEmbeddables(schema).isEmpty()
&& database.getEnums(schema).isEmpty()
&& database.getPackages(schema).isEmpty()
&& database.getRoutines(schema).isEmpty()
&& database.getSequences(schema).isEmpty()
&& database.getTables(schema).isEmpty()
&& database.getUDTs(schema).isEmpty())
return false;
return true;
}
private void generate(CatalogDefinition catalog) {
String newVersion = catalog.getDatabase().getCatalogVersionProvider().version(catalog);
if (StringUtils.isBlank(newVersion)) {
log.info("No schema version is applied for catalog " + catalog.getInputName() + ". Regenerating.");
}
else {
catalogVersions.put(catalog, newVersion);
String oldVersion = readVersion(getFile(catalog), "catalog");
if (StringUtils.isBlank(oldVersion)) {
log.info("No previous version available for catalog " + catalog.getInputName() + ". Regenerating.");
}
else if (!oldVersion.equals(newVersion)) {
log.info("Existing version " + oldVersion + " is not up to date with " + newVersion + " for catalog " + catalog.getInputName() + ". Regenerating.");
}
else {
log.info("Existing version " + oldVersion + " is up to date with " + newVersion + " for catalog " + catalog.getInputName() + ". Ignoring catalog.");
directoriesNotForRemoval.add(getFile(catalog).getParentFile());
return;
}
}
generateCatalog(catalog);
log.info("Generating schemata", "Total: " + catalog.getSchemata().size());
for (SchemaDefinition schema : catalog.getSchemata()) {
try {
if (generateSchemaIfEmpty(schema))
generate(schema);
else
log.info("Excluding empty schema", schema);
}
catch (Exception e) {
throw new GeneratorException("Error generating code for schema " + schema, e);
}
}
}
private void generate(SchemaDefinition schema) {
String newVersion = schema.getDatabase().getSchemaVersionProvider().version(schema);
if (StringUtils.isBlank(newVersion)) {
log.info("No schema version is applied for schema " + schema.getInputName() + ". Regenerating.");
}
else {
schemaVersions.put(schema, newVersion);
String oldVersion = readVersion(getFile(schema), "schema");
if (StringUtils.isBlank(oldVersion)) {
log.info("No previous version available for schema " + schema.getInputName() + ". Regenerating.");
}
else if (!oldVersion.equals(newVersion)) {
log.info("Existing version " + oldVersion + " is not up to date with " + newVersion + " for schema " + schema.getInputName() + ". Regenerating.");
}
else {
log.info("Existing version " + oldVersion + " is up to date with " + newVersion + " for schema " + schema.getInputName() + ". Ignoring schema.");
directoriesNotForRemoval.add(getFile(schema).getParentFile());
return;
}
}
generateSchema(schema);
if (generateGlobalSequenceReferences() && database.getSequences(schema).size() > 0)
generateSequences(schema);
if (generateTables() && database.getTables(schema).size() > 0)
generateTables(schema);
if (generateEmbeddables() && database.getEmbeddables(schema).size() > 0)
generateEmbeddables(schema);
if (generateEmbeddables() && generateInterfaces() && database.getEmbeddables(schema).size() > 0)
generateEmbeddableInterfaces(schema);
if (generateEmbeddables() && generatePojos() && database.getEmbeddables(schema).size() > 0)
generateEmbeddablePojos(schema);
if (generatePojos() && database.getTables(schema).size() > 0)
generatePojos(schema);
if (generateDaos() && database.getTables(schema).size() > 0)
generateDaos(schema);
if (generateGlobalTableReferences() && database.getTables(schema).size() > 0)
generateTableReferences(schema);
if (generateGlobalKeyReferences() && generateRelations() && database.getTables(schema).size() > 0)
generateRelations(schema);
if (generateGlobalIndexReferences() && database.getTables(schema).size() > 0)
generateIndexes(schema);
if (generateRecords() && database.getTables(schema).size() > 0)
generateRecords(schema);
if (generateInterfaces() && database.getTables(schema).size() > 0)
generateInterfaces(schema);
if (generateUDTs() && database.getUDTs(schema).size() > 0)
generateUDTs(schema);
if (generateUDTs() && generatePojos() && database.getUDTs(schema).size() > 0)
generateUDTPojos(schema);
if (generateUDTs() && database.getUDTs(schema).size() > 0)
generateUDTRecords(schema);
if (generateUDTs() && generateInterfaces() && database.getUDTs(schema).size() > 0)
generateUDTInterfaces(schema);
if (generateUDTs() && generateRoutines() && database.getUDTs(schema).size() > 0)
generateUDTRoutines(schema);
if (generateUDTs() && generateGlobalUDTReferences() && database.getUDTs(schema).size() > 0)
generateUDTReferences(schema);
if (generateUDTs() && database.getArrays(schema).size() > 0)
generateArrays(schema);
if (generateUDTs() && database.getEnums(schema).size() > 0)
generateEnums(schema);
if (generateUDTs() && database.getDomains(schema).size() > 0)
generateDomainReferences(schema);
if (generateRoutines() && (database.getRoutines(schema).size() > 0 || hasTableValuedFunctions(schema)))
generateRoutines(schema);
watch.splitInfo("Generation finished: " + schema.getQualifiedName());
log.info("");
}
private class AvoidAmbiguousClassesFilter implements Database.Filter {
private Map<String, String> included = new HashMap<>();
@Override
public boolean exclude(Definition definition) {
if ( definition instanceof ColumnDefinition
|| definition instanceof AttributeDefinition
|| definition instanceof ParameterDefinition)
return false;
String name = getStrategy().getFullJavaClassName(definition);
String nameLC = name.toLowerCase(getStrategy().getTargetLocale());
String existing = included.put(nameLC, name);
if (existing == null)
return false;
log.warn("Ambiguous type name", "The object " + definition.getQualifiedOutputName() + " generates a type " + name + " which conflicts with the existing type " + existing + " on some operating systems. Use a custom generator strategy to disambiguate the types.");
return true;
}
}
private boolean hasTableValuedFunctions(SchemaDefinition schema) {
for (TableDefinition table : database.getTables(schema)) {
if (table.isTableValuedFunction()) {
return true;
}
}
return false;
}
protected void generateRelations(SchemaDefinition schema) {
log.info("Generating Keys");
boolean empty = true;
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, ConstraintDefinition.class));
out.refConflicts(getStrategy().getJavaIdentifiers(database.getUniqueKeys(schema)));
out.refConflicts(getStrategy().getJavaIdentifiers(database.getForeignKeys(schema)));
printGlobalReferencesPackage(out, schema, ConstraintDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "A class modelling foreign key relationships and constraints of tables in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, ConstraintDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
boolean distributeUniqueKeys = database.getUniqueKeys(schema).size() > maxMembersPerInitialiser();
boolean distributeForeignKeys = database.getForeignKeys(schema).size() > maxMembersPerInitialiser();
List<UniqueKeyDefinition> allUniqueKeys = new ArrayList<>();
List<ForeignKeyDefinition> allForeignKeys = new ArrayList<>();
try {
for (UniqueKeyDefinition uniqueKey : database.getUniqueKeys(schema)) {
empty = false;
final String keyType = out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD));
final String keyId = getStrategy().getJavaIdentifier(uniqueKey);
final int block = allUniqueKeys.size() / maxMembersPerInitialiser();
if (allUniqueKeys.isEmpty()) {
out.header("UNIQUE and PRIMARY KEY definitions");
out.println();
}
if (distributeUniqueKeys)
if (scala || kotlin)
out.println("val %s = UniqueKeys%s.%s", keyId, block, keyId);
else
out.println("public static final %s<%s> %s = UniqueKeys%s.%s;", UniqueKey.class, keyType, keyId, block, keyId);
else
printUniqueKey(out, -1, uniqueKey, distributeUniqueKeys);
allUniqueKeys.add(uniqueKey);
}
}
catch (Exception e) {
log.error("Error while generating unique keys for schema " + schema, e);
}
try {
for (ForeignKeyDefinition foreignKey : database.getForeignKeys(schema)) {
empty = false;
final String keyType = out.ref(getStrategy().getFullJavaClassName(foreignKey.getKeyTable(), Mode.RECORD));
final String referencedType = out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD));
final String keyId = getStrategy().getJavaIdentifier(foreignKey);
final int block = allForeignKeys.size() / maxMembersPerInitialiser();
if (allForeignKeys.isEmpty()) {
out.header("FOREIGN KEY definitions");
out.println();
}
if (distributeForeignKeys)
if (scala || kotlin)
out.println("val %s = ForeignKeys%s.%s", keyId, block, keyId);
else
out.println("public static final %s<%s, %s> %s = ForeignKeys%s.%s;", ForeignKey.class, keyType, referencedType, keyId, block, keyId);
else
printForeignKey(out, -1, foreignKey, distributeForeignKeys);
allForeignKeys.add(foreignKey);
}
}
catch (Exception e) {
log.error("Error while generating foreign keys for schema " + schema, e);
}
int uniqueKeyCounter = 0;
int foreignKeyCounter = 0;
if (distributeUniqueKeys || distributeForeignKeys) {
out.header("[#1459] [#10554] [#10653] distribute members to avoid static initialisers > 64kb");
if (distributeUniqueKeys) {
for (UniqueKeyDefinition uniqueKey : allUniqueKeys)
printUniqueKey(out, uniqueKeyCounter++, uniqueKey, distributeUniqueKeys);
if (uniqueKeyCounter > 0)
out.println("}");
}
if (distributeForeignKeys) {
for (ForeignKeyDefinition foreignKey : allForeignKeys)
printForeignKey(out, foreignKeyCounter++, foreignKey, distributeForeignKeys);
if (foreignKeyCounter > 0)
out.println("}");
}
}
generateRelationsClassFooter(schema, out);
if (!kotlin)
out.println("}");
if (empty) {
log.info("Skipping empty keys");
}
else {
closeJavaWriter(out);
watch.splitInfo("Keys generated");
}
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
protected void generateIndexes(SchemaDefinition schema) {
log.info("Generating Indexes");
if (database.getIndexes(schema).isEmpty()) {
log.info("Skipping empty indexes");
return;
}
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, IndexDefinition.class));
out.refConflicts(getStrategy().getJavaIdentifiers(database.getIndexes(schema)));
printGlobalReferencesPackage(out, schema, IndexDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "A class modelling indexes of tables in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, IndexDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
boolean distributeIndexes = database.getIndexes(schema).size() > maxMembersPerInitialiser();
List<IndexDefinition> allIndexes = new ArrayList<>();
out.header("INDEX definitions");
out.println();
for (IndexDefinition index : database.getIndexes(schema)) {
try {
final String keyId = getStrategy().getJavaIdentifier(index);
final int block = allIndexes.size() / maxMembersPerInitialiser();
if (distributeIndexes)
if (scala || kotlin)
out.println("val %s = Indexes%s.%s", keyId, block, keyId);
else
out.println("public static final %s %s = Indexes%s.%s;", Index.class, keyId, block, keyId);
else
printIndex(out, -1, index, distributeIndexes);
allIndexes.add(index);
}
catch (Exception e) {
log.error("Error while generating index " + index, e);
}
}
int indexCounter = 0;
if (distributeIndexes) {
out.header("[#1459] [#10554] [#10653] distribute members to avoid static initialisers > 64kb");
for (IndexDefinition index : allIndexes) {
printIndex(out, indexCounter, index, distributeIndexes);
indexCounter++;
}
if (indexCounter > 0)
out.println("}");
}
generateIndexesClassFooter(schema, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("Indexes generated");
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
protected void printIndex(JavaWriter out, int indexCounter, IndexDefinition index, boolean distributeIndexes) {
final int block = indexCounter / maxMembersPerInitialiser();
if (indexCounter % maxMembersPerInitialiser() == 0) {
if (indexCounter > 0)
out.println("}");
out.println();
if (scala || kotlin)
out.println("private object Indexes%s {", block);
else
out.println("private static class Indexes%s {", block);
}
if (scala || kotlin)
out.print("val %s: %s = ",
getStrategy().getJavaIdentifier(index),
Index.class
);
else
out.print("%sstatic final %s %s = ",
distributeIndexes ? "" : "public ",
Index.class,
getStrategy().getJavaIdentifier(index)
);
printCreateIndex(out, index);
out.println("%s", semicolon);
}
private void printCreateIndex(JavaWriter out, IndexDefinition index) {
String sortFieldSeparator = "";
StringBuilder orderFields = new StringBuilder();
for (IndexColumnDefinition column : index.getIndexColumns()) {
orderFields.append(sortFieldSeparator);
orderFields.append(out.ref(getStrategy().getFullJavaIdentifier(column.getColumn()), colRefSegments(null)));
orderFields.append(column.getSortOrder() == DESC ? ".desc()" : "");
sortFieldSeparator = ", ";
}
if (scala)
out.print("%s.createIndex(%s.name(\"%s\"), %s, Array[%s [_] ](%s), %s)",
Internal.class,
DSL.class,
escapeString(index.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifier(index.getTable()), 2),
OrderField.class,
orderFields,
index.isUnique()
);
else if (kotlin)
out.print("%s.createIndex(%s.name(\"%s\"), %s, arrayOf(%s), %s)",
Internal.class,
DSL.class,
escapeString(index.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifier(index.getTable()), 2),
orderFields,
index.isUnique()
);
else
out.print("%s.createIndex(%s.name(\"%s\"), %s, new %s[] { %s }, %s)",
Internal.class,
DSL.class,
escapeString(index.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifier(index.getTable()), 2),
OrderField.class,
orderFields,
index.isUnique()
);
}
protected void printUniqueKey(JavaWriter out, int uniqueKeyCounter, UniqueKeyDefinition uniqueKey, boolean distributeUniqueKeys) {
final int block = uniqueKeyCounter / maxMembersPerInitialiser();
if (distributeUniqueKeys && uniqueKeyCounter % maxMembersPerInitialiser() == 0) {
if (uniqueKeyCounter > 0)
out.println("}");
out.println();
if (scala || kotlin)
out.println("private object UniqueKeys%s {", block);
else
out.println("private static class UniqueKeys%s {", block);
}
if (scala)
out.print("val %s: %s[%s] = ",
getStrategy().getJavaIdentifier(uniqueKey),
UniqueKey.class,
out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)));
else if (kotlin)
out.print("val %s: %s<%s> = ",
getStrategy().getJavaIdentifier(uniqueKey),
UniqueKey.class,
out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)));
else
out.print("%sstatic final %s<%s> %s = ",
distributeUniqueKeys ? "" : "public ",
UniqueKey.class,
out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)),
getStrategy().getJavaIdentifier(uniqueKey));
printCreateUniqueKey(out, uniqueKey);
out.println("%s", semicolon);
}
private void printCreateUniqueKey(JavaWriter out, UniqueKeyDefinition uniqueKey) {
printCreateNonEmbeddableUniqueKey(out, uniqueKey);
}
private void printCreateNonEmbeddableUniqueKey(JavaWriter out, UniqueKeyDefinition uniqueKey) {
if (scala)
out.print("%s.createUniqueKey(%s, %s.name(\"%s\"), Array([[%s]]).asInstanceOf[Array[%s[%s, _] ] ], %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(uniqueKey.getTable()), 2),
DSL.class,
escapeString(uniqueKey.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifiers(uniqueKey.getKeyColumns()), colRefSegments(null)),
TableField.class,
out.ref(getStrategy().getJavaClassName(uniqueKey.getTable(), Mode.RECORD)),
uniqueKey.enforced());
else if (kotlin)
out.print("%s.createUniqueKey(%s, %s.name(\"%s\"), arrayOf([[%s]]), %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(uniqueKey.getTable()), 2),
DSL.class,
escapeString(uniqueKey.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifiers(uniqueKey.getKeyColumns()), colRefSegments(null)),
uniqueKey.enforced());
else
out.print("%s.createUniqueKey(%s, %s.name(\"%s\"), new %s[] { [[%s]] }, %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(uniqueKey.getTable()), 2),
DSL.class,
escapeString(uniqueKey.getOutputName()),
TableField.class,
out.ref(getStrategy().getFullJavaIdentifiers(uniqueKey.getKeyColumns()), colRefSegments(null)),
uniqueKey.enforced());
}
protected void printForeignKey(JavaWriter out, int foreignKeyCounter, ForeignKeyDefinition foreignKey, boolean distributeForeignKey) {
final int block = foreignKeyCounter / maxMembersPerInitialiser();
if (distributeForeignKey && foreignKeyCounter % maxMembersPerInitialiser() == 0) {
if (foreignKeyCounter > 0)
out.println("}");
out.println();
if (scala || kotlin)
out.println("private object ForeignKeys%s {", block);
else
out.println("private static class ForeignKeys%s {", block);
}
if (scala)
out.print("val %s: %s[%s, %s] = ",
getStrategy().getJavaIdentifier(foreignKey),
ForeignKey.class,
out.ref(getStrategy().getFullJavaClassName(foreignKey.getKeyTable(), Mode.RECORD)),
out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD)));
else if (kotlin)
out.print("val %s: %s<%s, %s> = ",
getStrategy().getJavaIdentifier(foreignKey),
ForeignKey.class,
out.ref(getStrategy().getFullJavaClassName(foreignKey.getKeyTable(), Mode.RECORD)),
out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD)));
else
out.print("%sstatic final %s<%s, %s> %s = ",
distributeForeignKey ? "" : "public ",
ForeignKey.class,
out.ref(getStrategy().getFullJavaClassName(foreignKey.getKeyTable(), Mode.RECORD)),
out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD)),
getStrategy().getJavaIdentifier(foreignKey));
printCreateNonEmbeddableForeignKey(out, foreignKey);
out.println("%s", semicolon);
}
private void printCreateNonEmbeddableForeignKey(JavaWriter out, ForeignKeyDefinition foreignKey) {
if (scala)
out.print("%s.createForeignKey(%s, %s.name(\"%s\"), Array([[%s]]).asInstanceOf[Array[%s[%s, _] ] ], %s, Array([[%s]]).asInstanceOf[Array[%s[%s, _] ] ], %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getKeyTable()), 2),
DSL.class,
escapeString(foreignKey.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getKeyColumns()), colRefSegments(null)),
TableField.class,
out.ref(getStrategy().getJavaClassName(foreignKey.getTable(), Mode.RECORD)),
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getReferencedKey()), 2),
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getReferencedColumns()), colRefSegments(null)),
TableField.class,
out.ref(getStrategy().getJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD)),
foreignKey.enforced()
);
else if (kotlin)
out.print("%s.createForeignKey(%s, %s.name(\"%s\"), arrayOf([[%s]]), %s, arrayOf([[%s]]), %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getKeyTable()), 2),
DSL.class,
escapeString(foreignKey.getOutputName()),
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getKeyColumns()), colRefSegments(null)),
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getReferencedKey())),
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getReferencedColumns()), colRefSegments(null)),
foreignKey.enforced()
);
else
out.print("%s.createForeignKey(%s, %s.name(\"%s\"), new %s[] { [[%s]] }, %s, new %s[] { [[%s]] }, %s)",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getKeyTable()), 2),
DSL.class,
escapeString(foreignKey.getOutputName()),
TableField.class,
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getKeyColumns()), colRefSegments(null)),
out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getReferencedKey()), 2),
TableField.class,
out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getReferencedColumns()), colRefSegments(null)),
foreignKey.enforced()
);
}
protected void generateRecords(SchemaDefinition schema) {
log.info("Generating table records");
for (TableDefinition table : database.getTables(schema)) {
try {
generateRecord(table);
}
catch (Exception e) {
log.error("Error while generating table record " + table, e);
}
}
watch.splitInfo("Table records generated");
}
protected void generateRecord(TableDefinition table) {
JavaWriter out = newJavaWriter(getFile(table, Mode.RECORD));
log.info("Generating record", out.file().getName());
generateRecord0(table, out);
closeJavaWriter(out);
}
protected void generateUDTRecord(UDTDefinition udt) {
JavaWriter out = newJavaWriter(getFile(udt, Mode.RECORD));
log.info("Generating record", out.file().getName());
generateRecord0(udt, out);
closeJavaWriter(out);
}
protected void generateRecord(TableDefinition table, JavaWriter out) {
generateRecord0(table, out);
}
protected void generateUDTRecord(UDTDefinition udt, JavaWriter out) {
generateRecord0(udt, out);
}
private final void generateRecord0(Definition tableUdtOrEmbeddable, JavaWriter out) {
final UniqueKeyDefinition key = (tableUdtOrEmbeddable instanceof TableDefinition)
? ((TableDefinition) tableUdtOrEmbeddable).getPrimaryKey()
: null;
final String className = getStrategy().getJavaClassName(tableUdtOrEmbeddable, Mode.RECORD);
final String tableIdentifier = !(tableUdtOrEmbeddable instanceof EmbeddableDefinition)
? out.ref(getStrategy().getFullJavaIdentifier(tableUdtOrEmbeddable), 2)
: null;
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(tableUdtOrEmbeddable, Mode.RECORD));
final List<? extends TypedElementDefinition<?>> columns = getTypedElements(tableUdtOrEmbeddable);
printPackage(out, tableUdtOrEmbeddable, Mode.RECORD);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateRecordClassJavadoc((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassJavadoc((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTRecordClassJavadoc((UDTDefinition) tableUdtOrEmbeddable, out);
printClassAnnotations(out, tableUdtOrEmbeddable, Mode.RECORD);
if (tableUdtOrEmbeddable instanceof TableDefinition)
printTableJPAAnnotation(out, (TableDefinition) tableUdtOrEmbeddable);
Class<?> baseClass;
if (tableUdtOrEmbeddable instanceof UDTDefinition)
baseClass = UDTRecordImpl.class;
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
baseClass = EmbeddableRecordImpl.class;
else if (generateRelations() && key != null)
baseClass = UpdatableRecordImpl.class;
else
baseClass = TableRecordImpl.class;
List<Definition> embeddablesAndColumns = embeddablesAndColumns(tableUdtOrEmbeddable);
List<Definition> embeddablesAndUnreplacedColumns = embeddablesAndUnreplacedColumns(tableUdtOrEmbeddable);
List<Definition> replacingEmbeddablesAndUnreplacedColumns = replacingEmbeddablesAndUnreplacedColumns(tableUdtOrEmbeddable);
List<Definition> embeddablesOrColumns = embeddablesOrColumns(tableUdtOrEmbeddable);
int degree = replacingEmbeddablesAndUnreplacedColumns.size();
String rowType = null;
String rowTypeRecord = null;
if (generateRecordsImplementingRecordN() && degree > 0 && degree <= Constants.MAX_ROW_DEGREE) {
rowType = refRowType(out, replacingEmbeddablesAndUnreplacedColumns);
if (scala)
rowTypeRecord = out.ref(Record.class.getName() + degree) + "[" + rowType + "]";
else
rowTypeRecord = out.ref(Record.class.getName() + degree) + "<" + rowType + ">";
interfaces.add(rowTypeRecord);
}
if (generateInterfaces())
interfaces.add(out.ref(getStrategy().getFullJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE)));
if (scala)
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("class %s extends %s[%s](%s.fieldsRow(%s.%s))[[before= with ][separator= with ][%s]] {",
className,
baseClass,
className,
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(((EmbeddableDefinition) tableUdtOrEmbeddable).getTable()), 2),
getStrategy().getJavaIdentifier(tableUdtOrEmbeddable),
interfaces
);
else
out.println("class %s extends %s[%s](%s)[[before= with ][separator= with ][%s]] {",
className,
baseClass,
className,
tableIdentifier,
interfaces
);
else if (kotlin)
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("open class %s() : %s<%s>(%s.fieldsRow(%s.%s))[[before=, ][%s]] {",
className,
baseClass,
className,
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(((EmbeddableDefinition) tableUdtOrEmbeddable).getTable()), 2),
getStrategy().getJavaIdentifier(tableUdtOrEmbeddable),
interfaces
);
else
out.println("open class %s() : %s<%s>(%s)[[before=, ][%s]] {",
className,
baseClass,
className,
tableIdentifier,
interfaces
);
else
out.println("public class %s extends %s<%s>[[before= implements ][%s]] {", className, baseClass, className, interfaces);
out.printSerial();
for (Definition column : embeddablesAndUnreplacedColumns) {
final int index = replacingEmbeddablesAndUnreplacedColumns.indexOf(column);
if (column instanceof EmbeddableDefinition) {
final EmbeddableDefinition embeddable = (EmbeddableDefinition) column;
generateEmbeddableRecordSetter(embeddable, index, out);
generateEmbeddableRecordGetter(embeddable, index, out);
}
else {
final TypedElementDefinition<?> c = (TypedElementDefinition<?>) column;
if (tableUdtOrEmbeddable instanceof TableDefinition) {
generateRecordSetter(c, index, out);
generateRecordGetter(c, index, out);
}
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition) {
generateEmbeddableSetter(c, index, out);
generateEmbeddableGetter(c, index, out);
}
else {
generateUDTRecordSetter(c, index, out);
generateUDTRecordGetter(c, index, out);
}
}
}
if (generateRelations() && key != null) {
int keyDegree = key.getKeyColumns().size();
if (keyDegree <= Constants.MAX_ROW_DEGREE) {
final String recordNType = out.ref(Record.class.getName() + keyDegree);
final String keyType = refRowType(out, key.getKeyColumns());
out.header("Primary key information");
if (scala) {
out.println();
out.println("override def key: %s[%s] = super.key.asInstanceOf[ %s[%s] ]", recordNType, keyType, recordNType, keyType);
}
else if (kotlin) {
out.println();
out.println("override fun key(): %s<%s> = super.key() as %s<%s>", recordNType, keyType, recordNType, keyType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> key() {", recordNType, keyType);
out.println("return (%s) super.key();", recordNType);
out.println("}");
}
}
}
if (tableUdtOrEmbeddable instanceof UDTDefinition) {
for (RoutineDefinition routine : ((UDTDefinition) tableUdtOrEmbeddable).getRoutines()) {
boolean instance = routine.getInParameters().size() > 0
&& routine.getInParameters().get(0).getInputName().toUpperCase(getStrategy().getTargetLocale()).equals("SELF");
try {
if (!routine.isSQLUsable()) {
printConvenienceMethodProcedure(out, routine, instance);
}
else {
if (!routine.isAggregate()) {
printConvenienceMethodFunction(out, routine, instance);
}
}
} catch (Exception e) {
log.error("Error while generating routine " + routine, e);
}
}
}
if (generateRecordsImplementingRecordN() && degree > 0 && degree <= Constants.MAX_ROW_DEGREE) {
final String recordNType = out.ref(Row.class.getName() + degree);
out.header("Record%s type implementation", degree);
if (scala) {
out.println();
out.println("override def fieldsRow: %s[%s] = super.fieldsRow.asInstanceOf[ %s[%s] ]", recordNType, rowType, recordNType, rowType);
}
else if (kotlin) {
out.println();
out.println("override fun fieldsRow(): %s<%s> = super.fieldsRow() as %s<%s>", recordNType, rowType, recordNType, rowType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> fieldsRow() {", recordNType, rowType);
out.println("return (%s) super.fieldsRow();", recordNType);
out.println("}");
}
if (scala) {
out.println();
out.println("override def valuesRow: %s[%s] = super.valuesRow.asInstanceOf[ %s[%s] ]", recordNType, rowType, recordNType, rowType);
}
else if (kotlin) {
out.println("override fun valuesRow(): %s<%s> = super.valuesRow() as %s<%s>", recordNType, rowType, recordNType, rowType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> valuesRow() {", recordNType, rowType);
out.println("return (%s) super.valuesRow();", recordNType);
out.println("}");
}
for (int i = 1; i <= degree; i++) {
Definition column = replacingEmbeddablesAndUnreplacedColumns.get(i - 1);
if (column instanceof EmbeddableColumnDefinition)
column = ((EmbeddableColumnDefinition) column).getReferencingColumn();
final String colTypeFull = getJavaType(column, out);
final String colType = out.ref(colTypeFull);
final String colIdentifierFull = out.ref(getStrategy().getFullJavaIdentifier(column), colRefSegments(column));
final String colIdentifier = getStrategy().getJavaIdentifier(column);
if (scala) {
printDeprecationIfUnknownType(out, colTypeFull);
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("override def field%s: %s[%s] = field(%s).asInstanceOf[%s [%s] ]",
i,
Field.class,
colType,
i - 1,
Field.class,
colType
);
else
out.println("override def field%s: %s[%s] = %s", i, Field.class, colType, colIdentifierFull);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, colTypeFull);
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("override fun field%s(): %s<%s?> = field(%s) as %s<%s?>",
i,
Field.class,
colType,
i - 1,
Field.class,
colType
);
else if (tableUdtOrEmbeddable instanceof UDTDefinition)
out.println("public override fun field%s(): %s<%s%s> = %s.%s", i, Field.class, colType, column instanceof EmbeddableDefinition ? "" : "?", out.ref(getStrategy().getFullJavaIdentifier(((AttributeDefinition) column).getContainer()), 2), colIdentifier);
else
out.println("override fun field%s(): %s<%s%s> = %s", i, Field.class, colType, column instanceof EmbeddableDefinition ? "" : "?", colIdentifierFull);
}
else {
if (printDeprecationIfUnknownType(out, colTypeFull))
out.override();
else
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> field%s() {", Field.class, colType, i);
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("return (%s<%s>) field(%s);", Field.class, colType, i - 1);
else
out.println("return %s;", colIdentifierFull);
out.println("}");
}
}
for (int i = 1; i <= degree; i++) {
Definition column = replacingEmbeddablesAndUnreplacedColumns.get(i - 1);
final String colTypeFull = getJavaType(column, out);
final String colType = out.ref(colTypeFull);
final String colGetter = getStrategy().getJavaGetterName(column, Mode.RECORD);
final String colMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (scala) {
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override def component%s: %s = %s", i, colType, colGetter);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override fun component%s(): %s? = %s", i, colType, colMember);
}
else {
if (printDeprecationIfUnknownType(out, colTypeFull))
out.override();
else
out.overrideInherit();
printNullableOrNonnullAnnotation(out, column);
out.println("public %s component%s() {", colType, i);
out.println("return %s();", colGetter);
out.println("}");
}
}
for (int i = 1; i <= degree; i++) {
Definition column = replacingEmbeddablesAndUnreplacedColumns.get(i - 1);
final String colTypeFull = getJavaType(column, out);
final String colType = out.ref(colTypeFull);
final String colGetter = getStrategy().getJavaGetterName(column, Mode.RECORD);
final String colMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (scala) {
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override def value%s: %s = %s", i, colType, colGetter);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override fun value%s(): %s? = %s", i, colType, colMember);
}
else {
if (printDeprecationIfUnknownType(out, colTypeFull))
out.override();
else
out.overrideInherit();
printNullableOrNonnullAnnotation(out, column);
out.println("public %s value%s() {", colType, i);
out.println("return %s();", colGetter);
out.println("}");
}
}
for (int i = 1; i <= degree; i++) {
Definition column = replacingEmbeddablesAndUnreplacedColumns.get(i - 1);
final String colTypeFull = getJavaType(column, out);
final String colType = out.ref(colTypeFull);
final String colSetter = getStrategy().getJavaSetterName(column, Mode.RECORD);
final String colMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (scala) {
out.println();
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override def value%s(value: %s): %s = {", i, colType, className);
out.println("%s(value)", colSetter);
out.println("this");
out.println("}");
}
else if (kotlin) {
out.println();
printDeprecationIfUnknownType(out, colTypeFull);
out.println("override fun value%s(value: %s%s): %s {", i, colType, column instanceof EmbeddableDefinition ? "" : "?", className);
out.println("this.%s = value", colMember);
out.println("return this");
out.println("}");
}
else {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
if (printDeprecationIfUnknownType(out, colTypeFull))
out.override();
else
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s value%s([[before=@][after= ][%s]]%s value) {", className, i, list(nullableAnnotation), varargsIfArray(colType));
out.println("%s(value);", colSetter);
out.println("return this;");
out.println("}");
}
}
List<String> arguments = new ArrayList<>(degree);
List<String> calls = new ArrayList<>(degree);
for (int i = 1; i <= degree; i++) {
final Definition column = replacingEmbeddablesAndUnreplacedColumns.get(i - 1);
final String colType = getJavaTypeRef(column, out);
if (scala) {
arguments.add("value" + i + " : " + colType);
calls.add("this.value" + i + "(value" + i + ")");
}
else if (kotlin) {
arguments.add("value" + i + ": " + colType + (column instanceof EmbeddableDefinition ? "" : "?"));
calls.add("this.value" + i + "(value" + i + ")");
}
else {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
arguments.add((nullableAnnotation == null ? "" : "@" + nullableAnnotation + " ") + colType + " value" + i);
calls.add("value" + i + "(value" + i + ");");
}
}
if (scala) {
out.println();
out.println("override def values([[%s]]): %s = {", arguments, className);
for (String call : calls)
out.println(call);
out.println("this");
out.println("}");
}
else if (kotlin) {
out.println();
out.println("override fun values([[%s]]): %s {", arguments, className);
for (String call : calls)
out.println(call);
out.println("return this");
out.println("}");
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s values([[%s]]) {", className, arguments);
for (String call : calls)
out.println(call);
out.println("return this;");
out.println("}");
}
}
if (generateInterfaces())
printFromAndInto(out, tableUdtOrEmbeddable, Mode.RECORD);
if (scala || kotlin) {}
else {
out.header("Constructors");
out.javadoc("Create a detached %s", className);
out.println("public %s() {", className);
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("super(%s.fieldsRow(%s.%s));",
Internal.class,
out.ref(getStrategy().getFullJavaIdentifier(((EmbeddableDefinition) tableUdtOrEmbeddable).getTable()), 2),
getStrategy().getJavaIdentifier(tableUdtOrEmbeddable));
else
out.println("super(%s);", tableIdentifier);
out.println("}");
}
generateRecordConstructor(tableUdtOrEmbeddable, out, replacingEmbeddablesAndUnreplacedColumns);
if (!replacingEmbeddablesAndUnreplacedColumns.equals(embeddablesOrColumns))
generateRecordConstructor(tableUdtOrEmbeddable, out, embeddablesOrColumns);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateRecordClassFooter((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassFooter((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTRecordClassFooter((UDTDefinition) tableUdtOrEmbeddable, out);
out.println("}");
}
@FunctionalInterface
private interface EmbeddableFilter {
void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable);
}
private static final EmbeddableFilter EMBEDDABLES_OR_COLUMNS = new EmbeddableFilter() {
@Override
public void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable) {
if (duplicates.add(embeddable))
result.set(index, embeddable);
else
result.remove(index);
}
};
private static final EmbeddableFilter EMBEDDABLES_AND_COLUMNS = new EmbeddableFilter() {
@Override
public void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable) {
if (duplicates.add(embeddable))
result.add(index, embeddable);
}
};
private List<Definition> embeddablesOrColumns(Definition tableUdtOrEmbeddable) {
return embeddablesAndColumns(tableUdtOrEmbeddable, EMBEDDABLES_OR_COLUMNS);
}
private List<Definition> embeddablesAndUnreplacedColumns(Definition tableUdtOrEmbeddable) {
return embeddablesAndColumns(tableUdtOrEmbeddable, new EmbeddableFilter() {
@Override
public void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable) {
EMBEDDABLES_AND_COLUMNS.accept(result, duplicates, index, embeddable);
}
});
}
private List<Definition> replacingEmbeddablesAndUnreplacedColumns(Definition tableUdtOrEmbeddable) {
return embeddablesAndColumns(tableUdtOrEmbeddable, new EmbeddableFilter() {
@Override
public void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable) {
}
});
}
private List<Definition> embeddablesAndColumns(Definition tableUdtOrEmbeddable) {
return embeddablesAndColumns(tableUdtOrEmbeddable, EMBEDDABLES_AND_COLUMNS);
}
private List<Definition> embeddablesAndColumns(Definition tableUdtOrEmbeddable, EmbeddableFilter filter) {
List<Definition> result = new ArrayList<>(getTypedElements(tableUdtOrEmbeddable));
if (tableUdtOrEmbeddable instanceof TableDefinition) {
Set<EmbeddableDefinition> duplicates = new HashSet<>();
for (EmbeddableDefinition embeddable : ((TableDefinition) tableUdtOrEmbeddable).getReferencedEmbeddables()) {
for (EmbeddableColumnDefinition embeddableColumn : embeddable.getColumns()) {
int index = result.indexOf(embeddableColumn.getReferencingColumn());
if (index >= 0)
filter.accept(result, duplicates, index, embeddable);
}
}
}
return result;
}
private void generateRecordConstructor(
Definition tableUdtOrEmbeddable,
JavaWriter out,
Collection<? extends Definition> columns
) {
final String className = getStrategy().getJavaClassName(tableUdtOrEmbeddable, Mode.RECORD);
final String tableIdentifier = !(tableUdtOrEmbeddable instanceof EmbeddableDefinition)
? out.ref(getStrategy().getFullJavaIdentifier(tableUdtOrEmbeddable), 2)
: null;
final int degree = columns.size();
if (degree > 0 && degree < 256) {
List<String> arguments = new ArrayList<>(degree);
List<String> properties = new ArrayList<>(degree);
for (Definition column : columns) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.DEFAULT);
final String type = getJavaTypeRef(column, out);
if (scala) {
arguments.add(columnMember + " : " + type);
}
else if (kotlin) {
arguments.add(columnMember + ": " + type + "? = null");
}
else {
final String nullableAnnotation = column instanceof EmbeddableDefinition
? null
: nullableOrNonnullAnnotation(out, column);
arguments.add((nullableAnnotation == null ? "" : "@" + nullableAnnotation + " ") + type + " " + columnMember);
}
properties.add("\"" + escapeString(columnMember) + "\"");
}
out.javadoc("Create a detached, initialised %s", className);
if (scala) {
out.println("def this([[%s]]) = {", arguments);
out.println("this()", tableIdentifier);
out.println();
}
else if (kotlin) {
out.println("constructor([[%s]]): this() {", arguments);
}
else {
if (generateConstructorPropertiesAnnotationOnRecords())
out.println("@%s({ [[%s]] })", ConstructorProperties.class, properties);
out.println("public %s([[%s]]) {", className, arguments);
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
out.println("this();", tableIdentifier);
else
out.println("super(%s);", tableIdentifier);
out.println();
}
for (Definition column : columns) {
if (column instanceof EmbeddableDefinition) {
if (kotlin)
out.println("this.%s = %s ?: %s([[%s]])",
getStrategy().getJavaMemberName(column, Mode.POJO),
getStrategy().getJavaMemberName(column, Mode.POJO),
out.ref(getStrategy().getFullJavaClassName(column, Mode.RECORD)),
Collections.nCopies(((EmbeddableDefinition) column).getColumns().size(), "null"));
else if (scala)
out.println("this.%s(%s)", getStrategy().getJavaSetterName(column, Mode.RECORD), getStrategy().getJavaMemberName(column, Mode.DEFAULT));
else
out.println("%s(%s);", getStrategy().getJavaSetterName(column, Mode.RECORD), getStrategy().getJavaMemberName(column, Mode.DEFAULT));
}
else {
if (kotlin)
out.println("this.%s = %s",
getStrategy().getJavaMemberName(column, Mode.POJO),
getStrategy().getJavaMemberName(column, Mode.POJO));
else if (scala)
out.println("this.%s(%s)", getStrategy().getJavaSetterName(column, Mode.RECORD), getStrategy().getJavaMemberName(column, Mode.POJO));
else
out.println("%s(%s);", getStrategy().getJavaSetterName(column, Mode.RECORD), getStrategy().getJavaMemberName(column, Mode.POJO));
}
}
out.println("}");
}
}
private String getJavaType(Definition column, JavaWriter out) {
return column instanceof EmbeddableDefinition
? getStrategy().getFullJavaClassName(column, Mode.RECORD)
: getJavaType(((TypedElementDefinition<?>) column).getType(resolver(out)), out);
}
private String getJavaTypeRef(Definition column, JavaWriter out) {
return out.ref(getJavaType(column, out));
}
protected void generateRecordSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordSetter0(column, index, out);
}
protected void generateEmbeddableSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordSetter0(column, index, out);
}
protected void generateUDTRecordSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordSetter0(column, index, out);
}
private final void generateRecordSetter0(TypedElementDefinition<?> column, int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(column.getContainer(), Mode.RECORD);
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
final String setter = getStrategy().getJavaSetterName(column, Mode.RECORD);
final String member = getStrategy().getJavaMemberName(column, Mode.POJO);
final String typeFull = getJavaType(column.getType(resolver(out)), out);
final String type = out.ref(typeFull);
final String name = column.getQualifiedOutputName();
final boolean isUDT = column.getType(resolver(out)).isUDT();
final boolean isArray = column.getType(resolver(out)).isArray();
final boolean isUDTArray = column.getType(resolver(out)).isArray() && database.getArray(column.getType(resolver(out)).getSchema(), column.getType(resolver(out)).getQualifiedUserType()).getElementType(resolver(out)).isUDT();
final boolean override = generateInterfaces() && !generateImmutableInterfaces() && !isUDT;
if (!(generateInterfaces() && isArray)) {
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Setter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (scala) {
out.println("def %s(value: %s): %s = {", setter, type, setterReturnType);
out.println("set(%s, value)", index);
if (generateFluentSetters())
out.println("this");
out.println("}");
}
else if (kotlin) {
out.println();
if (column instanceof ColumnDefinition)
printColumnJPAAnnotation(out, (ColumnDefinition) column);
printValidationAnnotation(out, column);
out.println("%svar %s: %s?",
(generateInterfaces() ? "override " : ""), member, type);
out.tab(1).println("set(value) = set(%s, value)", index);
}
else {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
out.overrideIf(override);
out.println("public %s %s([[before=@][after= ][%s]]%s value) {", setterReturnType, setter, list(nullableAnnotation), varargsIfArray(type));
out.println("set(%s, value);", index);
if (generateFluentSetters())
out.println("return this;");
out.println("}");
}
}
if (generateInterfaces() && !generateImmutableInterfaces() && (isUDT || isArray)) {
final String columnTypeFull = getJavaType(column.getType(resolver(out, Mode.RECORD)), out, Mode.RECORD);
final String columnType = out.ref(columnTypeFull);
final String columnTypeInterface = out.ref(getJavaType(column.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
if (!printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("Setter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
out.override();
if (scala) {
out.println("def %s(value: %s): %s = {", setter, columnTypeInterface, setterReturnType);
out.println("if (value == null)");
out.println("set(%s, null)", index);
out.println("else");
out.println("set(%s, value.into(new %s()))", index, type);
if (generateFluentSetters())
out.println("this");
out.println("}");
}
else if (kotlin) {}
else {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
out.println("public %s %s([[before=@][after= ][%s]]%s value) {", setterReturnType, setter, list(nullableAnnotation), varargsIfArray(columnTypeInterface));
out.println("if (value == null)");
out.println("set(%s, null);", index);
if (isUDT) {
out.println("else");
out.println("set(%s, value.into(new %s()));", index, type);
}
else if (isArray) {
final ArrayDefinition array = database.getArray(column.getType(resolver(out)).getSchema(), column.getType(resolver(out)).getQualifiedUserType());
final String componentType = out.ref(getJavaType(array.getElementType(resolver(out, Mode.RECORD)), out, Mode.RECORD));
final String componentTypeInterface = out.ref(getJavaType(array.getElementType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
out.println("else {");
out.println("%s a = new %s();", columnType, columnType);
out.println();
out.println("for (%s i : value)", componentTypeInterface);
if (isUDTArray)
out.println("a.add(i.into(new %s()));", componentType);
else
out.println("a.add(i);", componentType);
out.println();
out.println("set(1, a);");
out.println("}");
}
if (generateFluentSetters())
out.println("return this;");
out.println("}");
}
}
}
protected void generateEmbeddableRecordSetter(EmbeddableDefinition embeddable, int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(embeddable.getReferencingTable(), Mode.RECORD);
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
final String member = getStrategy().getJavaMemberName(embeddable, Mode.POJO);
final String setter = getStrategy().getJavaSetterName(embeddable, Mode.RECORD);
final String typeFull = getStrategy().getFullJavaClassName(embeddable, generateInterfaces() ? Mode.INTERFACE : Mode.RECORD);
final String type = out.ref(typeFull);
final String name = embeddable.getQualifiedOutputName();
final boolean override = generateInterfaces() && !generateImmutableInterfaces();
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Setter for the embeddable <code>%s</code>.", name);
if (scala) {
out.println("def %s(value: %s): %s = {", setter, type, setterReturnType);
}
else if (kotlin) {
out.println();
out.println("%svar %s: %s",
(generateInterfaces() ? "override " : ""), member, type);
out.tab(1).println("set(value) {");
}
else {
out.overrideIf(override);
out.println("public %s %s([[before=@][after= ][%s]]%s value) {", setterReturnType, setter, list(nonnullAnnotation(out)), type);
}
if (index > -1) {
if (kotlin)
out.tab(1).println("set(%s, value)", index);
else
out.println("set(%s, value)%s", index, semicolon);
}
else {
for (EmbeddableColumnDefinition column : embeddable.getColumns()) {
final int position = column.getReferencingColumnPosition() - 1;
if (kotlin)
out.tab(1).println("set(%s, value.%s)",
position,
getStrategy().getJavaMemberName(column, Mode.POJO)
);
else
out.println("set(%s, value.%s%s)%s",
position,
getStrategy().getJavaGetterName(column, Mode.RECORD),
emptyparens,
semicolon
);
}
}
if (generateFluentSetters())
if (scala)
out.println("this");
else
out.println("return this%s", semicolon);
if (kotlin)
out.tab(1).println("}");
else
out.println("}");
}
protected void generateRecordGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordGetter0(column, index, out);
}
protected void generateEmbeddableGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordGetter0(column, index, out);
}
protected void generateUDTRecordGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateRecordGetter0(column, index, out);
}
private final void generateRecordGetter0(TypedElementDefinition<?> column, int index, JavaWriter out) {
final String getter = getStrategy().getJavaGetterName(column, Mode.RECORD);
final String typeFull = getJavaType(column.getType(resolver(out)), out);
final String type = out.ref(typeFull);
final String name = column.getQualifiedOutputName();
if (!kotlin) {
if (!printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Getter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (column instanceof ColumnDefinition)
printColumnJPAAnnotation(out, (ColumnDefinition) column);
printValidationAnnotation(out, column);
}
printNullableOrNonnullAnnotation(out, column);
boolean override = generateInterfaces();
if (scala) {
out.println("def %s: %s = get(%s).asInstanceOf[%s]", scalaWhitespaceSuffix(getter), type, index, type);
}
else if (kotlin) {
out.tab(1).println("get() = get(%s) as %s%s", index, type, column instanceof EmbeddableDefinition ? "" : "?");
}
else {
out.overrideIf(override);
out.println("public %s %s() {", type, getter);
if (Object.class.getName().equals(typeFull))
out.println("return get(%s);", index);
else
out.println("return (%s) get(%s);", type, index);
out.println("}");
}
}
protected void generateEmbeddableRecordGetter(EmbeddableDefinition embeddable, int index, JavaWriter out) {
final String getter = getStrategy().getJavaGetterName(embeddable, Mode.RECORD);
final String typeFull = getStrategy().getFullJavaClassName(embeddable, Mode.RECORD);
final String type = out.ref(typeFull);
final String name = embeddable.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Getter for the embeddable <code>%s</code>.", name);
boolean override = generateInterfaces();
if (scala) {
out.print("def %s: %s = ", scalaWhitespaceSuffix(getter), type);
}
else if (kotlin) {
out.tab(1).print("get() = ");
}
else {
out.overrideIf(override);
out.println("public %s %s() {", type, getter);
}
if (index > -1) {
if (scala)
out.println("get(%s).asInstanceOf[%s]", index, type);
else if (kotlin)
out.tab(1).println("get(%s) as %s", index, type);
else {
if (Object.class.getName().equals(typeFull))
out.println("return get(%s);", index);
else
out.println("return (%s) get(%s);", type, index);
}
}
else {
if (scala)
out.println("new %s(", type);
else if (kotlin)
out.tab(1).println("%s(", type);
else
out.println("return new %s(", type);
String separator = " ";
for (EmbeddableColumnDefinition column : embeddable.getColumns()) {
final String columnType = out.ref(getJavaType(column.getReferencingColumn().getType(resolver(out)), out));
final int position = column.getReferencingColumnPosition() - 1;
if (scala)
out.println("%sget(%s).asInstanceOf[%s]", separator, position, columnType);
else if (kotlin)
out.tab(1).println("%sget(%s) as %s?", separator, position, columnType);
else {
if (Object.class.getName().equals(typeFull))
out.println("%sget(%s)", separator, position);
else
out.println("%s(%s) get(%s)", separator, columnType, position);
}
separator = ", ";
}
if (scala)
out.println(")");
else if (kotlin)
out.tab(1).println(")");
else
out.println(");");
}
if (scala || kotlin) {}
else
out.println("}");
}
private int colRefSegments(Definition column) {
if (column instanceof TypedElementDefinition && ((TypedElementDefinition<?>) column).getContainer() instanceof UDTDefinition)
return 2;
if (!getStrategy().getInstanceFields())
return 2;
return 3;
}
@SuppressWarnings("unused")
protected void (TableDefinition table, JavaWriter out) {}
protected void generateRecordClassJavadoc(TableDefinition table, JavaWriter out) {
if (generateCommentsOnTables())
printClassJavadoc(out, table);
else
printClassJavadoc(out, "The table <code>" + table.getQualifiedInputName() + "</code>.");
}
@SuppressWarnings("unused")
protected void (EmbeddableDefinition embeddable, JavaWriter out) {}
protected void generateEmbeddableClassJavadoc(EmbeddableDefinition embeddable, JavaWriter out) {
printClassJavadoc(out, "The embeddable <code>" + embeddable.getQualifiedInputName() + "</code>.");
}
private String refRowType(JavaWriter out, Collection<? extends Definition> columns) {
StringBuilder result = new StringBuilder();
String separator = "";
for (Definition column : columns) {
result.append(separator);
result.append(getJavaTypeRef(column, out));
if (kotlin && !(column instanceof EmbeddableDefinition))
result.append("?");
separator = ", ";
}
return result.toString();
}
protected void generateInterfaces(SchemaDefinition schema) {
log.info("Generating table interfaces");
for (TableDefinition table : database.getTables(schema)) {
try {
generateInterface(table);
} catch (Exception e) {
log.error("Error while generating table interface " + table, e);
}
}
watch.splitInfo("Table interfaces generated");
}
protected void generateInterface(TableDefinition table) {
JavaWriter out = newJavaWriter(getFile(table, Mode.INTERFACE));
log.info("Generating interface", out.file().getName());
generateInterface(table, out);
closeJavaWriter(out);
}
protected void generateUDTInterface(UDTDefinition udt) {
JavaWriter out = newJavaWriter(getFile(udt, Mode.INTERFACE));
log.info("Generating interface", out.file().getName());
generateInterface0(udt, out);
closeJavaWriter(out);
}
protected void generateEmbeddableInterface(EmbeddableDefinition embeddable) {
JavaWriter out = newJavaWriter(getFile(embeddable, Mode.INTERFACE));
log.info("Generating interface", out.file().getName());
generateInterface0(embeddable, out);
closeJavaWriter(out);
}
protected void generateInterface(TableDefinition table, JavaWriter out) {
generateInterface0(table, out);
}
protected void generateUDTInterface(UDTDefinition udt, JavaWriter out) {
generateInterface0(udt, out);
}
private final void generateInterface0(Definition tableUdtOrEmbeddable, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE);
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(tableUdtOrEmbeddable, Mode.INTERFACE));
printPackage(out, tableUdtOrEmbeddable, Mode.INTERFACE);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateInterfaceClassJavadoc((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassJavadoc((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTInterfaceClassJavadoc((UDTDefinition) tableUdtOrEmbeddable, out);
printClassAnnotations(out, tableUdtOrEmbeddable, Mode.INTERFACE);
if (tableUdtOrEmbeddable instanceof TableDefinition)
printTableJPAAnnotation(out, (TableDefinition) tableUdtOrEmbeddable);
if (scala)
out.println("trait %s[[before= extends ][%s]] {", className, interfaces);
else if (kotlin)
out.println("interface %s[[before= : ][%s]] {", className, interfaces);
else
out.println("public interface %s[[before= extends ][%s]] {", className, interfaces);
List<? extends TypedElementDefinition<?>> typedElements = getTypedElements(tableUdtOrEmbeddable);
for (int i = 0; i < typedElements.size(); i++) {
TypedElementDefinition<?> column = typedElements.get(i);
if (!generateImmutableInterfaces())
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateInterfaceSetter(column, i, out);
else
generateUDTInterfaceSetter(column, i, out);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateInterfaceGetter(column, i, out);
else
generateUDTInterfaceGetter(column, i, out);
}
if (tableUdtOrEmbeddable instanceof TableDefinition) {
List<EmbeddableDefinition> embeddables = ((TableDefinition) tableUdtOrEmbeddable).getReferencedEmbeddables();
for (int i = 0; i < embeddables.size(); i++) {
EmbeddableDefinition embeddable = embeddables.get(i);
generateEmbeddableInterfaceSetter(embeddable, i, out);
generateEmbeddableInterfaceGetter(embeddable, i, out);
}
}
if (!generateImmutableInterfaces()) {
String local = getStrategy().getJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE);
String qualified = out.ref(getStrategy().getFullJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE));
out.header("FROM and INTO");
out.javadoc("Load data from another generated Record/POJO implementing the common interface %s", local);
if (scala)
out.println("def from(from: %s)", qualified);
else if (kotlin)
out.println("fun from(from: %s)", qualified);
else
out.println("public void from(%s from);", qualified);
if (scala) {}
else {
out.javadoc("Copy data into another generated Record/POJO implementing the common interface %s", local);
if (kotlin)
out.println("fun <E : %s> into(into: E): E", qualified);
else
out.println("public <E extends %s> E into(E into);", qualified);
}
}
if (tableUdtOrEmbeddable instanceof TableDefinition)
generateInterfaceClassFooter((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassFooter((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTInterfaceClassFooter((UDTDefinition) tableUdtOrEmbeddable, out);
out.println("}");
}
protected void generateInterfaceSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateInterfaceSetter0(column, index, out);
}
protected void generateEmbeddableInterfaceSetter(EmbeddableDefinition embeddable, @SuppressWarnings("unused") int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(embeddable.getReferencingTable(), Mode.INTERFACE);
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
final String setter = getStrategy().getJavaSetterName(embeddable, Mode.INTERFACE);
final String typeFull = getStrategy().getFullJavaClassName(embeddable, Mode.INTERFACE);
final String type = out.ref(typeFull);
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Setter for <code>%s</code>.", embeddable.getQualifiedOutputName());
if (scala)
out.println("def %s(value: %s): %s", setter, type, setterReturnType);
else if (kotlin) {}
else
out.println("public %s %s([[before=@][after= ][%s]]%s value);", setterReturnType, setter, list(nonnullAnnotation(out)), type);
}
protected void generateUDTInterfaceSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateInterfaceSetter0(column, index, out);
}
private final void generateInterfaceSetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(column.getContainer(), Mode.INTERFACE);
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
final String setter = getStrategy().getJavaSetterName(column, Mode.INTERFACE);
final String typeFull = getJavaType(column.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE);
final String type = out.ref(typeFull);
final String name = column.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Setter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (scala)
out.println("def %s(value: %s): %s", setter, type, setterReturnType);
else if (kotlin) {}
else
out.println("public %s %s([[before=@][after= ][%s]]%s value);", setterReturnType, setter, list(nullableOrNonnullAnnotation(out, column)), varargsIfArray(type));
}
protected void generateInterfaceGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateInterfaceGetter0(column, index, out);
}
protected void generateEmbeddableInterfaceGetter(EmbeddableDefinition embeddable, @SuppressWarnings("unused") int index, JavaWriter out) {
final String member = getStrategy().getJavaMemberName(embeddable, Mode.POJO);
final String getter = getStrategy().getJavaGetterName(embeddable, Mode.INTERFACE);
final String typeFull = getStrategy().getFullJavaClassName(embeddable, Mode.INTERFACE);
final String type = out.ref(typeFull);
final String name = embeddable.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Getter for <code>%s</code>.", name);
printNonnullAnnotation(out);
if (scala)
out.println("def %s: %s", scalaWhitespaceSuffix(getter), type);
else if (kotlin)
out.println("%s %s: %s", (generateImmutableInterfaces() ? "val" : "var"), member, type);
else
out.println("public %s %s();", type, getter);
}
protected void generateUDTInterfaceGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generateInterfaceGetter0(column, index, out);
}
private final void generateInterfaceGetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
final String member = getStrategy().getJavaMemberName(column, Mode.POJO);
final String getter = getStrategy().getJavaGetterName(column, Mode.INTERFACE);
final String typeFull = getJavaType(column.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE);
final String type = out.ref(typeFull);
final String name = column.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
out.javadoc("Getter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (column instanceof ColumnDefinition)
printColumnJPAAnnotation(out, (ColumnDefinition) column);
printValidationAnnotation(out, column);
printNullableOrNonnullAnnotation(out, column);
if (scala)
out.println("def %s: %s", scalaWhitespaceSuffix(getter), type);
else if (kotlin)
out.println("%s %s: %s?", (generateImmutableInterfaces() ? "val" : "var"), member, type);
else
out.println("public %s %s();", type, getter);
}
@SuppressWarnings("unused")
protected void (TableDefinition table, JavaWriter out) {}
protected void generateInterfaceClassJavadoc(TableDefinition table, JavaWriter out) {
if (generateCommentsOnTables())
printClassJavadoc(out, table);
else
printClassJavadoc(out, "The table <code>" + table.getQualifiedInputName() + "</code>.");
}
protected void generateUDTs(SchemaDefinition schema) {
log.info("Generating UDTs");
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDT(schema, udt);
}
catch (Exception e) {
log.error("Error while generating udt " + udt, e);
}
}
watch.splitInfo("UDTs generated");
}
@SuppressWarnings("unused")
protected void generateUDT(SchemaDefinition schema, UDTDefinition udt) {
JavaWriter out = newJavaWriter(getFile(udt));
log.info("Generating UDT ", out.file().getName());
if (log.isDebugEnabled())
for (AttributeDefinition attribute : udt.getAttributes())
log.debug("With attribute", "name=" + attribute.getOutputName() + ", matching type names=" + attribute.getDefinedType().getMatchNames());
generateUDT(udt, out);
closeJavaWriter(out);
}
protected void generateUDT(UDTDefinition udt, JavaWriter out) {
final SchemaDefinition schema = udt.getSchema();
final PackageDefinition pkg = udt.getPackage();
final boolean synthetic = udt.isSynthetic();
final String className = getStrategy().getJavaClassName(udt);
final String recordType = out.ref(getStrategy().getFullJavaClassName(udt, Mode.RECORD));
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(udt, Mode.DEFAULT));
final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
final String packageId = pkg == null ? null : out.ref(getStrategy().getFullJavaIdentifier(pkg), 2);
final String udtId = out.ref(getStrategy().getJavaIdentifier(udt), 2);
printPackage(out, udt);
if (scala) {
out.println("object %s {", className);
printSingletonInstance(out, udt);
for (AttributeDefinition attribute : udt.getAttributes()) {
final String attrId = out.ref(getStrategy().getJavaIdentifier(attribute), 2);
out.javadoc("The attribute <code>%s</code>.[[before= ][%s]]", attribute.getQualifiedOutputName(), list(escapeEntities(comment(attribute))));
out.println("val %s = %s.%s", attrId, udtId, attrId);
}
out.println("}");
out.println();
}
generateUDTClassJavadoc(udt, out);
printClassAnnotations(out, udt, Mode.DEFAULT);
if (scala) {
out.println("class %s extends %s[%s](\"%s\", null, %s, %s)[[before= with ][separator= with ][%s]] {", className, UDTImpl.class, recordType, escapeString(udt.getOutputName()), packageId, synthetic, interfaces);
}
else if (kotlin) {
out.println("public open class %s : %s<%s>(\"%s\", null, %s, %s)[[before=, ][%s]] {", className, UDTImpl.class, recordType, escapeString(udt.getOutputName()), packageId, synthetic, interfaces);
out.println();
out.println("public companion object {");
out.javadoc("The reference instance of <code>%s</code>", udt.getQualifiedOutputName());
out.println("public val %s: %s = %s()", getStrategy().getJavaIdentifier(udt), className, className);
out.println("}");
}
else {
out.println("public class %s extends %s<%s>[[before= implements ][%s]] {", className, UDTImpl.class, recordType, interfaces);
out.printSerial();
printSingletonInstance(out, udt);
}
printRecordTypeMethod(out, udt);
for (AttributeDefinition attribute : udt.getAttributes()) {
final String attrTypeFull = getJavaType(attribute.getType(resolver(out)), out);
final String attrType = out.ref(attrTypeFull);
final String attrTypeRef = getJavaTypeReference(attribute.getDatabase(), attribute.getType(resolver(out)), out);
final String attrId = out.ref(getStrategy().getJavaIdentifier(attribute), 2);
final String attrName = attribute.getName();
final List<String> converter = out.ref(list(attribute.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(attribute.getType(resolver(out)).getBinding()));
if (!printDeprecationIfUnknownType(out, attrTypeFull))
out.javadoc("The attribute <code>%s</code>.[[before= ][%s]]", attribute.getQualifiedOutputName(), list(escapeEntities(comment(attribute))));
if (scala)
out.println("private val %s: %s[%s, %s] = %s.createField(%s.name(\"%s\"), %s, this, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ")",
attrId, UDTField.class, recordType, attrType, UDTImpl.class, DSL.class, escapeString(attrName), attrTypeRef, escapeString(""), converter, binding);
else if (kotlin)
out.println("public val %s: %s<%s, %s> = %s.createField(%s.name(\"%s\"), %s, this, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ")",
attrId, UDTField.class, recordType, attrType, UDTImpl.class, DSL.class, escapeString(attrName), attrTypeRef, escapeString(""), converter, binding);
else
out.println("public static final %s<%s, %s> %s = createField(%s.name(\"%s\"), %s, %s, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ");",
UDTField.class, recordType, attrType, attrId, DSL.class, escapeString(attrName), attrTypeRef, udtId, escapeString(""), converter, binding);
}
for (RoutineDefinition routine : udt.getRoutines()) {
try {
if (!routine.isSQLUsable()) {
printConvenienceMethodProcedure(out, routine, false);
}
else {
if (!routine.isAggregate())
printConvenienceMethodFunction(out, routine, false);
printConvenienceMethodFunctionAsField(out, routine, false);
printConvenienceMethodFunctionAsField(out, routine, true);
}
} catch (Exception e) {
log.error("Error while generating routine " + routine, e);
}
}
if (scala || kotlin) {
}
else {
out.javadoc(NO_FURTHER_INSTANCES_ALLOWED);
out.println("private %s() {", className);
out.println("super(\"%s\", null, %s, %s);", udt.getOutputName(), packageId, synthetic);
out.println("}");
}
if (scala) {
out.println();
out.println("override def getSchema: %s = %s", Schema.class, schemaId);
}
else if (kotlin) {
out.println();
out.println("public override fun getSchema(): %s = %s", Schema.class, schemaId);
}
else {
out.overrideInherit();
out.println("public %s getSchema() {", Schema.class);
out.println("return %s != null ? %s : new %s(%s.name(\"%s\"));", schemaId, schemaId, SchemaImpl.class, DSL.class, schema.getOutputName());
out.println("}");
}
generateUDTClassFooter(udt, out);
out.println("}");
closeJavaWriter(out);
}
@SuppressWarnings("unused")
protected void (UDTDefinition udt, JavaWriter out) {}
protected void generateUDTClassJavadoc(UDTDefinition udt, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, udt);
else
printClassJavadoc(out, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
}
protected void generateUDTPojos(SchemaDefinition schema) {
log.info("Generating UDT POJOs");
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDTPojo(udt);
}
catch (Exception e) {
log.error("Error while generating UDT POJO " + udt, e);
}
}
watch.splitInfo("UDT POJOs generated");
}
@SuppressWarnings("unused")
protected void (UDTDefinition udt, JavaWriter out) {}
protected void generateUDTPojoClassJavadoc(UDTDefinition udt, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, udt);
else
printClassJavadoc(out, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
}
protected void generateUDTInterfaces(SchemaDefinition schema) {
log.info("Generating UDT interfaces");
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDTInterface(udt);
}
catch (Exception e) {
log.error("Error while generating UDT interface " + udt, e);
}
}
watch.splitInfo("UDT interfaces generated");
}
@SuppressWarnings("unused")
protected void (UDTDefinition udt, JavaWriter out) {}
protected void generateUDTInterfaceClassJavadoc(UDTDefinition udt, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, udt);
else
printClassJavadoc(out, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
}
protected void generateUDTRecords(SchemaDefinition schema) {
log.info("Generating UDT records");
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDTRecord(udt);
}
catch (Exception e) {
log.error("Error while generating UDT record " + udt, e);
}
}
watch.splitInfo("UDT records generated");
}
@SuppressWarnings("unused")
protected void (UDTDefinition udt, JavaWriter out) {}
protected void generateUDTRecordClassJavadoc(UDTDefinition udt, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, udt);
else
printClassJavadoc(out, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
}
protected void generateUDTRoutines(SchemaDefinition schema) {
for (UDTDefinition udt : database.getUDTs(schema)) {
if (udt.getRoutines().size() > 0) {
try {
log.info("Generating member routines");
for (RoutineDefinition routine : udt.getRoutines()) {
try {
generateRoutine(schema, routine);
}
catch (Exception e) {
log.error("Error while generating member routines " + routine, e);
}
}
} catch (Exception e) {
log.error("Error while generating UDT " + udt, e);
}
watch.splitInfo("Member procedures routines");
}
}
}
protected void generateUDTReferences(Definition schemaOrPackage) {
String logSuffix = schemaOrPackage instanceof SchemaDefinition ? "" : (" for package " + schemaOrPackage.getOutputName());
log.info("Generating UDT references" + logSuffix);
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schemaOrPackage, UDTDefinition.class));
printGlobalReferencesPackage(out, schemaOrPackage, UDTDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all UDTs in " + schemaNameOrDefault(schemaOrPackage) + ".");
printClassAnnotations(out, schemaOrPackage, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schemaOrPackage, UDTDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
List<UDTDefinition> udts = new ArrayList<>();
if (schemaOrPackage instanceof SchemaDefinition) {
for (UDTDefinition udt : database.getUDTs((SchemaDefinition) schemaOrPackage))
if (udt.getPackage() == null)
udts.add(udt);
}
else
udts.addAll(database.getUDTs((PackageDefinition) schemaOrPackage));
for (UDTDefinition udt : udts) {
final String className = out.ref(getStrategy().getFullJavaClassName(udt));
final String id = getStrategy().getJavaIdentifier(udt);
final String fullId = getStrategy().getFullJavaIdentifier(udt);
out.javadoc("The type <code>%s</code>", udt.getQualifiedOutputName());
if (scala)
out.println("def %s = %s", id, fullId);
else if (kotlin)
out.println("val %s = %s", id, fullId);
else
out.println("public static final %s %s = %s;", className, id, fullId);
}
generateUDTReferencesClassFooter(schemaOrPackage, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("UDT references generated" + logSuffix);
if (schemaOrPackage instanceof SchemaDefinition)
for (PackageDefinition pkg : database.getPackages((SchemaDefinition) schemaOrPackage))
if (!pkg.getUDTs().isEmpty())
generateUDTReferences(pkg);
}
@SuppressWarnings("unused")
protected void (Definition schemaOrPackage, JavaWriter out) {}
@SuppressWarnings("unused")
protected void (PackageDefinition pkg, JavaWriter out) {}
protected void generateDomainReferences(SchemaDefinition schema) {
log.info("Generating DOMAIN references");
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, DomainDefinition.class));
out.refConflicts(getStrategy().getJavaIdentifiers(database.getDomains(schema)));
printGlobalReferencesPackage(out, schema, DomainDefinition.class);
final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all Domains in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DOMAIN);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, DomainDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
for (DomainDefinition domain : database.getDomains(schema)) {
final String id = getStrategy().getJavaIdentifier(domain);
final String domainTypeFull = getJavaType(domain.getType(resolver(out)), out);
final String domainType = out.ref(domainTypeFull);
final String domainTypeRef = getJavaTypeReference(domain.getDatabase(), domain.getType(resolver(out)), out);
out.javadoc("The domain <code>%s</code>.", domain.getQualifiedOutputName());
if (scala) {
out.println("val %s: %s[%s] = %s.createDomain(", id, Domain.class, domainType, Internal.class);
out.println(" schema");
out.println(", %s.name(\"%s\")", DSL.class, escapeString(domain.getOutputName()));
out.println(", %s", domainTypeRef);
for (String check : domain.getCheckClauses())
out.println(", %s.createCheck(null, null, \"%s\")", Internal.class, escapeString(check));
out.println(")");
}
else if (kotlin) {
out.println("val %s: %s<%s> = %s.createDomain(", id, Domain.class, domainType, Internal.class);
out.println(" schema()");
out.println(", %s.name(\"%s\")", DSL.class, escapeString(domain.getOutputName()));
out.println(", %s", domainTypeRef);
for (String check : domain.getCheckClauses())
out.println(", %s.createCheck<%s>(null, null, \"%s\")", Internal.class, Record.class, escapeString(check));
out.println(")");
}
else {
out.println("public static final %s<%s> %s = %s.createDomain(", Domain.class, domainType, id, Internal.class);
out.println(" schema()");
out.println(", %s.name(\"%s\")", DSL.class, escapeString(domain.getOutputName()));
out.println(", %s", domainTypeRef);
for (String check : domain.getCheckClauses())
out.println(", %s.createCheck(null, null, \"%s\")", Internal.class, escapeString(check));
out.println(");");
}
}
if (scala) {
out.println();
out.println("private def schema: %s = new %s(%s.name(\"%s\"), %s.comment(\"\"), () => %s)", Schema.class, LazySchema.class, DSL.class, escapeString(schema.getOutputName()), DSL.class, schemaId);
}
else if (kotlin) {
out.println();
out.println("private fun schema(): %s = %s(%s.name(\"%s\"), %s.comment(\"\"), %s { %s })", Schema.class, LazySchema.class, DSL.class, escapeString(schema.getOutputName()), DSL.class, LazySupplier.class, schemaId);
}
else {
out.println();
out.println("private static final %s schema() {", Schema.class);
out.println("return new %s(%s.name(\"%s\"), %s.comment(\"\"), new %s<%s>() {", LazySchema.class, DSL.class, escapeString(schema.getOutputName()), DSL.class, LazySupplier.class, Schema.class);
out.override();
out.println("public %s get() {", Schema.class);
out.println("return %s;", schemaId);
out.println("}");
out.println("});");
out.println("}");
}
generateDomainReferencesClassFooter(schema, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("DOMAIN references generated");
}
@SuppressWarnings("unused")
protected void generateDomainReferencesClassFooter(SchemaDefinition schema, JavaWriter out) {}
protected void generateArrays(SchemaDefinition schema) {
log.info("Generating ARRAYs");
for (ArrayDefinition array : database.getArrays(schema)) {
try {
generateArray(schema, array);
}
catch (Exception e) {
log.error("Error while generating ARRAY record " + array, e);
}
}
watch.splitInfo("ARRAYs generated");
}
@SuppressWarnings("unused")
protected void generateArray(SchemaDefinition schema, ArrayDefinition array) {
JavaWriter out = newJavaWriter(getFile(array, Mode.RECORD));
log.info("Generating ARRAY", out.file().getName());
generateArray(array, out);
closeJavaWriter(out);
}
protected void generateArray(ArrayDefinition array, JavaWriter out) {
}
@SuppressWarnings("unused")
protected void (ArrayDefinition array, JavaWriter out) {}
protected void generateArrayClassJavadoc(ArrayDefinition array, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, array);
else
printClassJavadoc(out, "The type <code>" + array.getQualifiedInputName() + "</code>.");
}
protected void generateEnums(SchemaDefinition schema) {
log.info("Generating ENUMs");
for (EnumDefinition e : database.getEnums(schema)) {
try {
generateEnum(e);
} catch (Exception ex) {
log.error("Error while generating enum " + e, ex);
}
}
watch.splitInfo("Enums generated");
}
@Deprecated
protected void generateDomains(SchemaDefinition schema) {}
protected void generateEnum(EnumDefinition e) {
JavaWriter out = newJavaWriter(getFile(e, Mode.ENUM));
log.info("Generating ENUM", out.file().getName());
generateEnum(e, out);
closeJavaWriter(out);
}
protected void generateEnum(EnumDefinition e, JavaWriter out) {
final String className = getStrategy().getJavaClassName(e, Mode.ENUM);
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(e, Mode.ENUM));
final List<String> literals = e.getLiterals();
final List<String> identifiers = new ArrayList<>(literals.size());
for (int i = 0; i < literals.size(); i++) {
String identifier = convertToIdentifier(literals.get(i), language);
if (identifier.equals(getStrategy().getJavaPackageName(e).replaceAll("\\..*", "")))
identifier += "_";
identifiers.add(identifier);
}
printPackage(out, e);
generateEnumClassJavadoc(e, out);
printClassAnnotations(out, e, Mode.ENUM);
boolean enumHasNoSchema = e.isSynthetic() || !(e.getDatabase() instanceof PostgresDatabase);
if (scala) {
out.println("object %s {", className);
out.println();
for (int i = 0; i < identifiers.size(); i++)
out.println("val %s: %s = %s.%s", identifiers.get(i), className, getStrategy().getJavaPackageName(e), identifiers.get(i));
out.println();
out.println("def values: %s[%s] = %s(",
out.ref("scala.Array"),
className,
out.ref("scala.Array"));
for (int i = 0; i < identifiers.size(); i++) {
out.print((i > 0 ? ", " : " "));
out.println(identifiers.get(i));
}
out.println(")");
out.println();
out.println("def valueOf(s: %s): %s = s match {", String.class, className);
for (int i = 0; i < identifiers.size(); i++) {
out.println("case \"%s\" => %s", literals.get(i), identifiers.get(i));
}
out.println("case _ => throw new %s()", IllegalArgumentException.class);
out.println("}");
out.println("}");
out.println();
out.println("sealed trait %s extends %s[[before= with ][%s]] {", className, EnumType.class, interfaces);
if (enumHasNoSchema)
out.println("override def getCatalog: %s = null", Catalog.class);
else
out.println("override def getCatalog: %s = if (getSchema == null) null else getSchema().getCatalog()", Catalog.class);
out.println("override def getSchema: %s = %s",
Schema.class,
enumHasNoSchema
? "null"
: out.ref(getStrategy().getFullJavaIdentifier(e.getSchema()), 2));
out.println("override def getName: %s = %s",
String.class,
e.isSynthetic() ? "null" : "\"" + escapeString(e.getName()) + "\"");
generateEnumClassFooter(e, out);
out.println("}");
for (int i = 0; i < literals.size(); i++) {
out.println();
out.println("case object %s extends %s {", identifiers.get(i), className);
out.println("override def getLiteral: %s = \"%s\"",
String.class,
literals.get(i));
out.println("}");
}
}
else if (kotlin) {
interfaces.add(out.ref(EnumType.class));
out.println("enum class %s(@get:JvmName(\"literal\") val literal: String)[[before= : ][%s]] {", className, interfaces);
for (int i = 0; i < literals.size(); i++)
out.println("%s(\"%s\")%s", identifiers.get(i), literals.get(i), (i == literals.size() - 1) ? ";" : ",");
out.println("override fun getCatalog(): %s? = %s",
Catalog.class, enumHasNoSchema ? "null" : "schema.catalog");
out.println("override fun getSchema(): %s%s = %s",
Schema.class, enumHasNoSchema ? "?" : "", enumHasNoSchema ? "null" : out.ref(getStrategy().getFullJavaIdentifier(e.getSchema()), 2));
out.println("override fun getName(): %s%s = %s",
String.class, e.isSynthetic() ? "?" : "", e.isSynthetic() ? "null" : "\"" + escapeString(e.getName()) + "\"");
out.println("override fun getLiteral(): String = literal");
generateEnumClassFooter(e, out);
out.println("}");
}
else {
interfaces.add(out.ref(EnumType.class));
out.println("public enum %s[[before= implements ][%s]] {", className, interfaces);
for (int i = 0; i < literals.size(); i++) {
out.println();
out.println("%s(\"%s\")%s", identifiers.get(i), literals.get(i), (i == literals.size() - 1) ? ";" : ",");
}
out.println();
out.println("private final %s literal;", String.class);
out.println();
out.println("private %s(%s literal) {", className, String.class);
out.println("this.literal = literal;");
out.println("}");
out.overrideInherit();
out.println("public %s getCatalog() {", Catalog.class);
if (enumHasNoSchema)
out.println("return null;");
else
out.println("return getSchema().getCatalog();");
out.println("}");
out.overrideInherit();
out.println("public %s getSchema() {", Schema.class);
out.println("return %s;",
enumHasNoSchema
? "null"
: out.ref(getStrategy().getFullJavaIdentifier(e.getSchema()), 2));
out.println("}");
out.overrideInherit();
out.println("public %s getName() {", String.class);
out.println("return %s;", e.isSynthetic() ? "null" : "\"" + escapeString(e.getName()) + "\"");
out.println("}");
out.overrideInherit();
out.println("public %s getLiteral() {", String.class);
out.println("return literal;");
out.println("}");
generateEnumClassFooter(e, out);
out.println("}");
}
}
@SuppressWarnings("unused")
protected void (EnumDefinition e, JavaWriter out) {}
protected void generateEnumClassJavadoc(EnumDefinition e, JavaWriter out) {
if (generateCommentsOnUDTs())
printClassJavadoc(out, e);
else
printClassJavadoc(out, "The enum <code>" + e.getQualifiedInputName() + "</code>.");
}
@Deprecated
protected void generateDomain(DomainDefinition d) {}
@Deprecated
protected void generateDomain(DomainDefinition d, JavaWriter out) {}
@Deprecated
@SuppressWarnings("unused")
protected void generateDomainClassFooter(DomainDefinition d, JavaWriter out) {}
@Deprecated
protected void generateDomainClassJavadoc(DomainDefinition e, JavaWriter out) {}
protected void generateRoutines(SchemaDefinition schema) {
log.info("Generating routines and table-valued functions");
if (generateGlobalRoutineReferences()) {
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, RoutineDefinition.class));
printGlobalReferencesPackage(out, schema, RoutineDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all stored procedures and functions in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, RoutineDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
for (RoutineDefinition routine : database.getRoutines(schema))
printRoutine(out, routine);
for (TableDefinition table : database.getTables(schema))
if (table.isTableValuedFunction())
printTableValuedFunction(out, table, getStrategy().getJavaMethodName(table, Mode.DEFAULT));
generateRoutinesClassFooter(schema, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
}
for (RoutineDefinition routine : database.getRoutines(schema)) {
try {
generateRoutine(schema, routine);
}
catch (Exception e) {
log.error("Error while generating routine " + routine, e);
}
}
watch.splitInfo("Routines generated");
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
protected void printConstant(JavaWriter out, AttributeDefinition constant) {
}
protected void printRoutine(JavaWriter out, RoutineDefinition routine) {
if (!routine.isSQLUsable()) {
printConvenienceMethodProcedure(out, routine, false);
}
else {
if (!routine.isAggregate())
printConvenienceMethodFunction(out, routine, false);
printConvenienceMethodFunctionAsField(out, routine, false);
printConvenienceMethodFunctionAsField(out, routine, true);
}
}
protected void printTableValuedFunction(JavaWriter out, TableDefinition table, String javaMethodName) {
printConvenienceMethodTableValuedFunction(out, table, javaMethodName);
printConvenienceMethodTableValuedFunctionAsField(out, table, false, javaMethodName);
printConvenienceMethodTableValuedFunctionAsField(out, table, true, javaMethodName);
}
protected void generatePackages(SchemaDefinition schema) {
}
@SuppressWarnings("unused")
protected void generatePackage(SchemaDefinition schema, PackageDefinition pkg) {
}
protected void generatePackage(PackageDefinition pkg, JavaWriter out) {
}
@SuppressWarnings("unused")
protected void (PackageDefinition pkg, JavaWriter out) {}
protected void generatePackageClassJavadoc(PackageDefinition pkg, JavaWriter out) {
printClassJavadoc(out, "Convenience access to all stored procedures and functions in " + pkg.getName());
}
protected void generateTableReferences(SchemaDefinition schema) {
log.info("Generating table references");
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, TableDefinition.class));
printGlobalReferencesPackage(out, schema, TableDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all tables in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, TableDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
for (TableDefinition table : database.getTables(schema)) {
final String className = getStrategy().getJavaClassName(table);
final String fullClassName = scala || kotlin
? ""
: out.ref(getStrategy().getFullJavaClassName(table));
final String id = getStrategy().getJavaIdentifier(table);
final String referencedId = className.equals(id)
? getStrategy().getFullJavaIdentifier(table)
: out.ref(getStrategy().getFullJavaIdentifier(table), 2);
final String comment = escapeEntities(comment(table));
out.javadoc(isBlank(comment) ? "The table <code>" + table.getQualifiedOutputName() + "</code>." : comment);
if (scala)
out.println("def %s = %s", id, referencedId);
else if (kotlin)
out.println("val %s = %s", id, referencedId);
else
out.println("public static final %s %s = %s;", fullClassName, id, referencedId);
if (table.isTableValuedFunction())
printTableValuedFunction(out, table, getStrategy().getJavaIdentifier(table));
}
generateTableReferencesClassFooter(schema, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("Table refs generated");
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
private String schemaNameOrDefault(Definition schema) {
return StringUtils.isEmpty(schema.getOutputName()) ? "the default schema" : schema.getOutputName();
}
protected void generateDaos(SchemaDefinition schema) {
log.info("Generating DAOs");
for (TableDefinition table : database.getTables(schema)) {
try {
generateDao(table);
}
catch (Exception e) {
log.error("Error while generating table DAO " + table, e);
}
}
watch.splitInfo("Table DAOs generated");
}
protected void generateDao(TableDefinition table) {
JavaWriter out = newJavaWriter(getFile(table, Mode.DAO));
log.info("Generating DAO", out.file().getName());
generateDao(table, out);
closeJavaWriter(out);
}
protected void generateDao(TableDefinition table, JavaWriter out) {
UniqueKeyDefinition key = table.getPrimaryKey();
if (key == null) {
log.info("Skipping DAO generation", out.file().getName());
return;
}
final String className = getStrategy().getJavaClassName(table, Mode.DAO);
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(table, Mode.DAO));
final String tableRecord = out.ref(getStrategy().getFullJavaClassName(table, Mode.RECORD));
final String daoImpl = out.ref(DAOImpl.class);
final String tableIdentifier = out.ref(getStrategy().getFullJavaIdentifier(table), 2);
String tType = (scala || kotlin ? "Unit" : "Void");
String pType = out.ref(getStrategy().getFullJavaClassName(table, Mode.POJO));
List<ColumnDefinition> keyColumns = key.getKeyColumns();
if (keyColumns.size() == 1) {
tType = getJavaType(keyColumns.get(0).getType(resolver(out)), out, Mode.POJO);
}
else if (keyColumns.size() <= Constants.MAX_ROW_DEGREE) {
String generics = "";
String separator = "";
for (ColumnDefinition column : keyColumns) {
generics += separator + out.ref(getJavaType(column.getType(resolver(out)), out));
if (kotlin)
generics += "?";
separator = ", ";
}
if (scala)
tType = Record.class.getName() + keyColumns.size() + "[" + generics + "]";
else
tType = Record.class.getName() + keyColumns.size() + "<" + generics + ">";
}
else {
tType = Record.class.getName();
}
tType = out.ref(tType);
printPackage(out, table, Mode.DAO);
generateDaoClassJavadoc(table, out);
printClassAnnotations(out, table, Mode.DAO);
if (generateSpringAnnotations())
out.println("@%s", out.ref("org.springframework.stereotype.Repository"));
if (scala)
out.println("class %s(configuration: %s) extends %s[%s, %s, %s](%s, classOf[%s], configuration)[[before= with ][separator= with ][%s]] {",
className, Configuration.class, daoImpl, tableRecord, pType, tType, tableIdentifier, pType, interfaces);
else if (kotlin)
out.println("open class %s(configuration: %s?) : %s<%s, %s, %s>(%s, %s::class.java, configuration)[[before=, ][%s]] {",
className, Configuration.class, daoImpl, tableRecord, pType, tType, tableIdentifier, pType, interfaces);
else
out.println("public class %s extends %s<%s, %s, %s>[[before= implements ][%s]] {", className, daoImpl, tableRecord, pType, tType, interfaces);
out.javadoc("Create a new %s without any configuration", className);
if (scala) {
out.println("def this() = this(null)");
}
else if (kotlin) {
out.println("constructor(): this(null)");
}
else {
out.println("public %s() {", className);
out.println("super(%s, %s.class);", tableIdentifier, pType);
out.println("}");
}
if (!scala && !kotlin) {
out.javadoc("Create a new %s with an attached configuration", className);
printDaoConstructorAnnotations(table, out);
out.println("public %s(%s configuration) {", className, Configuration.class);
out.println("super(%s, %s.class, configuration);", tableIdentifier, pType);
out.println("}");
}
if (scala) {
out.println();
out.print("override def getId(o: %s): %s = ", pType, tType);
}
else if (kotlin) {
out.println();
out.print("override fun getId(o: %s): %s? = ", pType, tType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s getId(%s object) {", tType, pType);
}
if (keyColumns.size() == 1) {
if (scala)
out.println("o.%s", getStrategy().getJavaGetterName(keyColumns.get(0), Mode.POJO));
else if (kotlin)
out.println("o.%s", getStrategy().getJavaMemberName(keyColumns.get(0), Mode.POJO));
else
out.println("return object.%s();", getStrategy().getJavaGetterName(keyColumns.get(0), Mode.POJO));
}
else {
String params = "";
String separator = "";
for (ColumnDefinition column : keyColumns) {
if (scala)
params += separator + "o." + getStrategy().getJavaGetterName(column, Mode.POJO);
else if (kotlin)
params += separator + "o." + getStrategy().getJavaMemberName(column, Mode.POJO);
else
params += separator + "object." + getStrategy().getJavaGetterName(column, Mode.POJO) + "()";
separator = ", ";
}
if (scala || kotlin)
out.println("compositeKeyRecord(%s)", params);
else
out.println("return compositeKeyRecord(%s);", params);
}
if (scala || kotlin) {}
else
out.println("}");
for (ColumnDefinition column : table.getColumns()) {
final String colName = column.getOutputName();
final String colClass = getStrategy().getJavaClassName(column);
final String colTypeFull = getJavaType(column.getType(resolver(out)), out);
final String colType = out.ref(colTypeFull);
final String colIdentifier = out.ref(getStrategy().getFullJavaIdentifier(column), colRefSegments(column));
if (!printDeprecationIfUnknownType(out, colTypeFull))
out.javadoc("Fetch records that have <code>%s BETWEEN lowerInclusive AND upperInclusive</code>", colName);
if (scala) {
out.println("def fetchRangeOf%s(lowerInclusive: %s, upperInclusive: %s): %s[%s] = fetchRange(%s, lowerInclusive, upperInclusive)",
colClass, colType, colType, List.class, pType, colIdentifier);
}
else if (kotlin) {
out.println("fun fetchRangeOf%s(lowerInclusive: %s?, upperInclusive: %s?): %s<%s> = fetchRange(%s, lowerInclusive, upperInclusive)",
colClass, colType, colType, out.ref(KLIST), pType, colIdentifier);
}
else {
printNonnullAnnotation(out);
out.println("public %s<%s> fetchRangeOf%s(%s lowerInclusive, %s upperInclusive) {", List.class, pType, colClass, colType, colType);
out.println("return fetchRange(%s, lowerInclusive, upperInclusive);", colIdentifier);
out.println("}");
}
if (!printDeprecationIfUnknownType(out, colTypeFull))
out.javadoc("Fetch records that have <code>%s IN (values)</code>", colName);
if (scala) {
out.println("def fetchBy%s(values: %s*): %s[%s] = fetch(%s, values:_*)", colClass, colType, List.class, pType, colIdentifier);
}
else if (kotlin) {
String toTypedArray = PRIMITIVE_WRAPPERS.contains(colTypeFull) ? ".toTypedArray()" : "";
out.println("fun fetchBy%s(vararg values: %s): %s<%s> = fetch(%s, *values%s)", colClass, colType, out.ref(KLIST), pType, colIdentifier, toTypedArray);
}
else {
printNonnullAnnotation(out);
out.println("public %s<%s> fetchBy%s(%s... values) {", List.class, pType, colClass, colType);
out.println("return fetch(%s, values);", colIdentifier);
out.println("}");
}
ukLoop:
for (UniqueKeyDefinition uk : column.getUniqueKeys()) {
if (uk.getKeyColumns().size() == 1 && uk.getKeyColumns().get(0).equals(column)) {
if (!printDeprecationIfUnknownType(out, colTypeFull))
out.javadoc("Fetch a unique record that has <code>%s = value</code>", colName);
if (scala) {
out.println("def fetchOneBy%s(value: %s): %s = fetchOne(%s, value)", colClass, colType, pType, colIdentifier);
}
else if (kotlin) {
out.println("fun fetchOneBy%s(value: %s): %s? = fetchOne(%s, value)", colClass, colType, pType, colIdentifier);
}
else {
printNullableAnnotation(out);
out.println("public %s fetchOneBy%s(%s value) {", pType, colClass, colType);
out.println("return fetchOne(%s, value);", colIdentifier);
out.println("}");
}
break ukLoop;
}
}
}
generateDaoClassFooter(table, out);
out.println("}");
}
protected void printDaoConstructorAnnotations(TableDefinition table, JavaWriter out) {
if (generateSpringAnnotations())
out.println("@%s", out.ref("org.springframework.beans.factory.annotation.Autowired"));
}
@SuppressWarnings("unused")
protected void (TableDefinition table, JavaWriter out) {}
protected void generateDaoClassJavadoc(TableDefinition table, JavaWriter out) {
if (generateCommentsOnTables())
printClassJavadoc(out, table);
else
printClassJavadoc(out, "The table <code>" + table.getQualifiedInputName() + "</code>.");
}
protected void generatePojos(SchemaDefinition schema) {
log.info("Generating table POJOs");
for (TableDefinition table : database.getTables(schema)) {
try {
generatePojo(table);
}
catch (Exception e) {
log.error("Error while generating table POJO " + table, e);
}
}
watch.splitInfo("Table POJOs generated");
}
protected void generatePojo(TableDefinition table) {
JavaWriter out = newJavaWriter(getFile(table, Mode.POJO));
log.info("Generating POJO", out.file().getName());
generatePojo(table, out);
closeJavaWriter(out);
}
protected void generateEmbeddablePojo(EmbeddableDefinition embeddable) {
JavaWriter out = newJavaWriter(getFile(embeddable, Mode.POJO));
log.info("Generating POJO", out.file().getName());
generatePojo0(embeddable, out);
closeJavaWriter(out);
}
protected void generateUDTPojo(UDTDefinition udt) {
JavaWriter out = newJavaWriter(getFile(udt, Mode.POJO));
log.info("Generating POJO", out.file().getName());
generatePojo0(udt, out);
closeJavaWriter(out);
}
protected void generatePojo(TableDefinition table, JavaWriter out) {
generatePojo0(table, out);
}
protected void generateUDTPojo(UDTDefinition udt, JavaWriter out) {
generatePojo0(udt, out);
}
private final void generatePojo0(Definition tableUdtOrEmbeddable, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableUdtOrEmbeddable, Mode.POJO);
final String interfaceName = generateInterfaces()
? out.ref(getStrategy().getFullJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE))
: "";
final String superName = out.ref(getStrategy().getJavaClassExtends(tableUdtOrEmbeddable, Mode.POJO));
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(tableUdtOrEmbeddable, Mode.POJO));
if (generateInterfaces())
interfaces.add(interfaceName);
final List<String> superTypes = list(superName, interfaces);
printPackage(out, tableUdtOrEmbeddable, Mode.POJO);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generatePojoClassJavadoc((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassJavadoc((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTPojoClassJavadoc((UDTDefinition) tableUdtOrEmbeddable, out);
printClassAnnotations(out, tableUdtOrEmbeddable, Mode.POJO);
if (tableUdtOrEmbeddable instanceof TableDefinition)
printTableJPAAnnotation(out, (TableDefinition) tableUdtOrEmbeddable);
int maxLength = 0;
for (TypedElementDefinition<?> column : getTypedElements(tableUdtOrEmbeddable))
maxLength = Math.max(maxLength, out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)).length());
if (scala) {
out.println("%sclass %s(", (generatePojosAsScalaCaseClasses() ? "case " : ""), className);
String separator = " ";
for (TypedElementDefinition<?> column : getTypedElements(tableUdtOrEmbeddable)) {
out.println("%s%s %s: %s",
separator,
generateImmutablePojos() ? "val" : "var",
getStrategy().getJavaMemberName(column, Mode.POJO),
out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)));
separator = ", ";
}
out.println(")[[before= extends ][%s]][[before= with ][separator= with ][%s]] {", first(superTypes), remaining(superTypes));
}
else if (kotlin) {
out.println("%sclass %s(", (generatePojosAsKotlinDataClasses() ? "data " : ""), className);
String separator = ", ";
List<? extends TypedElementDefinition<? extends Definition>> typedElements = getTypedElements(tableUdtOrEmbeddable);
for (int i = 0; i < typedElements.size(); i++) {
if (i + 1 == typedElements.size())
separator = "";
TypedElementDefinition<?> column = typedElements.get(i);
final String member = getStrategy().getJavaMemberName(column, Mode.POJO);
if (column instanceof ColumnDefinition)
printColumnJPAAnnotation(out, (ColumnDefinition) column);
printValidationAnnotation(out, column);
out.println("%s%s %s: %s? = null%s",
generateInterfaces() ? "override " : "",
generateImmutablePojos() ? "val" : "var",
member,
out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)),
separator
);
}
out.println(")[[before=: ][%s]] {", superTypes);
}
else {
out.println("public class %s[[before= extends ][%s]][[before= implements ][%s]] {", className, list(superName), interfaces);
if (generateSerializablePojos() || generateSerializableInterfaces())
out.printSerial();
out.println();
for (TypedElementDefinition<?> column : getTypedElements(tableUdtOrEmbeddable)) {
out.println("private %s%s %s;",
generateImmutablePojos() ? "final " : "",
StringUtils.rightPad(out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)), maxLength),
getStrategy().getJavaMemberName(column, Mode.POJO));
}
}
if (!generateImmutablePojos())
generatePojoDefaultConstructor(tableUdtOrEmbeddable, out);
if (!kotlin) {
generatePojoCopyConstructor(tableUdtOrEmbeddable, out);
generatePojoMultiConstructor(tableUdtOrEmbeddable, out);
List<? extends TypedElementDefinition<?>> elements = getTypedElements(tableUdtOrEmbeddable);
for (int i = 0; i < elements.size(); i++) {
TypedElementDefinition<?> column = elements.get(i);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generatePojoGetter(column, i, out);
else
generateUDTPojoGetter(column, i, out);
if (!generateImmutablePojos())
if (tableUdtOrEmbeddable instanceof TableDefinition)
generatePojoSetter(column, i, out);
else
generateUDTPojoSetter(column, i, out);
}
}
if (tableUdtOrEmbeddable instanceof TableDefinition) {
List<EmbeddableDefinition> embeddables = ((TableDefinition) tableUdtOrEmbeddable).getReferencedEmbeddables();
for (int i = 0; i < embeddables.size(); i++) {
EmbeddableDefinition embeddable = embeddables.get(i);
generateEmbeddablePojoSetter(embeddable, i, out);
generateEmbeddablePojoGetter(embeddable, i, out);
}
}
if (generatePojosEqualsAndHashCode())
generatePojoEqualsAndHashCode(tableUdtOrEmbeddable, out);
if (generatePojosToString())
generatePojoToString(tableUdtOrEmbeddable, out);
if (generateInterfaces() && !generateImmutablePojos())
printFromAndInto(out, tableUdtOrEmbeddable, Mode.POJO);
if (tableUdtOrEmbeddable instanceof TableDefinition)
generatePojoClassFooter((TableDefinition) tableUdtOrEmbeddable, out);
else if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
generateEmbeddableClassFooter((EmbeddableDefinition) tableUdtOrEmbeddable, out);
else
generateUDTPojoClassFooter((UDTDefinition) tableUdtOrEmbeddable, out);
out.println("}");
closeJavaWriter(out);
}
protected void generatePojoMultiConstructor(Definition tableOrUDT, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO);
final List<String> properties = new ArrayList<>();
int maxLength = 0;
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
maxLength = Math.max(maxLength, out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)).length());
properties.add("\"" + escapeString(getStrategy().getJavaMemberName(column, Mode.POJO)) + "\"");
}
if (scala) {
}
else if (getTypedElements(tableOrUDT).size() > 0 &&
getTypedElements(tableOrUDT).size() < 256) {
out.println();
if (generateConstructorPropertiesAnnotationOnPojos())
out.println("@%s({ [[%s]] })", ConstructorProperties.class, properties);
out.print("public %s(", className);
String separator1 = "";
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
out.println(separator1);
out.print("[[before=@][after= ][%s]]%s %s",
list(nullableAnnotation),
StringUtils.rightPad(out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)), maxLength),
getStrategy().getJavaMemberName(column, Mode.POJO));
separator1 = ",";
}
out.println();
out.println(") {");
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
out.println("this.%s = %s;", columnMember, columnMember);
}
out.println("}");
}
}
protected void generatePojoCopyConstructor(Definition tableOrUDT, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO);
final String interfaceName = generateInterfaces()
? out.ref(getStrategy().getFullJavaClassName(tableOrUDT, Mode.INTERFACE))
: "";
out.println();
if (scala) {
out.println("def this(value: %s) = this(", generateInterfaces() ? interfaceName : className);
String separator = " ";
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
out.println("%svalue.%s",
separator,
generateInterfaces()
? getStrategy().getJavaGetterName(column, Mode.INTERFACE)
: getStrategy().getJavaMemberName(column, Mode.POJO));
separator = ", ";
}
out.println(")");
}
else {
out.println("public %s(%s value) {", className, generateInterfaces() ? interfaceName : className);
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
out.println("this.%s = value.%s%s;",
getStrategy().getJavaMemberName(column, Mode.POJO),
generateInterfaces()
? getStrategy().getJavaGetterName(column, Mode.INTERFACE)
: getStrategy().getJavaMemberName(column, Mode.POJO),
generateInterfaces()
? "()"
: "");
}
out.println("}");
}
}
protected void generatePojoDefaultConstructor(Definition tableOrUDT, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO);
out.println();
int size = getTypedElements(tableOrUDT).size();
if (scala) {
if (size > 0) {
List<String> nulls = new ArrayList<>(size);
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT))
if (size == 1)
nulls.add("null: " + out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)));
else
nulls.add("null");
out.println("def this() = this([[%s]])", nulls);
}
}
else if (kotlin) {}
else {
out.println("public %s() {}", className);
}
}
protected void generatePojoGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generatePojoGetter0(column, index, out);
}
protected void generateEmbeddablePojoGetter(EmbeddableDefinition embeddable, @SuppressWarnings("unused") int index, JavaWriter out) {
final String columnTypeFull = getStrategy().getFullJavaClassName(embeddable, Mode.POJO);
final String columnType = out.ref(columnTypeFull);
final String columnGetter = getStrategy().getJavaGetterName(embeddable, Mode.POJO);
final String name = embeddable.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("Getter for <code>%s</code>.", name);
printNonnullAnnotation(out);
if (scala)
out.println("def %s: %s = new %s(", scalaWhitespaceSuffix(columnGetter), columnType, columnType);
else if (kotlin)
out.tab(1).println("get() = %s(", columnType);
else {
out.overrideIf(generateInterfaces());
out.println("public %s %s() {", columnType, columnGetter);
out.println("return new %s(", columnType);
}
String separator = " ";
for (EmbeddableColumnDefinition column : embeddable.getColumns()) {
if (kotlin)
out.tab(1).println("%s%s", separator, getStrategy().getJavaMemberName(column.getReferencingColumn(), Mode.POJO));
else
out.println("%s%s%s", separator, getStrategy().getJavaGetterName(column.getReferencingColumn(), Mode.POJO), emptyparens);
separator = ", ";
}
if (scala)
out.println(")");
else if (kotlin)
out.tab(1).println(")");
else {
out.println(");");
out.println("}");
}
}
protected void generateUDTPojoGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generatePojoGetter0(column, index, out);
}
private final void generatePojoGetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
final String columnTypeFull = getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO);
final String columnType = out.ref(columnTypeFull);
final String columnGetter = getStrategy().getJavaGetterName(column, Mode.POJO);
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
final String name = column.getQualifiedOutputName();
if (!printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("Getter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (column instanceof ColumnDefinition)
printColumnJPAAnnotation(out, (ColumnDefinition) column);
printValidationAnnotation(out, column);
printNullableOrNonnullAnnotation(out, column);
if (scala) {
out.println("def %s: %s = this.%s", scalaWhitespaceSuffix(columnGetter), columnType, columnMember);
}
else {
out.overrideIf(generateInterfaces());
out.println("public %s %s() {", columnType, columnGetter);
out.println("return this.%s;", columnMember);
out.println("}");
}
}
protected void generatePojoSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generatePojoSetter0(column, index, out);
}
protected void generateEmbeddablePojoSetter(EmbeddableDefinition embeddable, @SuppressWarnings("unused") int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(embeddable.getReferencingTable(), Mode.POJO);
final String columnTypeFull = getStrategy().getFullJavaClassName(embeddable, Mode.POJO);
final String columnType = out.ref(columnTypeFull);
final String columnSetterReturnType = generateFluentSetters() ? className : tokenVoid;
final String columnSetter = getStrategy().getJavaSetterName(embeddable, Mode.POJO);
final String columnMember = getStrategy().getJavaMemberName(embeddable, Mode.POJO);
final String name = embeddable.getQualifiedOutputName();
if (!kotlin && !printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("Setter for <code>%s</code>.", name);
if (scala) {
out.println("def %s(value: %s): %s = {", columnSetter, columnType, columnSetterReturnType);
}
else if (kotlin) {
out.println("var %s: %s", columnMember, columnType);
out.tab(1).println("set(value) {");
}
else {
out.overrideIf(generateInterfaces() && !generateImmutableInterfaces());
out.println("public %s %s([[before=@][after= ][%s]]%s value) {", columnSetterReturnType, columnSetter, list(nonnullAnnotation(out)), columnType);
}
if (kotlin) {
for (EmbeddableColumnDefinition column : embeddable.getColumns()) {
final String s = getStrategy().getJavaMemberName(column.getReferencingColumn(), Mode.POJO);
final String g = getStrategy().getJavaMemberName(column, Mode.POJO);
out.tab(1).println("%s = value.%s", s, g);
}
}
else {
for (EmbeddableColumnDefinition column : embeddable.getColumns()) {
final String s = getStrategy().getJavaSetterName(column.getReferencingColumn(), Mode.POJO);
final String g = getStrategy().getJavaGetterName(column, Mode.POJO);
out.println("%s(value.%s%s)%s", s, g, emptyparens, semicolon);
}
}
if (generateFluentSetters())
out.println("return this;");
if (kotlin)
out.tab(1).println("}");
else
out.println("}");
}
protected void generateUDTPojoSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
generatePojoSetter0(column, index, out);
}
private final void generatePojoSetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
final String className = getStrategy().getJavaClassName(column.getContainer(), Mode.POJO);
final String columnTypeFull = getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO);
final String columnType = out.ref(columnTypeFull);
final String columnSetterReturnType = generateFluentSetters() ? className : tokenVoid;
final String columnSetter = getStrategy().getJavaSetterName(column, Mode.POJO);
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
final boolean isUDT = column.getType(resolver(out)).isUDT();
final boolean isUDTArray = column.getType(resolver(out)).isArray() && database.getArray(column.getType(resolver(out)).getSchema(), column.getType(resolver(out)).getQualifiedUserType()).getElementType(resolver(out)).isUDT();
final String name = column.getQualifiedOutputName();
if (!(generateInterfaces() && isUDTArray)) {
if (!printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("Setter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
if (scala) {
out.println("def %s(%s: %s): %s = {", columnSetter, columnMember, columnType, columnSetterReturnType);
out.println("this.%s = %s", columnMember, columnMember);
if (generateFluentSetters())
out.println("this");
out.println("}");
}
else {
final String nullableAnnotation = nullableOrNonnullAnnotation(out, column);
out.overrideIf(generateInterfaces() && !generateImmutableInterfaces() && !isUDT);
out.println("public %s %s([[before=@][after= ][%s]]%s %s) {", columnSetterReturnType, columnSetter, list(nullableAnnotation), varargsIfArray(columnType), columnMember);
out.println("this.%s = %s;", columnMember, columnMember);
if (generateFluentSetters())
out.println("return this;");
out.println("}");
}
}
if (generateInterfaces() && (isUDT || isUDTArray)) {
final String columnTypeInterface = out.ref(getJavaType(column.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
out.println();
if (scala) {
out.println("def %s(%s: %s): %s = {", columnSetter, columnMember, columnTypeInterface, columnSetterReturnType);
out.println("if (%s == null)", columnMember);
out.println("this.%s = null", columnMember);
out.println("else");
out.println("this.%s = %s.into(new %s)", columnMember, columnMember, columnType);
if (generateFluentSetters())
out.println("this");
out.println("}");
}
else {
out.override();
out.println("public %s %s(%s %s) {", columnSetterReturnType, columnSetter, varargsIfArray(columnTypeInterface), columnMember);
out.println("if (%s == null)", columnMember);
out.println("this.%s = null;", columnMember);
if (isUDT) {
out.println("else");
out.println("this.%s = %s.into(new %s());", columnMember, columnMember, columnType);
}
else if (isUDTArray) {
final ArrayDefinition array = database.getArray(column.getType(resolver(out)).getSchema(), column.getType(resolver(out)).getQualifiedUserType());
final String componentType = out.ref(getJavaType(array.getElementType(resolver(out, Mode.POJO)), out, Mode.POJO));
final String componentTypeInterface = out.ref(getJavaType(array.getElementType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
out.println("else {");
out.println("this.%s = new %s();", columnMember, ArrayList.class);
out.println();
out.println("for (%s i : %s)", componentTypeInterface, columnMember);
out.println("this.%s.add(i.into(new %s()));", columnMember, componentType);
out.println("}");
}
if (generateFluentSetters())
out.println("return this;");
out.println("}");
}
}
}
protected void generatePojoEqualsAndHashCode(Definition tableOrUDT, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO);
out.println();
if (scala) {
out.println("override def equals(obj: Any): scala.Boolean = {");
out.println("if (this eq obj.asInstanceOf[AnyRef])");
out.println("return true");
out.println("if (obj == null)");
out.println("return false");
out.println("if (getClass() != obj.getClass())");
out.println("return false");
out.println("val other = obj.asInstanceOf[%s]", className);
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
out.println("if (%s == null) {", columnMember);
out.println("if (other.%s != null)", columnMember);
out.println("return false");
out.println("}");
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("else if (!(%s sameElements other.%s))", columnMember, columnMember);
else
out.println("else if (!%s.equals(other.%s))", columnMember, columnMember);
out.println("return false");
}
out.println("true");
out.println("}");
}
else if (kotlin) {
out.println("override fun equals(other: Any?): Boolean {");
out.println("if (this === other)");
out.println("return true");
out.println("if (other === null)");
out.println("return false");
out.println("if (this::class != other::class)");
out.println("return false");
out.println("val o: %s = other as %s", className, className);
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
out.println("if (%s === null) {", columnMember);
out.println("if (o.%s !== null)", columnMember);
out.println("return false");
out.println("}");
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("else if (!%s.equals(%s, o.%s))", Arrays.class, columnMember, columnMember);
else
out.println("else if (%s != o.%s)", columnMember, columnMember);
out.println("return false");
}
out.println("return true");
out.println("}");
}
else {
out.println("@Override");
out.println("public boolean equals(%s obj) {", Object.class);
out.println("if (this == obj)");
out.println("return true;");
out.println("if (obj == null)");
out.println("return false;");
out.println("if (getClass() != obj.getClass())");
out.println("return false;");
out.println("final %s other = (%s) obj;", className, className);
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
out.println("if (%s == null) {", columnMember);
out.println("if (other.%s != null)", columnMember);
out.println("return false;");
out.println("}");
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("else if (!%s.equals(%s, other.%s))", Arrays.class, columnMember, columnMember);
else
out.println("else if (!%s.equals(other.%s))", columnMember, columnMember);
out.println("return false;");
}
out.println("return true;");
out.println("}");
}
out.println();
if (scala) {
out.println("override def hashCode: Int = {");
out.println("val prime = 31");
out.println("var result = 1");
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("result = prime * result + (if (this.%s == null) 0 else %s.toSeq.hashCode)", columnMember, columnMember);
else
out.println("result = prime * result + (if (this.%s == null) 0 else this.%s.hashCode)", columnMember, columnMember);
}
out.println("return result");
out.println("}");
}
else if (kotlin) {
out.println("override fun hashCode(): Int {");
out.println("val prime = 31");
out.println("var result = 1");
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("result = prime * result + (if (this.%s === null) 0 else %s.hashCode(this.%s))", columnMember, Arrays.class, columnMember);
else
out.println("result = prime * result + (if (this.%s === null) 0 else this.%s.hashCode())", columnMember, columnMember);
}
out.println("return result");
out.println("}");
}
else {
out.println("@Override");
out.println("public int hashCode() {");
out.println("final int prime = 31;");
out.println("int result = 1;");
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
if (isArrayType(getJavaType(column.getType(resolver(out)), out)))
out.println("result = prime * result + ((this.%s == null) ? 0 : %s.hashCode(this.%s));", columnMember, Arrays.class, columnMember);
else
out.println("result = prime * result + ((this.%s == null) ? 0 : this.%s.hashCode());", columnMember, columnMember);
}
out.println("return result;");
out.println("}");
}
}
protected void generatePojoToString(Definition tableOrUDT, JavaWriter out) {
final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO);
out.println();
if (scala) {
out.println("override def toString: String = {");
out.println("val sb = new %s(\"%s (\")", StringBuilder.class, className);
out.println();
String separator = "";
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
final String columnType = getJavaType(column.getType(resolver(out)), out);
final boolean array = isArrayType(columnType);
if (columnType.equals("scala.Array[scala.Byte]"))
out.println("sb%s.append(\"[binary...]\")", separator);
else if (array)
out.println("sb%s.append(\"[\").append(if (this.%s == null) \"\" else %s.mkString(\", \")).append(\"]\")", separator, columnMember, columnMember);
else
out.println("sb%s.append(%s)", separator, columnMember);
separator = ".append(\", \")";
}
out.println();
out.println("sb.append(\")\")");
out.println("sb.toString");
out.println("}");
}
else if (kotlin) {
out.println("override fun toString(): String {");
out.println("val sb = %s(\"%s (\")", StringBuilder.class, className);
out.println();
String separator = "";
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
final String columnType = getJavaType(column.getType(resolver(out)), out);
final boolean array = isArrayType(columnType);
if (array && columnType.equals("kotlin.ByteArray"))
out.println("sb%s.append(\"[binary...]\")", separator);
else if (array)
out.println("sb%s.append(%s.toString(%s))", separator, Arrays.class, columnMember);
else
out.println("sb%s.append(%s)", separator, columnMember);
separator = ".append(\", \")";
}
out.println();
out.println("sb.append(\")\")");
out.println("return sb.toString()");
out.println("}");
}
else {
out.println("@Override");
out.println("public String toString() {");
out.println("%s sb = new %s(\"%s (\");", StringBuilder.class, StringBuilder.class, className);
out.println();
String separator = "";
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO);
final String columnType = getJavaType(column.getType(resolver(out)), out);
final boolean array = isArrayType(columnType);
if (array && columnType.equals("byte[]"))
out.println("sb%s.append(\"[binary...]\");", separator);
else if (array)
out.println("sb%s.append(%s.toString(%s));", separator, Arrays.class, columnMember);
else
out.println("sb%s.append(%s);", separator, columnMember);
separator = ".append(\", \")";
}
out.println();
out.println("sb.append(\")\");");
out.println("return sb.toString();");
out.println("}");
}
}
private List<? extends TypedElementDefinition<? extends Definition>> getTypedElements(Definition definition) {
if (definition instanceof TableDefinition)
return ((TableDefinition) definition).getColumns();
else if (definition instanceof EmbeddableDefinition)
return ((EmbeddableDefinition) definition).getColumns();
else if (definition instanceof UDTDefinition)
return ((UDTDefinition) definition).getAttributes();
else if (definition instanceof RoutineDefinition)
return ((RoutineDefinition) definition).getAllParameters();
else
throw new IllegalArgumentException("Unsupported type : " + definition);
}
@SuppressWarnings("unused")
protected void (TableDefinition table, JavaWriter out) {}
protected void generatePojoClassJavadoc(TableDefinition table, JavaWriter out) {
if (generateCommentsOnTables())
printClassJavadoc(out, table);
else
printClassJavadoc(out, "The table <code>" + table.getQualifiedInputName() + "</code>.");
}
protected void generateTables(SchemaDefinition schema) {
log.info("Generating tables");
for (TableDefinition table : database.getTables(schema)) {
try {
generateTable(schema, table);
}
catch (Exception e) {
log.error("Error while generating table " + table, e);
}
}
watch.splitInfo("Tables generated");
}
@SuppressWarnings("unused")
protected void generateTable(SchemaDefinition schema, TableDefinition table) {
JavaWriter out = newJavaWriter(getFile(table));
out.refConflicts(getStrategy().getJavaIdentifiers(table.getColumns()));
out.refConflicts(getStrategy().getJavaIdentifiers(table.getReferencedEmbeddables()));
log.info("Generating table", out.file().getName() +
" [input=" + table.getInputName() +
", output=" + table.getOutputName() +
", pk=" + (table.getPrimaryKey() != null ? table.getPrimaryKey().getName() : "N/A") +
"]");
if (log.isDebugEnabled())
for (ColumnDefinition column : table.getColumns())
log.debug("With column", "name=" + column.getOutputName() + ", matching type names=" + column.getDefinedType().getMatchNames());
generateTable(table, out);
closeJavaWriter(out);
}
protected void generateTable(TableDefinition table, JavaWriter out) {
final SchemaDefinition schema = table.getSchema();
final UniqueKeyDefinition primaryKey = table.getPrimaryKey();
final String className = getStrategy().getJavaClassName(table);
final String tableId = scala
? out.ref(getStrategy().getFullJavaIdentifier(table), 2)
: getStrategy().getJavaIdentifier(table);
final String recordType = out.ref(getStrategy().getFullJavaClassName(table, Mode.RECORD));
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(table, Mode.DEFAULT));
final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
final String tableType = table.isTemporary()
? "temporaryTable"
: table.isView()
? "view"
: table.isMaterializedView()
? "materializedView"
: table.isTableValuedFunction()
? "function"
: "table";
final List<ParameterDefinition> parameters = table.getParameters();
printPackage(out, table);
if (scala) {
out.println("object %s {", className);
printSingletonInstance(out, table);
out.println("}");
out.println();
}
generateTableClassJavadoc(table, out);
printClassAnnotations(out, table, Mode.DEFAULT);
if (scala) {
out.println("class %s(", className);
out.println("alias: %s,", Name.class);
out.println("child: %s[_ <: %s],", Table.class, Record.class);
out.println("path: %s[_ <: %s, %s],", ForeignKey.class, Record.class, recordType);
out.println("aliased: %s[%s],", Table.class, recordType);
out.println("parameters: %s[ %s[_] ]", out.ref("scala.Array"), Field.class);
out.println(")");
out.println("extends %s[%s](", TableImpl.class, recordType);
out.println("alias,");
out.println("%s,", schemaId);
out.println("child,");
out.println("path,");
out.println("aliased,");
out.println("parameters,");
out.println("%s.comment(\"%s\"),", DSL.class, escapeString(comment(table)));
if (generateSourcesOnViews() && table.isView() && table.getSource() != null)
out.println("%s.%s(\"%s\")", TableOptions.class, tableType, escapeString(table.getSource()));
else
out.println("%s.%s", TableOptions.class, tableType);
out.println(")[[before= with ][separator= with ][%s]] {", interfaces);
}
else if (kotlin) {
out.println("open class %s(", className);
out.println("alias: %s,", Name.class);
out.println("child: %s<out %s>?,", Table.class, Record.class);
out.println("path: %s<out %s, %s>?,", ForeignKey.class, Record.class, recordType);
out.println("aliased: %s<%s>?,", Table.class, recordType);
out.println("parameters: Array<%s<*>?>?", Field.class);
out.println("): %s<%s>(", TableImpl.class, recordType);
out.println("alias,");
out.println("%s,", schemaId);
out.println("child,");
out.println("path,");
out.println("aliased,");
out.println("parameters,");
out.println("%s.comment(\"%s\"),", DSL.class, escapeString(comment(table)));
if (generateSourcesOnViews() && table.isView() && table.getSource() != null)
out.println("%s.%s(\"%s\")", TableOptions.class, tableType, escapeString(table.getSource()));
else
out.println("%s.%s()", TableOptions.class, tableType);
out.println(")[[before=, ][%s]] {", interfaces);
out.println("companion object {");
printSingletonInstance(out, table);
out.println("}");
}
else {
out.println("public class %s extends %s<%s>[[before= implements ][%s]] {", className, TableImpl.class, recordType, interfaces);
out.printSerial();
printSingletonInstance(out, table);
}
printRecordTypeMethod(out, table);
for (ColumnDefinition column : table.getColumns()) {
final String columnTypeFull = getJavaType(column.getType(resolver(out)), out);
final String columnType = out.ref(columnTypeFull);
final String columnTypeRef = getJavaTypeReference(column.getDatabase(), column.getType(resolver(out)), out);
final String columnId = out.ref(getStrategy().getJavaIdentifier(column), colRefSegments(column));
final String columnName = column.getName();
final List<String> converter = out.ref(list(column.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(column.getType(resolver(out)).getBinding()));
final String columnVisibility =
scala || kotlin ?
"" :
"public ";
if (!printDeprecationIfUnknownType(out, columnTypeFull))
out.javadoc("The column <code>%s</code>.[[before= ][%s]]", column.getQualifiedOutputName(), list(escapeEntities(comment(column))));
if (scala) {
out.println("%sval %s: %s[%s, %s] = createField(%s.name(\"%s\"), %s, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ")",
columnVisibility, columnId, TableField.class, recordType, columnType, DSL.class, columnName, columnTypeRef, escapeString(comment(column)), converter, binding);
}
else if (kotlin) {
out.println("%sval %s: %s<%s, %s?> = createField(%s.name(\"%s\"), %s, this, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ")",
columnVisibility, columnId, TableField.class, recordType, columnType, DSL.class, columnName, columnTypeRef, escapeString(comment(column)), converter, binding);
}
else {
String isStatic = generateInstanceFields() ? "" : "static ";
String tableRef = generateInstanceFields() ? "this" : out.ref(getStrategy().getJavaIdentifier(table), 2);
out.println("%s%sfinal %s<%s, %s> %s = createField(%s.name(\"%s\"), %s, %s, \"%s\"" + converterTemplate(converter) + converterTemplate(binding) + ");",
columnVisibility, isStatic, TableField.class, recordType, columnType, columnId, DSL.class, columnName, columnTypeRef, tableRef, escapeString(comment(column)), converter, binding);
}
}
for (EmbeddableDefinition embeddable : table.getReferencedEmbeddables()) {
final String columnId = out.ref(getStrategy().getJavaIdentifier(embeddable), colRefSegments(null));
final String columnType = out.ref(getStrategy().getFullJavaClassName(embeddable, Mode.RECORD));
final List<String> columnIds = new ArrayList<>();
for (EmbeddableColumnDefinition column : embeddable.getColumns())
columnIds.add(out.ref(getStrategy().getJavaIdentifier(column.getReferencingColumn()), colRefSegments(column.getReferencingColumn())));
out.javadoc("The embeddable type <code>%s</code>.[[before= ][%s]]", embeddable.getOutputName(), list(escapeEntities(referencingComment(embeddable))));
if (scala)
out.println("val %s: %s[%s, %s] = %s.createEmbeddable(%s.name(\"%s\"), classOf[%s], %s, this, [[%s]])",
columnId, TableField.class, recordType, columnType, Internal.class, DSL.class, escapeString(embeddable.getName()), columnType, embeddable.replacesFields(), columnIds);
else if (kotlin)
out.println("val %s: %s<%s, %s> = %s.createEmbeddable(%s.name(\"%s\"), %s::class.java, %s, this, [[%s]])",
columnId, TableField.class, recordType, columnType, Internal.class, DSL.class, escapeString(embeddable.getName()), columnType, embeddable.replacesFields(), columnIds);
else
out.println("public final %s<%s, %s> %s = %s.createEmbeddable(%s.name(\"%s\"), %s.class, %s, this, [[%s]]);",
TableField.class, recordType, columnType, columnId, Internal.class, DSL.class, escapeString(embeddable.getName()), columnType, embeddable.replacesFields(), columnIds);
}
out.println();
if (scala) {
if (table.isTableValuedFunction())
out.println("private def this(alias: %s, aliased: %s[%s]) = this(alias, null, null, aliased, new %s[ %s[_] ](%s))",
Name.class, Table.class, recordType, out.ref("scala.Array"), Field.class, parameters.size());
else
out.println("private def this(alias: %s, aliased: %s[%s]) = this(alias, null, null, aliased, null)",
Name.class, Table.class, recordType);
}
else if (kotlin) {
if (table.isTableValuedFunction())
out.println("private constructor(alias: %s, aliased: %s<%s>?): this(alias, null, null, aliased, arrayOf())",
Name.class, Table.class, recordType, Field.class, parameters.size());
else
out.println("private constructor(alias: %s, aliased: %s<%s>?): this(alias, null, null, aliased, null)",
Name.class, Table.class, recordType);
out.println("private constructor(alias: %s, aliased: %s<%s>?, parameters: Array<%s<*>?>?): this(alias, null, null, aliased, parameters)",
Name.class, Table.class, recordType, Field.class);
}
else {
out.println("private %s(%s alias, %s<%s> aliased) {", className, Name.class, Table.class, recordType);
if (table.isTableValuedFunction())
out.println("this(alias, aliased, new %s[%s]);", Field.class, parameters.size());
else
out.println("this(alias, aliased, null);");
out.println("}");
out.println();
out.println("private %s(%s alias, %s<%s> aliased, %s<?>[] parameters) {", className, Name.class, Table.class, recordType, Field.class);
if (generateSourcesOnViews() && table.isView() && table.getSource() != null)
out.println("super(alias, null, aliased, parameters, %s.comment(\"%s\"), %s.%s(\"%s\"));", DSL.class, escapeString(comment(table)), TableOptions.class, tableType, escapeString(table.getSource()));
else
out.println("super(alias, null, aliased, parameters, %s.comment(\"%s\"), %s.%s());", DSL.class, escapeString(comment(table)), TableOptions.class, tableType);
out.println("}");
}
if (scala) {
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("def this(alias: %s) = this(%s.name(alias), %s)", String.class, DSL.class, tableId);
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("def this(alias: %s) = this(alias, %s)", Name.class, tableId);
}
else if (kotlin) {
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("constructor(alias: %s): this(%s.name(alias))", String.class, DSL.class);
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("constructor(alias: %s): this(alias, null)", Name.class, tableId);
}
else if (generateInstanceFields()) {
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("public %s(%s alias) {", className, String.class);
out.println("this(%s.name(alias), %s);", DSL.class, tableId);
out.println("}");
out.javadoc("Create an aliased <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("public %s(%s alias) {", className, Name.class);
out.println("this(alias, %s);", tableId);
out.println("}");
}
if (scala) {
out.javadoc("Create a <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("def this() = this(%s.name(\"%s\"), null)", DSL.class, escapeString(table.getOutputName()));
}
else if (kotlin) {
out.javadoc("Create a <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("constructor(): this(%s.name(\"%s\"), null)", DSL.class, escapeString(table.getOutputName()));
}
else {
if (generateInstanceFields()) {
out.javadoc("Create a <code>%s</code> table reference", table.getQualifiedOutputName());
out.println("public %s() {", className);
}
else {
out.javadoc(NO_FURTHER_INSTANCES_ALLOWED);
out.println("private %s() {", className);
}
out.println("this(%s.name(\"%s\"), null);", DSL.class, escapeString(table.getOutputName()));
out.println("}");
}
if (generateImplicitJoinPathsToOne() && generateGlobalKeyReferences() && !table.isTableValuedFunction()) {
out.println();
if (scala) {
out.println("def this(child: %s[_ <: %s], key: %s[_ <: %s, %s]) = this(%s.createPathAlias(child, key), child, key, %s, null)",
Table.class, Record.class, ForeignKey.class, Record.class, recordType, Internal.class, tableId);
}
else if (kotlin) {
out.println("constructor(child: %s<out %s>, key: %s<out %s, %s>): this(%s.createPathAlias(child, key), child, key, %s, null)",
Table.class, Record.class, ForeignKey.class, Record.class, recordType, Internal.class, tableId);
}
else {
out.println("public <O extends %s> %s(%s<O> child, %s<O, %s> key) {", Record.class, className, Table.class, ForeignKey.class, recordType);
out.println("super(child, key, %s);", tableId);
out.println("}");
}
}
if (scala) {
out.println();
out.println("override def getSchema: %s = %s", Schema.class, schemaId);
}
else if (kotlin) {
out.println("override fun getSchema(): %s = %s", Schema.class, schemaId);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s getSchema() {", Schema.class);
out.println("return %s;", schemaId);
out.println("}");
}
if (generateIndexes()) {
List<IndexDefinition> indexes = table.getIndexes();
if (!indexes.isEmpty()) {
if (generateGlobalIndexReferences()) {
final List<String> indexFullIds = kotlin
? out.ref(getStrategy().getFullJavaIdentifiers(indexes))
: out.ref(getStrategy().getFullJavaIdentifiers(indexes), 2);
if (scala) {
out.println();
out.println("override def getIndexes: %s[%s] = %s.asList[ %s ]([[%s]])",
List.class, Index.class, Arrays.class, Index.class, indexFullIds);
}
else if (kotlin) {
out.println("override fun getIndexes(): %s<%s> = listOf([[%s]])", out.ref(KLIST), Index.class, indexFullIds);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> getIndexes() {", List.class, Index.class);
out.println("return %s.<%s>asList([[%s]]);", Arrays.class, Index.class, indexFullIds);
out.println("}");
}
}
else {
String separator = "";
if (scala) {
out.println();
out.println("override def getIndexes: %s[%s] = %s.asList[%s](", List.class, Index.class, Arrays.class, Index.class);
for (IndexDefinition index : indexes) {
out.print("%s", separator);
printCreateIndex(out, index);
out.println();
separator = ", ";
}
out.println(")");
}
else if (kotlin) {
out.println("override fun getIndexes(): %s<%s> = listOf(", out.ref(KLIST), Index.class);
for (IndexDefinition index : indexes) {
out.print("%s", separator);
printCreateIndex(out, index);
out.println();
separator = ", ";
}
out.println(")");
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> getIndexes() {", List.class, Index.class);
out.println("return %s.<%s>asList(", Arrays.class, Index.class);
for (IndexDefinition index : indexes) {
out.print("%s", separator);
printCreateIndex(out, index);
out.println();
separator = ", ";
}
out.println(");");
out.println("}");
}
}
}
}
if (generateRelations()) {
IdentityDefinition identity = table.getIdentity();
if (identity != null) {
final String identityTypeFull = getJavaType(identity.getColumn().getType(resolver(out)), out);
final String identityType = out.ref(identityTypeFull);
if (scala) {
out.println();
printDeprecationIfUnknownType(out, identityTypeFull);
out.println("override def getIdentity: %s[%s, %s] = super.getIdentity.asInstanceOf[ %s[%s, %s] ]", Identity.class, recordType, identityType, Identity.class, recordType, identityType);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, identityTypeFull);
out.println("override fun getIdentity(): %s<%s, %s?> = super.getIdentity() as %s<%s, %s?>", Identity.class, recordType, identityType, Identity.class, recordType, identityType);
}
else {
if (printDeprecationIfUnknownType(out, identityTypeFull))
out.override();
else
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s, %s> getIdentity() {", Identity.class, recordType, identityType);
out.println("return (%s<%s, %s>) super.getIdentity();", Identity.class, recordType, identityType);
out.println("}");
}
}
if (primaryKey != null) {
final String keyFullId = generateGlobalKeyReferences()
? kotlin
? out.ref(getStrategy().getFullJavaIdentifier(primaryKey))
: out.ref(getStrategy().getFullJavaIdentifier(primaryKey), 2)
: null;
if (scala) {
out.println();
out.print("override def getPrimaryKey: %s[%s] = ", UniqueKey.class, recordType);
if (keyFullId != null)
out.print("%s", keyFullId);
else
printCreateUniqueKey(out, primaryKey);
out.println();
}
else if (kotlin) {
out.print("override fun getPrimaryKey(): %s<%s> = ", UniqueKey.class, recordType);
if (keyFullId != null)
out.print("%s", keyFullId);
else
printCreateUniqueKey(out, primaryKey);
out.println();
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> getPrimaryKey() {", UniqueKey.class, recordType);
out.print("return ");
if (keyFullId != null)
out.print("%s", keyFullId);
else
printCreateUniqueKey(out, primaryKey);
out.println(";");
out.println("}");
}
}
List<UniqueKeyDefinition> uniqueKeys = table.getUniqueKeys();
if (uniqueKeys.size() > 0) {
if (generateGlobalKeyReferences()) {
final List<String> keyFullIds = kotlin
? out.ref(getStrategy().getFullJavaIdentifiers(uniqueKeys))
: out.ref(getStrategy().getFullJavaIdentifiers(uniqueKeys), 2);
if (scala) {
out.println();
out.println("override def getKeys: %s[ %s[%s] ] = %s.asList[ %s[%s] ]([[%s]])",
List.class, UniqueKey.class, recordType, Arrays.class, UniqueKey.class, recordType, keyFullIds);
}
else if (kotlin) {
out.println("override fun getKeys(): %s<%s<%s>> = listOf([[%s]])", out.ref(KLIST), UniqueKey.class, recordType, keyFullIds);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s<%s>> getKeys() {", List.class, UniqueKey.class, recordType);
out.println("return %s.<%s<%s>>asList([[%s]]);", Arrays.class, UniqueKey.class, recordType, keyFullIds);
out.println("}");
}
}
else {
String separator = " ";
if (scala) {
out.println();
out.println("override def getKeys: %s[ %s[%s] ] = %s.asList[ %s[%s] ](",
List.class, UniqueKey.class, recordType, Arrays.class, UniqueKey.class, recordType);
for (UniqueKeyDefinition uniqueKey : uniqueKeys) {
out.print("%s", separator);
printCreateUniqueKey(out, uniqueKey);
out.println();
separator = ", ";
}
out.println(")");
}
else if (kotlin) {
out.println("override fun getKeys(): %s<%s<%s>> = listOf(", out.ref(KLIST), UniqueKey.class, recordType);
for (UniqueKeyDefinition uniqueKey : uniqueKeys) {
out.print("%s", separator);
printCreateUniqueKey(out, uniqueKey);
out.println();
separator = ", ";
}
out.println(")");
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s<%s>> getKeys() {", List.class, UniqueKey.class, recordType);
out.println("return %s.<%s<%s>>asList(", Arrays.class, UniqueKey.class, recordType);
for (UniqueKeyDefinition uniqueKey : uniqueKeys) {
out.print("%s", separator);
printCreateUniqueKey(out, uniqueKey);
out.println();
separator = ", ";
}
out.println(");");
out.println("}");
}
}
}
List<ForeignKeyDefinition> foreignKeys = table.getForeignKeys();
if (foreignKeys.size() > 0 && generateGlobalKeyReferences()) {
final List<String> keyFullIds = kotlin
? out.ref(getStrategy().getFullJavaIdentifiers(foreignKeys))
: out.ref(getStrategy().getFullJavaIdentifiers(foreignKeys), 2);
if (scala) {
out.println();
out.println("override def getReferences: %s[ %s[%s, _] ] = %s.asList[ %s[%s, _] ]([[%s]])",
List.class, ForeignKey.class, recordType, Arrays.class, ForeignKey.class, recordType, keyFullIds);
}
else if (kotlin) {
out.println("override fun getReferences(): %s<%s<%s, *>> = listOf([[%s]])", out.ref(KLIST), ForeignKey.class, recordType, keyFullIds);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s<%s, ?>> getReferences() {", List.class, ForeignKey.class, recordType);
out.println("return %s.<%s<%s, ?>>asList([[%s]]);", Arrays.class, ForeignKey.class, recordType, keyFullIds);
out.println("}");
}
if (generateImplicitJoinPathsToOne()) {
if (scala) {}
else {
out.println();
for (ForeignKeyDefinition foreignKey : foreignKeys) {
final String referencedTableClassName = out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable()));
final String keyMethodName = out.ref(getStrategy().getJavaMethodName(foreignKey));
if (kotlin)
out.println("private lateinit var _%s: %s", keyMethodName, referencedTableClassName);
else
out.println("private transient %s _%s;", referencedTableClassName, keyMethodName);
}
}
for (ForeignKeyDefinition foreignKey : foreignKeys) {
final String keyFullId = kotlin
? out.ref(getStrategy().getFullJavaIdentifier(foreignKey))
: out.ref(getStrategy().getFullJavaIdentifier(foreignKey), 2);
final String referencedTableClassName = out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable()));
final String keyMethodName = out.ref(getStrategy().getJavaMethodName(foreignKey));
if (scala) {
out.println("lazy val %s: %s = { new %s(this, %s) }", scalaWhitespaceSuffix(keyMethodName), referencedTableClassName, referencedTableClassName, keyFullId);
}
else if (kotlin) {
out.println("fun %s(): %s {", keyMethodName, referencedTableClassName);
out.println("if (!this::_%s.isInitialized)", keyMethodName);
out.println("_%s = %s(this, %s)", keyMethodName, referencedTableClassName, keyFullId);
out.println();
out.println("return _%s;", keyMethodName);
out.println("}");
}
else {
out.println();
out.println("public %s %s() {", referencedTableClassName, keyMethodName);
out.println("if (_%s == null)", keyMethodName);
out.println("_%s = new %s(this, %s);", keyMethodName, referencedTableClassName, keyFullId);
out.println();
out.println("return _%s;", keyMethodName);
out.println("}");
}
}
}
}
}
List<CheckConstraintDefinition> cc = table.getCheckConstraints();
if (!cc.isEmpty()) {
if (scala) {
out.println("override def getChecks: %s[ %s[%s] ] = %s.asList[ %s[%s] ](",
List.class, Check.class, recordType, Arrays.class, Check.class, recordType);
}
else if (kotlin) {
out.println("override fun getChecks(): %s<%s<%s>> = listOf(",
out.ref(KLIST), Check.class, recordType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s<%s>> getChecks() {", List.class, Check.class, recordType);
out.println("return %s.<%s<%s>>asList(", Arrays.class, Check.class, recordType);
}
String separator = " ";
for (CheckConstraintDefinition c : cc) {
out.println("%s%s.createCheck(this, %s.name(\"%s\"), \"%s\", %s)", separator, Internal.class, DSL.class, escapeString(c.getName()), escapeString(c.getCheckClause()), c.enforced());
separator = ", ";
}
if (scala || kotlin) {
out.println(")");
}
else {
out.println(");");
out.println("}");
}
}
versionLoop: for (String pattern : database.getRecordVersionFields()) {
Pattern p = Pattern.compile(pattern, Pattern.COMMENTS);
for (ColumnDefinition column : table.getColumns()) {
if ((p.matcher(column.getName()).matches() ||
p.matcher(column.getQualifiedName()).matches())) {
final String columnTypeFull = getJavaType(column.getType(resolver(out)), out);
final String columnType = out.ref(columnTypeFull);
final String columnId = getStrategy().getJavaIdentifier(column);
if (scala) {
printDeprecationIfUnknownType(out, columnTypeFull);
out.println("override def getRecordVersion: %s[%s, %s] = %s", TableField.class, recordType, columnType, columnId);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, columnTypeFull);
out.println("override fun getRecordVersion(): %s<%s, %s?> = %s", TableField.class, recordType, columnType, columnId);
}
else {
if (printDeprecationIfUnknownType(out, columnTypeFull))
out.override();
else
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s, %s> getRecordVersion() {", TableField.class, recordType, columnType);
out.println("return %s;", columnId);
out.println("}");
}
break versionLoop;
}
}
}
timestampLoop: for (String pattern : database.getRecordTimestampFields()) {
Pattern p = Pattern.compile(pattern, Pattern.COMMENTS);
for (ColumnDefinition column : table.getColumns()) {
if ((p.matcher(column.getName()).matches() ||
p.matcher(column.getQualifiedName()).matches())) {
final String columnTypeFull = getJavaType(column.getType(resolver(out)), out);
final String columnType = out.ref(columnTypeFull);
final String columnId = getStrategy().getJavaIdentifier(column);
if (scala) {
printDeprecationIfUnknownType(out, columnTypeFull);
out.println("override def getRecordTimestamp: %s[%s, %s] = %s", TableField.class, recordType, columnType, columnId);
}
else if (kotlin) {
printDeprecationIfUnknownType(out, columnTypeFull);
out.println("override fun getRecordTimestamp(): %s<%s, %s?> = %s", TableField.class, recordType, columnType, columnId);
}
else {
if (printDeprecationIfUnknownType(out, columnTypeFull))
out.override();
else
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s, %s> getRecordTimestamp() {", TableField.class, recordType, columnType);
out.println("return %s;", columnId);
out.println("}");
}
break timestampLoop;
}
}
}
if (scala) {
out.print("override def as(alias: %s): %s = ", String.class, className);
if (table.isTableValuedFunction())
out.println("new %s(%s.name(alias), null, null, this, parameters)", className, DSL.class);
else
out.println("new %s(%s.name(alias), this)", className, DSL.class);
out.print("override def as(alias: %s): %s = ", Name.class, className);
if (table.isTableValuedFunction())
out.println("new %s(alias, null, null, this, parameters)", className);
else
out.println("new %s(alias, this)", className);
}
else if (kotlin) {
out.print("override fun `as`(alias: %s): %s = ", String.class, className);
if (table.isTableValuedFunction())
out.println("%s(%s.name(alias), this, parameters)", className, DSL.class);
else
out.println("%s(%s.name(alias), this)", className, DSL.class);
out.print("override fun `as`(alias: %s): %s = ", Name.class, className);
if (table.isTableValuedFunction())
out.println("%s(alias, this, parameters)", className);
else
out.println("%s(alias, this)", className);
}
else if (generateInstanceFields()) {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s as(%s alias) {", className, String.class);
if (table.isTableValuedFunction())
out.println("return new %s(%s.name(alias), this, parameters);", className, DSL.class);
else
out.println("return new %s(%s.name(alias), this);", className, DSL.class);
out.println("}");
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s as(%s alias) {", className, Name.class);
if (table.isTableValuedFunction())
out.println("return new %s(alias, this, parameters);", className);
else
out.println("return new %s(alias, this);", className);
out.println("}");
}
if (scala) {
out.javadoc("Rename this table");
out.print("override def rename(name: %s): %s = ", String.class, className);
if (table.isTableValuedFunction())
out.println("new %s(%s.name(name), null, null, null, parameters)", className, DSL.class);
else
out.println("new %s(%s.name(name), null)", className, DSL.class);
out.javadoc("Rename this table");
out.print("override def rename(name: %s): %s = ", Name.class, className);
if (table.isTableValuedFunction())
out.println("new %s(name, null, null, null, parameters)", className);
else
out.println("new %s(name, null)", className);
}
else if (kotlin) {
out.javadoc("Rename this table");
out.print("override fun rename(name: %s): %s = ", String.class, className);
if (table.isTableValuedFunction())
out.println("%s(%s.name(name), null, parameters)", className, DSL.class);
else
out.println("%s(%s.name(name), null)", className, DSL.class);
out.javadoc("Rename this table");
out.print("override fun rename(name: %s): %s = ", Name.class, className);
if (table.isTableValuedFunction())
out.println("%s(name, null, parameters)", className);
else
out.println("%s(name, null)", className);
}
else if (generateInstanceFields()) {
out.javadoc("Rename this table");
out.override();
printNonnullAnnotation(out);
out.println("public %s rename(%s name) {", className, String.class);
if (table.isTableValuedFunction())
out.println("return new %s(%s.name(name), null, parameters);", className, DSL.class);
else
out.println("return new %s(%s.name(name), null);", className, DSL.class);
out.println("}");
out.javadoc("Rename this table");
out.override();
printNonnullAnnotation(out);
out.println("public %s rename(%s name) {", className, Name.class);
if (table.isTableValuedFunction())
out.println("return new %s(name, null, parameters);", className);
else
out.println("return new %s(name, null);", className);
out.println("}");
}
List<Definition> replacingEmbeddablesAndUnreplacedColumns = replacingEmbeddablesAndUnreplacedColumns(table);
int degree = replacingEmbeddablesAndUnreplacedColumns.size();
String rowType = refRowType(out, replacingEmbeddablesAndUnreplacedColumns);
if (generateRecordsImplementingRecordN() && degree > 0 && degree <= Constants.MAX_ROW_DEGREE) {
final String rowNType = out.ref(Row.class.getName() + degree);
out.header("Row%s type methods", degree);
if (scala) {
out.println("override def fieldsRow: %s[%s] = super.fieldsRow.asInstanceOf[ %s[%s] ]", rowNType, rowType, rowNType, rowType);
}
else if (kotlin) {
out.println("override fun fieldsRow(): %s<%s> = super.fieldsRow() as %s<%s>", rowNType, rowType, rowNType, rowType);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s<%s> fieldsRow() {", rowNType, rowType);
out.println("return (%s) super.fieldsRow();", rowNType);
out.println("}");
}
}
if (table.isTableValuedFunction()) {
for (boolean parametersAsField : new boolean[] { false, true }) {
if (parametersAsField && parameters.size() == 0)
break;
out.javadoc("Call this table-valued function");
if (scala) {
out.print("def call(").printlnIf(!parameters.isEmpty());
printParameterDeclarations(out, parameters, parametersAsField, " ");
out.print("): %s = ", className);
out.print("Option(new %s(%s.name(\"%s\"), null, null, null, %s(", className, DSL.class, escapeString(table.getOutputName()), out.ref("scala.Array")).printlnIf(!parameters.isEmpty());
String separator = " ";
for (ParameterDefinition parameter : parameters) {
final String paramArgName = getStrategy().getJavaMemberName(parameter);
final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType(resolver(out)), out);
final List<String> converter = out.ref(list(parameter.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(parameter.getType(resolver(out)).getBinding()));
out.print(separator);
if (parametersAsField)
out.println("%s", paramArgName);
else
out.println("%s.value(%s, %s" + converterTemplateForTableValuedFunction(converter) + converterTemplateForTableValuedFunction(binding) + ")", DSL.class, paramArgName, paramTypeRef, converter, binding);
separator = ", ";
}
out.println("))).map(r => if (aliased()) r.as(getUnqualifiedName) else r).get");
}
else if (kotlin) {
out.print("fun call(").printlnIf(!parameters.isEmpty());
printParameterDeclarations(out, parameters, parametersAsField, " ");
out.print("): %s = %s(%s.name(\"%s\"), null, arrayOf(", className, className, DSL.class, escapeString(table.getOutputName()), Field.class).printlnIf(!parameters.isEmpty());
String separator = " ";
for (ParameterDefinition parameter : parameters) {
final String paramArgName = getStrategy().getJavaMemberName(parameter);
final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType(resolver(out)), out);
final List<String> converter = out.ref(list(parameter.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(parameter.getType(resolver(out)).getBinding()));
if (parametersAsField)
out.println("%s%s", separator, paramArgName);
else
out.println("%s%s.value(%s, %s" + converterTemplateForTableValuedFunction(converter) + converterTemplateForTableValuedFunction(binding) + ")", separator, DSL.class, paramArgName, paramTypeRef, converter, binding);
separator = ", ";
}
out.println(")).let { if (aliased()) it.`as`(unqualifiedName) else it }");
}
else {
out.print("public %s call(", className).printlnIf(!parameters.isEmpty());
printParameterDeclarations(out, parameters, parametersAsField, " ");
out.println(") {");
out.print("%s result = new %s(%s.name(\"%s\"), null, new %s[] {", className, className, DSL.class, escapeString(table.getOutputName()), Field.class).printlnIf(!parameters.isEmpty());
String separator = " ";
for (ParameterDefinition parameter : parameters) {
final String paramArgName = getStrategy().getJavaMemberName(parameter);
final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType(resolver(out)), out);
final List<String> converter = out.ref(list(parameter.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(parameter.getType(resolver(out)).getBinding()));
out.print(separator);
if (parametersAsField)
out.println("%s", paramArgName);
else
out.println("%s.val(%s, %s" + converterTemplateForTableValuedFunction(converter) + converterTemplateForTableValuedFunction(binding) + ")", DSL.class, paramArgName, paramTypeRef, converter, binding);
separator = ", ";
}
out.println("});");
out.println();
out.println("return aliased() ? result.as(getUnqualifiedName()) : result;");
out.println("}");
}
}
}
generateTableClassFooter(table, out);
out.println("}");
closeJavaWriter(out);
}
private Iterable<EmbeddableDefinition> embeddables(SchemaDefinition schema) {
LinkedHashSet<EmbeddableDefinition> embeddables = new LinkedHashSet<>(database.getEmbeddables(schema));
for (EmbeddableDefinition embeddable : embeddables)
if (embeddable.getTable().equals(embeddable.getReferencingTable()))
embeddables.add(embeddable);
return embeddables;
}
protected void generateEmbeddables(SchemaDefinition schema) {
log.info("Generating embeddables");
Set<File> duplicates = new HashSet<>();
for (EmbeddableDefinition embeddable : embeddables(schema)) {
try {
if (duplicates.add(getFile(embeddable, Mode.RECORD)))
generateEmbeddable(schema, embeddable);
}
catch (Exception e) {
log.error("Error while generating embeddable " + embeddable, e);
}
}
watch.splitInfo("Tables generated");
}
@SuppressWarnings("unused")
protected void generateEmbeddable(SchemaDefinition schema, EmbeddableDefinition embeddable) {
JavaWriter out = newJavaWriter(getFile(embeddable, Mode.RECORD));
log.info("Generating embeddable", out.file().getName());
generateRecord0(embeddable, out);
closeJavaWriter(out);
}
protected void generateEmbeddablePojos(SchemaDefinition schema) {
log.info("Generating embeddable POJOs");
for (EmbeddableDefinition embeddable : embeddables(schema)) {
try {
generateEmbeddablePojo(embeddable);
}
catch (Exception e) {
log.error("Error while generating embeddable POJO " + embeddable, e);
}
}
watch.splitInfo("Embeddable POJOs generated");
}
@SuppressWarnings("unused")
protected void (EmbeddableDefinition embeddable, JavaWriter out) {}
protected void generateEmbeddablePojoClassJavadoc(EmbeddableDefinition embeddable, JavaWriter out) {
if (generateCommentsOnEmbeddables())
printClassJavadoc(out, embeddable);
else
printClassJavadoc(out, "The embeddable <code>" + embeddable.getQualifiedInputName() + "</code>.");
}
protected void generateEmbeddableInterfaces(SchemaDefinition schema) {
log.info("Generating embeddable interfaces");
for (EmbeddableDefinition embeddable : embeddables(schema)) {
try {
generateEmbeddableInterface(embeddable);
} catch (Exception e) {
log.error("Error while generating embeddable interface " + embeddable, e);
}
}
watch.splitInfo("embeddable interfaces generated");
}
@SuppressWarnings("unused")
protected void (EmbeddableDefinition embeddable, JavaWriter out) {}
protected void generateEmbeddableInterfaceClassJavadoc(EmbeddableDefinition embeddable, JavaWriter out) {
if (generateCommentsOnEmbeddables())
printClassJavadoc(out, embeddable);
else
printClassJavadoc(out, "The embeddable <code>" + embeddable.getQualifiedInputName() + "</code>.");
}
private String converterTemplate(List<String> converter) {
if (converter == null || converter.isEmpty())
return "[[]]";
if (converter.size() > 1)
throw new IllegalArgumentException();
switch (GenerationUtil.expressionType(converter.get(0))) {
case CONSTRUCTOR_REFERENCE:
switch (language) {
case KOTLIN:
return "[[before=, ][%s()]]";
case JAVA:
case SCALA:
default:
return "[[before=, ][new %s()]]";
}
case EXPRESSION:
return "[[before=, ][%s]]";
default:
throw new IllegalArgumentException();
}
}
private String converterTemplateForTableValuedFunction(List<String> converter) {
if (converter == null || converter.isEmpty())
return "[[]]";
if (converter.size() > 1)
throw new IllegalArgumentException();
switch (GenerationUtil.expressionType(converter.get(0))) {
case CONSTRUCTOR_REFERENCE:
switch (language) {
case KOTLIN:
return "[[before=.asConvertedDataType(][after=)][%s()]]";
case JAVA:
case SCALA:
default:
return "[[before=.asConvertedDataType(][after=)][new %s()]]";
}
case EXPRESSION:
return "[[before=.asConvertedDataType(][after=)][%s]]";
default:
throw new IllegalArgumentException();
}
}
private String escapeString(String string) {
if (string == null)
return null;
String result = string.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r");
if (kotlin)
result = result.replace("$", "\\$");
int max = 16384;
if (result.length() <= max)
return result;
StringBuilder sb = new StringBuilder("\" + \"");
for (int i = 0; i < result.length(); i += max) {
if (i > 0)
sb.append("\".toString() + \"");
sb.append(result.substring(i, Math.min(i + max, result.length())));
}
return sb.append("\".toString() + \"").toString();
}
@SuppressWarnings("unused")
protected void (TableDefinition table, JavaWriter out) {}
protected void generateTableClassJavadoc(TableDefinition table, JavaWriter out) {
if (generateCommentsOnTables())
printClassJavadoc(out, table);
else
printClassJavadoc(out, "The table <code>" + table.getQualifiedInputName() + "</code>.");
}
protected void generateSequences(SchemaDefinition schema) {
log.info("Generating sequences");
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, SequenceDefinition.class));
out.refConflicts(getStrategy().getJavaIdentifiers(database.getSequences(schema)));
printGlobalReferencesPackage(out, schema, SequenceDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all sequences in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, SequenceDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
else if (kotlin) {}
else
out.println("public class %s {", referencesClassName);
for (SequenceDefinition sequence : database.getSequences(schema)) {
final String seqTypeFull = getJavaType(sequence.getType(resolver(out)), out);
final String seqType = out.ref(seqTypeFull);
final String seqId = getStrategy().getJavaIdentifier(sequence);
final String seqName = sequence.getOutputName();
final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
final String typeRef = getJavaTypeReference(sequence.getDatabase(), sequence.getType(resolver(out)), out);
if (!printDeprecationIfUnknownType(out, seqTypeFull))
out.javadoc("The sequence <code>%s</code>", sequence.getQualifiedOutputName());
boolean flags = generateSequenceFlags();
if (scala)
out.println("val %s: %s[%s] = %s.createSequence(\"%s\", %s, %s, %s, %s, %s, %s, %s, %s)",
seqId,
Sequence.class,
seqType,
Internal.class,
seqName,
schemaId,
typeRef,
flags ? numberLiteral(sequence.getStartWith()) : "null",
flags ? numberLiteral(sequence.getIncrementBy()) : "null",
flags ? numberLiteral(sequence.getMinvalue()) : "null",
flags ? numberLiteral(sequence.getMaxvalue()) : "null",
flags && sequence.getCycle(),
flags ? numberLiteral(sequence.getCache()) : "null"
);
else if (kotlin)
out.println("val %s: %s<%s> = %s.createSequence(\"%s\", %s, %s, %s, %s, %s, %s, %s, %s)",
seqId,
Sequence.class,
seqType,
Internal.class,
seqName,
schemaId,
typeRef,
flags ? numberLiteral(sequence.getStartWith()) : "null",
flags ? numberLiteral(sequence.getIncrementBy()) : "null",
flags ? numberLiteral(sequence.getMinvalue()) : "null",
flags ? numberLiteral(sequence.getMaxvalue()) : "null",
flags && sequence.getCycle(),
flags ? numberLiteral(sequence.getCache()) : "null"
);
else
out.println("public static final %s<%s> %s = %s.createSequence(\"%s\", %s, %s, %s, %s, %s, %s, %s, %s);",
Sequence.class,
seqType,
seqId,
Internal.class,
seqName,
schemaId,
typeRef,
flags ? numberLiteral(sequence.getStartWith()) : "null",
flags ? numberLiteral(sequence.getIncrementBy()) : "null",
flags ? numberLiteral(sequence.getMinvalue()) : "null",
flags ? numberLiteral(sequence.getMaxvalue()) : "null",
flags && sequence.getCycle(),
flags ? numberLiteral(sequence.getCache()) : "null"
);
}
generateSequencesClassFooter(schema, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("Sequences generated");
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
private String numberLiteral(Number n) {
if (n instanceof BigInteger) {
BigInteger bi = (BigInteger) n;
int bitLength = ((BigInteger) n).bitLength();
if (bitLength > Long.SIZE - 1)
return "new java.math.BigInteger(\"" + bi.toString() + "\")";
else if (bitLength > Integer.SIZE - 1)
return Long.toString(n.longValue()) + 'L';
else
return Integer.toString(n.intValue());
}
else if (n instanceof Integer || n instanceof Short || n instanceof Byte)
return Integer.toString(n.intValue());
else if (n != null)
return Long.toString(n.longValue()) + 'L';
return "null";
}
protected void generateCatalog(CatalogDefinition catalog) {
JavaWriter out = newJavaWriter(getFile(catalog));
log.info("");
log.info("Generating catalog", out.file().getName());
log.info("==========================================================");
generateCatalog(catalog, out);
closeJavaWriter(out);
}
protected void generateCatalog(CatalogDefinition catalog, JavaWriter out) {
final String catalogId = getStrategy().getJavaIdentifier(catalog);
final String catalogName = !catalog.getQualifiedOutputName().isEmpty() ? catalog.getQualifiedOutputName() : catalogId;
final String className = getStrategy().getJavaClassName(catalog);
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(catalog, Mode.DEFAULT));
printPackage(out, catalog);
if (scala) {
out.println("object %s {", className);
out.javadoc("The reference instance of <code>%s</code>", catalogName);
out.println("val %s = new %s", catalogId, className);
out.println("}");
out.println();
}
generateCatalogClassJavadoc(catalog, out);
printClassAnnotations(out, catalog, Mode.DEFAULT);
if (scala) {
out.println("class %s extends %s(\"%s\")[[before= with ][separator= with ][%s]] {", className, CatalogImpl.class, catalog.getOutputName(), interfaces);
}
else if (kotlin) {
out.println("open class %s : %s(\"%s\")[[before=, ][%s]] {", className, CatalogImpl.class, catalog.getOutputName(), interfaces);
out.println("companion object {");
out.javadoc("The reference instance of <code>%s</code>", catalogName);
out.println("val %s = %s()", catalogId, className);
out.println("}");
}
else {
out.println("public class %s extends %s[[before= implements ][%s]] {", className, CatalogImpl.class, interfaces);
out.printSerial();
out.javadoc("The reference instance of <code>%s</code>", catalogName);
out.println("public static final %s %s = new %s();", className, catalogId, className);
}
List<SchemaDefinition> schemas = new ArrayList<>();
if (generateGlobalSchemaReferences()) {
Set<String> fieldNames = new HashSet<>();
fieldNames.add(catalogId);
for (SchemaDefinition schema : catalog.getSchemata())
if (generateSchemaIfEmpty(schema))
fieldNames.add(getStrategy().getJavaIdentifier(schema));
for (SchemaDefinition schema : catalog.getSchemata()) {
if (generateSchemaIfEmpty(schema)) {
schemas.add(schema);
final String schemaClassName = out.ref(getStrategy().getFullJavaClassName(schema));
final String schemaId = getStrategy().getJavaIdentifier(schema);
final String schemaFullId = getStrategy().getFullJavaIdentifier(schema);
String schemaShortId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
if (fieldNames.contains(schemaShortId.substring(0, schemaShortId.indexOf('.'))))
schemaShortId = schemaFullId;
final String schemaComment = escapeEntities(comment(schema));
out.javadoc(isBlank(schemaComment) ? ("The schema <code>" + (!schema.getQualifiedOutputName().isEmpty() ? schema.getQualifiedOutputName() : schemaId) + "</code>.") : schemaComment);
if (scala)
out.println("def %s = %s", schemaId, schemaShortId);
else if (kotlin)
out.println("val %s get() = %s", schemaId, schemaShortId);
else
out.println("public final %s %s = %s;", schemaClassName, schemaId, schemaShortId);
}
}
}
if (scala || kotlin)
;
else {
out.javadoc(NO_FURTHER_INSTANCES_ALLOWED);
out.println("private %s() {", className);
out.println("super(\"%s\");", catalog.getOutputName());
out.println("}");
}
printReferences(out, schemas, Schema.class, false);
generateCatalogClassFooter(catalog, out);
out.println("}");
}
@SuppressWarnings("unused")
protected void (CatalogDefinition schema, JavaWriter out) {}
protected void generateCatalogClassJavadoc(CatalogDefinition catalog, JavaWriter out) {
if (generateCommentsOnCatalogs())
printClassJavadoc(out, catalog);
else
printClassJavadoc(out, "The catalog <code>" + catalog.getQualifiedInputName() + "</code>.");
}
protected void generateSchema(SchemaDefinition schema) {
JavaWriter out = newJavaWriter(getFile(schema));
log.info("Generating schema", out.file().getName());
log.info("----------------------------------------------------------");
generateSchema(schema, out);
closeJavaWriter(out);
}
protected void generateSchema(SchemaDefinition schema, JavaWriter out) {
final String catalogId = out.ref(getStrategy().getFullJavaIdentifier(schema.getCatalog()), 2);
final String schemaId = getStrategy().getJavaIdentifier(schema);
final String schemaName = !schema.getQualifiedOutputName().isEmpty() ? schema.getQualifiedOutputName() : schemaId;
final String className = getStrategy().getJavaClassName(schema);
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(schema, Mode.DEFAULT));
printPackage(out, schema);
if (scala) {
out.println("object %s {", className);
out.javadoc("The reference instance of <code>%s</code>", schemaName);
out.println("val %s = new %s", schemaId, className);
out.println("}");
out.println();
}
generateSchemaClassJavadoc(schema, out);
printClassAnnotations(out, schema, Mode.DEFAULT);
if (scala) {
out.println("class %s extends %s(\"%s\", %s)[[before= with ][separator= with ][%s]] {", className, SchemaImpl.class, escapeString(schema.getOutputName()), catalogId, interfaces);
}
else if (kotlin) {
out.println("open class %s : %s(\"%s\", %s)[[before=, ][%s]] {", className, SchemaImpl.class, escapeString(schema.getOutputName()), catalogId, interfaces);
out.println("companion object {");
out.javadoc("The reference instance of <code>%s</code>", schemaName);
out.println("val %s = %s()", schemaId, className);
out.println("}");
}
else {
out.println("public class %s extends %s[[before= implements ][%s]] {", className, SchemaImpl.class, interfaces);
out.printSerial();
out.javadoc("The reference instance of <code>%s</code>", schemaName);
out.println("public static final %s %s = new %s();", className, schemaId, className);
}
if (generateGlobalTableReferences()) {
Set<String> memberNames = getMemberNames(schema);
for (TableDefinition table : schema.getTables()) {
if (scala && table.isTableValuedFunction() && table.getParameters().isEmpty())
continue;
final String tableClassName = out.ref(getStrategy().getFullJavaClassName(table));
final String tableId = getStrategy().getJavaIdentifier(table);
final String tableShortId = getShortId(out, memberNames, table);
final String tableComment = escapeEntities(comment(table));
out.javadoc(isBlank(tableComment) ? "The table <code>" + table.getQualifiedOutputName() + "</code>." : tableComment);
if (scala)
out.println("def %s = %s", tableId, tableShortId);
else if (kotlin)
out.println("val %s get() = %s", tableId, tableShortId);
else
out.println("public final %s %s = %s;", tableClassName, tableId, tableShortId);
if (table.isTableValuedFunction())
printTableValuedFunction(out, table, getStrategy().getJavaIdentifier(table));
}
}
if (!scala && !kotlin) {
out.javadoc(NO_FURTHER_INSTANCES_ALLOWED);
out.println("private %s() {", className);
out.println("super(\"%s\", null);", escapeString(schema.getOutputName()));
out.println("}");
}
out.println();
if (scala) {
out.println("override def getCatalog: %s = %s", Catalog.class, catalogId);
}
else if (kotlin) {
out.println("override fun getCatalog(): %s = %s", Catalog.class, catalogId);
}
else {
out.overrideInherit();
printNonnullAnnotation(out);
out.println("public %s getCatalog() {", Catalog.class);
out.println("return %s;", catalogId);
out.println("}");
}
if (generateGlobalSequenceReferences())
printReferences(out, database.getSequences(schema), Sequence.class, true);
if (generateGlobalDomainReferences())
printReferences(out, database.getDomains(schema), Domain.class, true);
if (generateTables())
printReferences(out, database.getTables(schema), Table.class, true);
if (generateUDTs())
printReferences(out, database.getUDTs(schema), UDT.class, true);
generateSchemaClassFooter(schema, out);
out.println("}");
}
private Set<String> getMemberNames(CatalogDefinition catalog) {
Set<String> members = new HashSet<>();
members.add(getStrategy().getJavaIdentifier(catalog));
for (SchemaDefinition table : catalog.getSchemata())
members.add(getStrategy().getJavaIdentifier(table));
return members;
}
private Set<String> getMemberNames(SchemaDefinition schema) {
Set<String> members = new HashSet<>();
members.add(getStrategy().getJavaIdentifier(schema));
for (TableDefinition table : schema.getTables())
members.add(getStrategy().getJavaIdentifier(table));
return members;
}
private String getShortId(JavaWriter out, Set<String> memberNames, Definition table) {
String shortId = out.ref(getStrategy().getFullJavaIdentifier(table), 2);
if (memberNames.contains(shortId.substring(0, shortId.indexOf('.'))))
shortId = getStrategy().getFullJavaIdentifier(table);
return shortId;
}
@SuppressWarnings("unused")
protected void (SchemaDefinition schema, JavaWriter out) {}
protected void generateSchemaClassJavadoc(SchemaDefinition schema, JavaWriter out) {
if (generateCommentsOnSchemas())
printClassJavadoc(out, schema);
else
printClassJavadoc(out, "The schema <code>" + schema.getQualifiedInputName() + "</code>.");
}
protected void printFromAndInto(JavaWriter out, TableDefinition table) {
printFromAndInto(out, table, Mode.DEFAULT);
}
private void printFromAndInto(JavaWriter out, Definition tableOrUDT, Mode mode) {
String qualified = out.ref(getStrategy().getFullJavaClassName(tableOrUDT, Mode.INTERFACE));
out.header("FROM and INTO");
boolean override = generateInterfaces() && !generateImmutableInterfaces();
if (scala) {
out.println();
out.println("%sdef from(from: %s) {", (override ? "override " : ""), qualified);
}
else if (kotlin) {
out.println();
out.println("%sfun from(from: %s) {", (override ? "override " : ""), qualified);
}
else {
out.overrideInheritIf(override);
out.println("public void from(%s from) {", qualified);
}
for (TypedElementDefinition<?> column : getTypedElements(tableOrUDT)) {
final String setter = getStrategy().getJavaSetterName(column, Mode.INTERFACE);
final String getter = getStrategy().getJavaGetterName(column, Mode.INTERFACE);
final String member = getStrategy().getJavaMemberName(column, Mode.POJO);
if (scala)
out.println("%s(from.%s)", setter, getter);
else if (kotlin)
out.println("%s = from.%s", member, member);
else
out.println("%s(from.%s());", setter, getter);
}
out.println("}");
if (override) {
if (scala) {
if (mode != Mode.POJO) {
out.println();
out.println("override def into [E](into: E): E = {", qualified);
out.println("if (into.isInstanceOf[%s])", qualified);
out.println("into.asInstanceOf[%s].from(this)", qualified);
out.println("else");
out.println("super.into(into)");
out.println("into");
out.println("}");
}
}
else if (kotlin) {
out.println();
out.println("%sfun <E : %s> into(into: E): E {", (override ? "override " : ""), qualified);
out.println("into.from(this)");
out.println("return into");
out.println("}");
}
else {
out.overrideInherit();
out.println("public <E extends %s> E into(E into) {", qualified);
out.println("into.from(this);");
out.println("return into;");
out.println("}");
}
}
}
protected void printReferences(JavaWriter out, List<? extends Definition> definitions, Class<?> type, boolean isGeneric) {
if (out != null && !definitions.isEmpty()) {
final String generic = isGeneric ? (scala ? "[_]" : kotlin ? "<*>" : "<?>") : "";
final List<String> references = new ArrayList<>();
final Definition first = definitions.get(0);
if ((scala || kotlin) && (first instanceof TableDefinition || first instanceof UDTDefinition)) {
final Set<String> memberNames = getMemberNames(first.getSchema());
for (Definition table : definitions)
references.add(getShortId(out, memberNames, table));
}
else if ((scala || kotlin) && first instanceof SchemaDefinition) {
final Set<String> memberNames = getMemberNames(first.getCatalog());
for (Definition schema : definitions)
references.add(getShortId(out, memberNames, schema));
}
else {
references.addAll(kotlin
? out.ref(getStrategy().getFullJavaIdentifiers(definitions))
: out.ref(getStrategy().getFullJavaIdentifiers(definitions), 2));
}
out.println();
if (scala) {
out.println("override def get%ss: %s[%s%s] = {", type.getSimpleName(), List.class, type, generic);
if (definitions.size() > maxMembersPerInitialiser()) {
out.println("val result = new %s[%s%s]", ArrayList.class, type, generic);
for (int i = 0; i < definitions.size(); i += maxMembersPerInitialiser())
out.println("result.addAll(get%ss%s)", type.getSimpleName(), i / maxMembersPerInitialiser());
out.println("result");
}
else
out.println("return %s.asList[%s%s]([[before=\n\t\t\t][separator=,\n\t\t\t][%s]])", Arrays.class, type, generic, references);
out.println("}");
}
else if (kotlin) {
if (definitions.size() > maxMembersPerInitialiser()) {
out.println("override fun get%ss(): %s<%s%s> {", type.getSimpleName(), out.ref(KLIST), type, generic);
out.println("val result = mutableListOf<%s%s>()", type, generic);
for (int i = 0; i < definitions.size(); i += maxMembersPerInitialiser())
out.println("result.addAll(get%ss%s())", type.getSimpleName(), i / maxMembersPerInitialiser());
out.println("return result");
out.println("}");
}
else {
out.println("override fun get%ss(): %s<%s%s> = listOf(", type.getSimpleName(), out.ref(KLIST), type, generic);
out.println("[[separator=,\n\t\t][%s]]", references);
out.println(")");
}
}
else {
out.override();
printNonnullAnnotation(out);
out.println("public final %s<%s%s> get%ss() {", List.class, type, generic, type.getSimpleName());
if (definitions.size() > maxMembersPerInitialiser()) {
out.println("%s result = new %s();", List.class, ArrayList.class);
for (int i = 0; i < definitions.size(); i += maxMembersPerInitialiser())
out.println("result.addAll(get%ss%s());", type.getSimpleName(), i / maxMembersPerInitialiser());
out.println("return result;");
}
else {
out.println("return %s.<%s%s>asList([[before=\n\t\t\t][separator=,\n\t\t\t][%s]]);", Arrays.class, type, generic, references);
}
out.println("}");
}
if (definitions.size() > maxMembersPerInitialiser()) {
for (int i = 0; i < definitions.size(); i += maxMembersPerInitialiser()) {
out.println();
if (scala) {
out.println("private def get%ss%s(): %s[%s%s] = %s.asList[%s%s](", type.getSimpleName(), i / maxMembersPerInitialiser(), List.class, type, generic, Arrays.class, type, generic);
out.println("[[before=\n\t\t\t][separator=,\n\t\t\t][%s]]", references.subList(i, Math.min(i + maxMembersPerInitialiser(), references.size())));
out.println(")");
}
else if (kotlin) {
out.println("private fun get%ss%s(): %s<%s%s> = listOf(", type.getSimpleName(), i / maxMembersPerInitialiser(), out.ref(KLIST), type, generic);
out.println("[[before=\t][separator=,\n\t\t\t][%s]]", references.subList(i, Math.min(i + maxMembersPerInitialiser(), references.size())));
out.println(")");
}
else {
out.println("private final %s<%s%s> get%ss%s() {", List.class, type, generic, type.getSimpleName(), i / maxMembersPerInitialiser());
out.println("return %s.<%s%s>asList([[before=\n\t\t\t][separator=,\n\t\t\t][%s]]);", Arrays.class, type, generic, references.subList(i, Math.min(i + maxMembersPerInitialiser(), references.size())));
out.println("}");
}
}
}
}
}
protected void printTableJPAAnnotation(JavaWriter out, TableDefinition table) {
SchemaDefinition schema = table.getSchema();
int indent = out.indent();
if (generateJPAAnnotations()) {
out.println("@%s", out.ref("javax.persistence.Entity"));
out.println("@%s(", out.ref("javax.persistence.Table"));
out.print("name = \"", out.ref("javax.persistence.Table"));
out.print(escapeString(table.getName()));
out.print("\"");
if (!schema.isDefaultSchema()) {
out.println(",");
out.print("schema = \"");
out.print(escapeString(schema.getOutputName()));
out.print("\"");
}
List<UniqueKeyDefinition> keys = table.getUniqueKeys();
if (!keys.isEmpty()) {
out.println(",");
out.print("uniqueConstraints = ");
out.println(scala ? "Array(" : kotlin ? "[" : "{");
for (int i = 0; i < keys.size(); i++) {
UniqueKeyDefinition uk = keys.get(i);
out.print(scala ? "new " : kotlin ? "" : "@")
.print(out.ref("javax.persistence.UniqueConstraint"))
.print("(");
if (!StringUtils.isBlank(uk.getOutputName()))
out.print("name = \"" + escapeString(uk.getOutputName()) + "\", ");
out.print("columnNames = ")
.print(scala ? "Array(" : kotlin ? "[ " : "{ ");
List<ColumnDefinition> columns = uk.getKeyColumns();
for (int j = 0; j < columns.size(); j++) {
out.print(j > 0 ? ", " : "");
out.print("\"");
out.print(escapeString(columns.get(j).getName()));
out.print("\"");
}
out.print(scala ? ")" : kotlin ? " ]" : " }").print(")").println(i < keys.size() - 1 ? "," : "");
}
out.print(scala ? ")" : kotlin ? "]" : "}");
}
if (StringUtils.isBlank(generateJPAVersion()) || "2.1".compareTo(generateJPAVersion()) <= 0) {
List<IndexDefinition> indexes = table.getIndexes();
if (!indexes.isEmpty()) {
out.println(",");
out.print("indexes = ").println(scala ? "Array(" : kotlin ? "[" : "{");
for (int i = 0; i < indexes.size(); i++) {
IndexDefinition index = indexes.get(i);
out.print(scala ? "new " : kotlin ? "" : "@");
out.print(out.ref("javax.persistence.Index"));
out.print("(name = \"").print(escapeString(index.getOutputName())).print("\"");
if (index.isUnique())
out.print(", unique = true");
out.print(", columnList = \"");
List<IndexColumnDefinition> columns = index.getIndexColumns();
for (int j = 0; j < columns.size(); j++) {
IndexColumnDefinition column = columns.get(j);
if (j > 0)
out.print(", ");
out.print(escapeString(column.getOutputName()));
if (column.getSortOrder() == SortOrder.ASC)
out.print(" ASC");
else if (column.getSortOrder() == SortOrder.DESC)
out.print(" DESC");
}
out.print("\")").println(i < indexes.size() - 1 ? "," : "");
}
out.print(scala ? ")" : kotlin ? "]" : "}");
}
}
out.println();
out.println(")");
}
out.indent(indent);
}
protected void printColumnJPAAnnotation(JavaWriter out, ColumnDefinition column) {
int indent = out.indent();
if (generateJPAAnnotations()) {
String prefix = kotlin ? "get:" : "";
UniqueKeyDefinition pk = column.getPrimaryKey();
if (pk != null) {
if (pk.getKeyColumns().size() == 1) {
out.println("@%s%s", prefix, out.ref("javax.persistence.Id"));
if (pk.getKeyColumns().get(0).isIdentity())
out.println("@%s%s(strategy = %s.IDENTITY)",
prefix,
out.ref("javax.persistence.GeneratedValue"),
out.ref("javax.persistence.GenerationType")
);
}
}
String nullable = "";
if (!column.getType(resolver(out)).isNullable())
nullable = ", nullable = false";
String length = "";
String precision = "";
String scale = "";
if (column.getType(resolver(out)).getLength() > 0) {
length = ", length = " + column.getType(resolver(out)).getLength();
}
else if (column.getType(resolver(out)).getPrecision() > 0) {
precision = ", precision = " + column.getType(resolver(out)).getPrecision();
if (column.getType(resolver(out)).getScale() > 0) {
scale = ", scale = " + column.getType(resolver(out)).getScale();
}
}
out.print("@%s%s(name = \"", prefix, out.ref("javax.persistence.Column"));
out.print(escapeString(column.getName()));
out.print("\"");
out.print(nullable);
out.print(length);
out.print(precision);
out.print(scale);
out.println(")");
}
out.indent(indent);
}
@Deprecated
protected void printColumnValidationAnnotation(JavaWriter out, ColumnDefinition column) {
printValidationAnnotation(out, column);
}
private void printValidationAnnotation(JavaWriter out, TypedElementDefinition<?> column) {
if (generateValidationAnnotations()) {
String prefix = kotlin ? "get:" : "";
DataTypeDefinition type = column.getType(resolver(out));
if (!column.getType(resolver(out)).isNullable() &&
!column.getType(resolver(out)).isDefaulted() &&
!column.getType(resolver(out)).isIdentity())
out.println("@%s%s", prefix, out.ref("javax.validation.constraints.NotNull"));
String javaType = getJavaType(type, out);
if ("java.lang.String".equals(javaType) || "byte[]".equals(javaType)) {
int length = type.getLength();
if (length > 0)
out.println("@%s%s(max = %s)", prefix, out.ref("javax.validation.constraints.Size"), length);
}
}
}
private String nullableAnnotation(JavaWriter out) {
return generateNullableAnnotation() ? out.ref(generatedNullableAnnotationType()) : null;
}
private String nonnullAnnotation(JavaWriter out) {
return generateNonnullAnnotation() ? out.ref(generatedNonnullAnnotationType()) : null;
}
private String nullableOrNonnullAnnotation(JavaWriter out, Definition column) {
return (column instanceof TypedElementDefinition && ((TypedElementDefinition<?>) column).getType().isNullable())
? nullableAnnotation(out)
: nonnullAnnotation(out);
}
private void printNullableOrNonnullAnnotation(JavaWriter out, Definition column) {
if (column instanceof TypedElementDefinition && ((TypedElementDefinition<?>) column).getType().isNullable())
printNullableAnnotation(out);
else
printNonnullAnnotation(out);
}
protected void printNullableAnnotation(JavaWriter out) {
if (generateNullableAnnotation())
out.println("@%s", out.ref(generatedNullableAnnotationType()));
}
protected void printNonnullAnnotation(JavaWriter out) {
if (generateNonnullAnnotation())
out.println("@%s", out.ref(generatedNonnullAnnotationType()));
}
private boolean printDeprecationIfUnknownTypes(JavaWriter out, Collection<? extends ParameterDefinition> params) {
for (ParameterDefinition param : params)
if (printDeprecationIfUnknownType(out, getJavaType(param.getType(resolver(out)), out)))
return true;
return false;
}
private boolean printDeprecationIfUnknownType(JavaWriter out, String type) {
if (generateDeprecationOnUnknownTypes() && (Object.class.getName().equals(type) || kotlin && "Any".equals(type))) {
if (kotlin) {
out.println("@%s(message = \"%s\")", out.ref("kotlin.Deprecated"), escapeString(
"Unknown data type. Please define an explicit org.jooq.Binding to specify how this type should be handled. "
+ "Deprecation can be turned off using <deprecationOnUnknownTypes/> in your code generator configuration."));
}
else {
out.javadoc("@deprecated Unknown data type. "
+ "Please define an explicit {@link org.jooq.Binding} to specify how this "
+ "type should be handled. Deprecation can be turned off using {@literal <deprecationOnUnknownTypes/>} "
+ "in your code generator configuration.");
out.println("@%s", out.ref(Deprecated.class));
}
return true;
}
else {
return false;
}
}
@SuppressWarnings("unused")
protected void generateRoutine(SchemaDefinition schema, RoutineDefinition routine) {
JavaWriter out = newJavaWriter(getFile(routine));
log.info("Generating routine", out.file().getName());
if (log.isDebugEnabled())
for (ParameterDefinition parameter : routine.getAllParameters())
log.debug("With parameter", "name=" + parameter.getOutputName() + ", matching type names=" + parameter.getDefinedType().getMatchNames());
generateRoutine(routine, out);
closeJavaWriter(out);
}
protected void generateRoutine(RoutineDefinition routine, JavaWriter out) {
final SchemaDefinition schema = routine.getSchema();
final String className = getStrategy().getJavaClassName(routine);
final String returnTypeFull = (routine.getReturnValue() == null)
? Void.class.getName()
: getJavaType(routine.getReturnType(resolver(out)), out);
final String returnType = (routine.getReturnValue() == null)
? Void.class.getName()
: out.ref(returnTypeFull);
final List<String> returnTypeRef = list((routine.getReturnValue() != null)
? getJavaTypeReference(database, routine.getReturnType(resolver(out)), out)
: null);
final List<String> returnConverter = out.ref(list(
(routine.getReturnValue() != null)
? routine.getReturnType(resolver(out)).getConverter()
: null));
final List<String> returnBinding = out.ref(list(
(routine.getReturnValue() != null)
? routine.getReturnType(resolver(out)).getBinding()
: null));
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(routine, Mode.DEFAULT));
final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2);
final List<String> packageId = out.ref(getStrategy().getFullJavaIdentifiers(routine.getPackage()), 2);
printPackage(out, routine);
if (scala) {
out.println("object %s {", className);
for (ParameterDefinition parameter : routine.getAllParameters()) {
final String paramTypeFull = getJavaType(parameter.getType(resolver(out)), out);
final String paramType = out.ref(paramTypeFull);
final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType(resolver(out)), out);
final String paramId = out.ref(getStrategy().getJavaIdentifier(parameter), 2);
final String paramName = parameter.getName();
final String isDefaulted = parameter.isDefaulted() ? "true" : "false";
final String isUnnamed = parameter.isUnnamed() ? "true" : "false";
final List<String> converter = out.ref(list(parameter.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(parameter.getType(resolver(out)).getBinding()));
if (!printDeprecationIfUnknownType(out, paramTypeFull))
out.javadoc("The parameter <code>%s</code>.[[before= ][%s]]", parameter.getQualifiedOutputName(), list(escapeEntities(comment(parameter))));
out.println("val %s: %s[%s] = %s.createParameter(\"%s\", %s, %s, %s" + converterTemplate(converter) + converterTemplate(binding) + ")",
paramId, Parameter.class, paramType, Internal.class, escapeString(paramName), paramTypeRef, isDefaulted, isUnnamed, converter, binding);
}
out.println("}");
out.println();
}
if (!printDeprecationIfUnknownType(out, returnTypeFull))
generateRoutineClassJavadoc(routine, out);
printClassAnnotations(out, routine, Mode.DEFAULT);
if (scala) {
out.println("class %s extends %s[%s](\"%s\", %s[[before=, ][%s]][[before=, ][%s]]" + converterTemplate(returnConverter) + converterTemplate(returnBinding) + ")[[before= with ][separator= with ][%s]] {",
className, AbstractRoutine.class, returnType, escapeString(routine.getName()), schemaId, packageId, returnTypeRef, returnConverter, returnBinding, interfaces);
}
else {
if (kotlin) {
out.println("open class %s : %s<%s>(\"%s\", %s[[before=, ][%s]][[before=, ][%s]]" + converterTemplate(returnConverter) + converterTemplate(returnBinding) + ")[[before=, ][%s]] {",
className, AbstractRoutine.class, returnType, escapeString(routine.getName()), schemaId, packageId, returnTypeRef, returnConverter, returnBinding, interfaces);
}
else {
out.println("public class %s extends %s<%s>[[before= implements ][%s]] {",
className, AbstractRoutine.class, returnType, interfaces);
out.printSerial();
}
if (kotlin)
out.println("companion object {");
for (ParameterDefinition parameter : routine.getAllParameters()) {
final String paramTypeFull = getJavaType(parameter.getType(resolver(out)), out);
final String paramType = out.ref(paramTypeFull);
final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType(resolver(out)), out);
final String paramId = getStrategy().getJavaIdentifier(parameter);
final String paramName = parameter.getName();
final String isDefaulted = parameter.isDefaulted() ? "true" : "false";
final String isUnnamed = parameter.isUnnamed() ? "true" : "false";
final List<String> converter = out.ref(list(parameter.getType(resolver(out)).getConverter()));
final List<String> binding = out.ref(list(parameter.getType(resolver(out)).getBinding()));
if (!printDeprecationIfUnknownType(out, paramTypeFull))
out.javadoc("The parameter <code>%s</code>.[[before= ][%s]]", parameter.getQualifiedOutputName(), list(escapeEntities(comment(parameter))));
if (kotlin)
out.println("val %s: %s<%s?> = %s.createParameter(\"%s\", %s, %s, %s" + converterTemplate(converter) + converterTemplate(binding) + ")",
paramId, Parameter.class, paramType, Internal.class, escapeString(paramName), paramTypeRef, isDefaulted, isUnnamed, converter, binding);
else
out.println("public static final %s<%s> %s = %s.createParameter(\"%s\", %s, %s, %s" + converterTemplate(converter) + converterTemplate(binding) + ");",
Parameter.class, paramType, paramId, Internal.class, escapeString(paramName), paramTypeRef, isDefaulted, isUnnamed, converter, binding);
}
if (kotlin)
out.println("}").println();
}
if (scala) {
out.println("{");
}
else if (kotlin) {
out.println("init {");
}
else {
out.javadoc("Create a new routine call instance");
out.println("public %s() {", className);
out.println("super(\"%s\", %s[[before=, ][%s]][[before=, ][%s]]" + converterTemplate(returnConverter) + converterTemplate(returnBinding) + ");", routine.getName(), schemaId, packageId, returnTypeRef, returnConverter, returnBinding);
if (routine.getAllParameters().size() > 0)
out.println();
}
for (ParameterDefinition parameter : routine.getAllParameters()) {
final String paramId = getStrategy().getJavaIdentifier(parameter);
if (parameter.equals(routine.getReturnValue())) {
if (parameter.isSynthetic()) {
if (scala)
out.println("setSyntheticReturnParameter(%s.%s)", className, paramId);
else if (kotlin)
out.println("syntheticReturnParameter = %s", paramId);
else
out.println("setSyntheticReturnParameter(%s);", paramId);
}
else {
if (scala)
out.println("setReturnParameter(%s.%s)", className, paramId);
else if (kotlin)
out.println("returnParameter = %s", paramId);
else
out.println("setReturnParameter(%s);", paramId);
}
}
else if (routine.getInParameters().contains(parameter)) {
if (routine.getOutParameters().contains(parameter)) {
if (scala)
out.println("addInOutParameter(%s.%s)", className, paramId);
else if (kotlin)
out.println("addInOutParameter(%s)", paramId);
else
out.println("addInOutParameter(%s);", paramId);
}
else {
if (scala)
out.println("addInParameter(%s.%s)", className, paramId);
else if (kotlin)
out.println("addInParameter(%s)", paramId);
else
out.println("addInParameter(%s);", paramId);
}
}
else {
if (scala)
out.println("addOutParameter(%s.%s)", className, paramId);
else if (kotlin)
out.println("addOutParameter(%s)", paramId);
else
out.println("addOutParameter(%s);", paramId);
}
}
if (routine.getOverload() != null)
out.println("setOverloaded(true)%s", semicolon);
out.println("}");
for (ParameterDefinition parameter : routine.getInParameters()) {
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
final String setter = getStrategy().getJavaSetterName(parameter, Mode.DEFAULT);
final String numberValue = parameter.getType(resolver(out)).isGenericNumberType() ? "Number" : "Value";
final String numberField = parameter.getType(resolver(out)).isGenericNumberType() ? "Number" : "Field";
final String paramId = getStrategy().getJavaIdentifier(parameter);
final String paramName = "value".equals(paramId) ? "value_" : "value";
out.javadoc("Set the <code>%s</code> parameter IN value to the routine", parameter.getOutputName());
if (scala) {
out.println("def %s(%s: %s) : Unit = set%s(%s.%s, %s)",
setter, paramName, refNumberType(out, parameter.getType(resolver(out))), numberValue, className, paramId, paramName);
}
else if (kotlin) {
out.println("fun %s(%s: %s?) = set%s(%s, %s)",
setter, paramName, refNumberType(out, parameter.getType(resolver(out))), numberValue, paramId, paramName);
}
else {
out.println("public void %s(%s %s) {", setter, varargsIfArray(refNumberType(out, parameter.getType(resolver(out)))), paramName);
out.println("set%s(%s, %s);", numberValue, paramId, paramName);
out.println("}");
}
if (routine.isSQLUsable()) {
out.javadoc("Set the <code>%s</code> parameter to the function to be used with a {@link org.jooq.Select} statement", parameter.getOutputName());
if (scala) {
out.println("def %s(field: %s[%s]): %s = {", setter, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))), setterReturnType);
out.println("set%s(%s.%s, field)", numberField, className, paramId);
if (generateFluentSetters())
out.println("this");
out.println("}");
}
else if (kotlin) {
out.println("fun %s(field: %s<%s?>): %s {", setter, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))), setterReturnType);
out.println("set%s(%s, field)", numberField, paramId);
if (generateFluentSetters())
out.println("return this");
out.println("}");
}
else {
out.println("public %s %s(%s<%s> field) {", setterReturnType, setter, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))));
out.println("set%s(%s, field);", numberField, paramId);
if (generateFluentSetters())
out.println("return this;");
out.println("}");
}
}
}
for (ParameterDefinition parameter : routine.getAllParameters()) {
boolean isReturnValue = parameter.equals(routine.getReturnValue());
boolean isOutParameter = routine.getOutParameters().contains(parameter);
if (isOutParameter && !isReturnValue) {
final String paramName = parameter.getOutputName();
final String paramTypeFull = getJavaType(parameter.getType(resolver(out)), out);
final String paramType = out.ref(paramTypeFull);
final String paramGetter = getStrategy().getJavaGetterName(parameter, Mode.DEFAULT);
final String paramId = getStrategy().getJavaIdentifier(parameter);
if (!printDeprecationIfUnknownType(out, paramTypeFull))
out.javadoc("Get the <code>%s</code> parameter OUT value from the routine", paramName);
if (scala) {
out.println("def %s: %s = get(%s.%s)", scalaWhitespaceSuffix(paramGetter), paramType, className, paramId);
}
else if (kotlin) {
out.println("fun %s(): %s? = get(%s)", paramGetter, paramType, paramId);
}
else {
out.println("public %s %s() {", paramType, paramGetter);
out.println("return get(%s);", paramId);
out.println("}");
}
}
}
generateRoutineClassFooter(routine, out);
out.println("}");
}
@SuppressWarnings("unused")
protected void (RoutineDefinition routine, JavaWriter out) {}
protected void generateRoutineClassJavadoc(RoutineDefinition routine, JavaWriter out) {
if (generateCommentsOnRoutines())
printClassJavadoc(out, routine);
else
printClassJavadoc(out, "The routine <code>" + routine.getQualifiedInputName() + "</code>.");
}
protected void printConvenienceMethodFunctionAsField(JavaWriter out, RoutineDefinition function, boolean parametersAsField) {
if (function.getInParameters().size() > 254) {
log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method.");
return;
}
if (parametersAsField && function.getInParameters().isEmpty())
return;
final String functionTypeFull = getJavaType(function.getReturnType(resolver(out)), out);
final String functionType = out.ref(functionTypeFull);
final String className = out.ref(getStrategy().getFullJavaClassName(function));
final String localVar = disambiguateJavaMemberName(function.getInParameters(), "f");
final String methodName = getStrategy().getJavaMethodName(function, Mode.DEFAULT);
if (!printDeprecationIfUnknownType(out, functionTypeFull) &&
!printDeprecationIfUnknownTypes(out, function.getInParameters()))
out.javadoc("Get <code>%s</code> as a field.", function.getQualifiedOutputName());
if (scala)
out.print("def %s(", methodName);
else if (kotlin)
out.print("fun %s(", methodName);
else
out.print("public static %s<%s> %s(",
function.isAggregate() ? AggregateFunction.class : Field.class,
functionType,
methodName);
if (!function.getInParameters().isEmpty())
out.println();
printParameterDeclarations(out, function.getInParameters(), parametersAsField, " ");
if (scala) {
out.println("): %s[%s] = {",
function.isAggregate() ? AggregateFunction.class : Field.class,
functionType);
out.println("val %s = new %s", localVar, className);
}
else if (kotlin) {
out.println("): %s<%s?> {",
function.isAggregate() ? AggregateFunction.class : Field.class,
functionType);
out.println("val %s = %s()", localVar, className);
}
else {
out.println(") {");
out.println("%s %s = new %s();", className, localVar, className);
}
for (ParameterDefinition parameter : function.getInParameters()) {
final String paramSetter = getStrategy().getJavaSetterName(parameter, Mode.DEFAULT);
final String paramMember = getStrategy().getJavaMemberName(parameter);
out.println("%s.%s(%s)%s", localVar, paramSetter, paramMember, semicolon);
}
out.println();
out.println("return %s.as%s%s%s", localVar, function.isAggregate() ? "AggregateFunction" : "Field", emptyparens, semicolon);
out.println("}");
}
protected void printConvenienceMethodTableValuedFunctionAsField(JavaWriter out, TableDefinition function, boolean parametersAsField, String methodName) {
if (function.getParameters().size() > 254) {
log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method.");
return;
}
if (function.getParameters().isEmpty())
if (parametersAsField)
return;
else if (scala)
return;
final String className = out.ref(getStrategy().getFullJavaClassName(function));
final String functionIdentifier = getStrategy().getFullJavaIdentifier(function);
if (!printDeprecationIfUnknownTypes(out, function.getParameters()))
out.javadoc("Get <code>%s</code> as a table.", function.getQualifiedOutputName());
if (scala)
out.print("def %s(", methodName);
else if (kotlin)
out.print("fun %s(", methodName);
else
out.print("public static %s %s(", className, methodName);
if (!function.getParameters().isEmpty())
out.println();
printParameterDeclarations(out, function.getParameters(), parametersAsField, " ");
if (scala || kotlin) {
out.println("): %s = %s.call(", className, functionIdentifier);
}
else {
out.println(") {");
out.println("return %s.call(", functionIdentifier);
}
String separator = " ";
for (ParameterDefinition parameter : function.getParameters()) {
out.println("%s%s", separator, getStrategy().getJavaMemberName(parameter));
separator = ", ";
}
if (scala || kotlin)
out.println(")");
else
out.println(");")
.println("}");
}
private void printParameterDeclarations(JavaWriter out, List<ParameterDefinition> parameters, boolean parametersAsField, String separator) {
for (ParameterDefinition parameter : parameters) {
final String memberName = getStrategy().getJavaMemberName(parameter);
if (scala) {
if (parametersAsField)
out.println("%s%s: %s[%s]", separator, memberName, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))));
else
out.println("%s%s: %s", separator, memberName, refNumberType(out, parameter.getType(resolver(out))));
}
else if (kotlin) {
if (parametersAsField)
out.println("%s%s: %s<%s?>", separator, memberName, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))));
else
out.println("%s%s: %s?", separator, memberName, refNumberType(out, parameter.getType(resolver(out))));
}
else {
if (parametersAsField)
out.println("%s%s<%s> %s", separator, Field.class, refExtendsNumberType(out, parameter.getType(resolver(out))), memberName);
else
out.println("%s%s %s", separator, refNumberType(out, parameter.getType(resolver(out))), memberName);
}
separator = ", ";
}
}
private String disambiguateJavaMemberName(Collection<? extends Definition> definitions, String defaultName) {
Set<String> names = new HashSet<>();
for (Definition definition : definitions)
names.add(getStrategy().getJavaMemberName(definition));
String name = defaultName;
while (names.contains(name))
name += "_";
return name;
}
protected void printConvenienceMethodFunction(JavaWriter out, RoutineDefinition function, boolean instance) {
if (function.getInParameters().size() > 254) {
log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method.");
return;
}
final String className = out.ref(getStrategy().getFullJavaClassName(function));
final String functionName = function.getQualifiedOutputName();
final String functionTypeFull = getJavaType(function.getReturnType(resolver(out)), out);
final String functionType = out.ref(functionTypeFull);
final String methodName = getStrategy().getJavaMethodName(function, Mode.DEFAULT);
final String configurationArgument = disambiguateJavaMemberName(function.getInParameters(), "configuration");
final String localVar = disambiguateJavaMemberName(function.getInParameters(), "f");
if (!printDeprecationIfUnknownType(out, functionTypeFull) &&
!printDeprecationIfUnknownTypes(out, function.getInParameters()))
out.javadoc("Call <code>%s</code>", functionName);
if (scala)
out.println("def %s(", methodName);
else if (kotlin)
out.println("fun %s(", methodName);
else
out.println("public %s%s %s(", !instance ? "static " : "", functionType, methodName);
String separator = " ";
if (!instance) {
if (scala || kotlin)
out.println("%s%s: %s", separator, configurationArgument, Configuration.class);
else
out.println("%s%s %s", separator, Configuration.class, configurationArgument);
separator = ", ";
}
for (ParameterDefinition parameter : function.getInParameters()) {
if (instance && parameter.equals(function.getInParameters().get(0)))
continue;
final String paramType = refNumberType(out, parameter.getType(resolver(out)));
final String paramMember = getStrategy().getJavaMemberName(parameter);
if (scala)
out.println("%s%s: %s", separator, paramMember, paramType);
else if (kotlin)
out.println("%s%s: %s?", separator, paramMember, paramType);
else
out.println("%s%s %s", separator, paramType, paramMember);
separator = ", ";
}
if (scala) {
out.println("): %s = {", functionType);
out.println("val %s = new %s()", localVar, className);
}
else if (kotlin) {
out.println("): %s? {", functionType);
out.println("val %s = %s()", localVar, className);
}
else {
out.println(") {");
out.println("%s %s = new %s();", className, localVar, className);
}
for (ParameterDefinition parameter : function.getInParameters()) {
final String paramSetter = getStrategy().getJavaSetterName(parameter, Mode.DEFAULT);
final String paramMember = (instance && parameter.equals(function.getInParameters().get(0)))
? "this"
: getStrategy().getJavaMemberName(parameter);
out.println("%s.%s(%s)%s", localVar, paramSetter, paramMember, semicolon);
}
out.println();
out.println("%s.execute(%s)%s", localVar, instance ? "configuration()" : configurationArgument, semicolon);
if (scala)
out.println("%s.getReturnValue", localVar);
else if (kotlin)
out.println("return %s.returnValue", localVar);
else
out.println("return %s.getReturnValue();", localVar);
out.println("}");
}
protected void printConvenienceMethodProcedure(JavaWriter out, RoutineDefinition procedure, boolean instance) {
if (procedure.getInParameters().size() > 254) {
log.warn("Too many parameters", "Procedure " + procedure + " has more than 254 in parameters. Skipping generation of convenience method.");
return;
}
final String className = out.ref(getStrategy().getFullJavaClassName(procedure));
final String configurationArgument = disambiguateJavaMemberName(procedure.getInParameters(), "configuration");
final String localVar = disambiguateJavaMemberName(procedure.getInParameters(), "p");
final List<ParameterDefinition> outParams = list(procedure.getReturnValue(), procedure.getOutParameters());
final String methodName = getStrategy().getJavaMethodName(procedure, Mode.DEFAULT);
final String firstOutParamType = outParams.size() == 1 ? out.ref(getJavaType(outParams.get(0).getType(resolver(out)), out)) : "";
if (!printDeprecationIfUnknownTypes(out, procedure.getAllParameters()))
out.javadoc("Call <code>%s</code>", procedure.getQualifiedOutputName());
if (scala)
out.println("def %s(", methodName);
else if (kotlin)
out.println("fun %s(", methodName);
else {
out.println("public %s%s %s(",
!instance ? "static " : "",
outParams.size() == 0 ? "void" : outParams.size() == 1 ? firstOutParamType : className,
methodName
);
}
String separator = " ";
if (!instance) {
if (scala || kotlin)
out.println("%s%s: %s", separator, configurationArgument, Configuration.class);
else
out.println("%s%s %s", separator, Configuration.class, configurationArgument);
separator = ", ";
}
for (ParameterDefinition parameter : procedure.getInParameters()) {
if (instance && parameter.equals(procedure.getInParameters().get(0)))
continue;
final String memberName = getStrategy().getJavaMemberName(parameter);
final String typeName = refNumberType(out, parameter.getType(resolver(out)));
if (scala)
out.println("%s%s: %s", separator, memberName, typeName);
else if (kotlin)
out.println("%s%s: %s?", separator, memberName, typeName);
else
out.println("%s%s %s", separator, typeName, memberName);
separator = ", ";
}
if (scala) {
out.println("): %s = {", outParams.size() == 0 ? "Unit" : outParams.size() == 1 ? firstOutParamType : className);
out.println("val %s = new %s", localVar, className);
}
else if (kotlin) {
out.println("): %s%s {", outParams.size() == 0 ? "Unit" : outParams.size() == 1 ? firstOutParamType : className, outParams.size() == 1 ? "?" : "");
out.println("val %s = %s()", localVar, className);
}
else {
out.println(") {");
out.println("%s %s = new %s();", className, localVar, className);
}
for (ParameterDefinition parameter : procedure.getInParameters()) {
final String setter = getStrategy().getJavaSetterName(parameter, Mode.DEFAULT);
final String arg = (instance && parameter.equals(procedure.getInParameters().get(0)))
? "this"
: getStrategy().getJavaMemberName(parameter);
out.println("%s.%s(%s)%s", localVar, setter, arg, semicolon);
}
out.println();
out.println("%s.execute(%s)%s", localVar, instance ? "configuration()" : configurationArgument, semicolon);
if (outParams.size() > 0) {
final ParameterDefinition parameter = outParams.get(0);
final String getter = parameter == procedure.getReturnValue()
? "getReturnValue"
: getStrategy().getJavaGetterName(parameter, Mode.DEFAULT);
final boolean isUDT = parameter.getType(resolver(out)).isUDT();
if (instance) {
if (generateInterfaces() && isUDT) {
final String columnTypeInterface = out.ref(getJavaType(parameter.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
if (scala)
out.println("from(%s.%s.asInstanceOf[%s])", localVar, getter, columnTypeInterface);
else if (kotlin)
out.println("from(%s.%s() as %s);", localVar, getter, columnTypeInterface);
else
out.println("from((%s) %s.%s());", columnTypeInterface, localVar, getter);
}
else {
out.println("from(%s.%s%s)%s", localVar, getter, emptyparens, semicolon);
}
}
if (outParams.size() == 1)
out.println("return %s.%s%s%s", localVar, getter, emptyparens, semicolon);
else if (outParams.size() > 1)
out.println("return %s%s", localVar, semicolon);
}
out.println("}");
}
protected void printConvenienceMethodTableValuedFunction(JavaWriter out, TableDefinition function, String methodName) {
if (function.getParameters().size() > 254) {
log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method.");
return;
}
final String recordClassName = out.ref(getStrategy().getFullJavaClassName(function, Mode.RECORD));
final String configurationArgument = disambiguateJavaMemberName(function.getParameters(), "configuration");
final String functionName = getStrategy().getFullJavaIdentifier(function);
if (!printDeprecationIfUnknownTypes(out, function.getParameters()))
out.javadoc("Call <code>%s</code>.", function.getQualifiedOutputName());
if (scala)
out.println("def %s(", methodName);
else if (kotlin)
out.println("fun %s(", methodName);
else
out.println("public static %s<%s> %s(", Result.class, recordClassName, methodName);
String separator = " ";
if (scala || kotlin)
out.println("%s%s: %s", separator, configurationArgument, Configuration.class);
else
out.println("%s%s %s", separator, Configuration.class, configurationArgument);
printParameterDeclarations(out, function.getParameters(), false, ", ");
if (scala) {
out.println("): %s[%s] = %s.dsl().selectFrom(%s.call(", Result.class, recordClassName, configurationArgument, functionName);
}
else if (kotlin) {
out.println("): %s<%s> = %s.dsl().selectFrom(%s.call(", Result.class, recordClassName, configurationArgument, functionName);
}
else {
out.println(") {");
out.println("return %s.dsl().selectFrom(%s.call(", configurationArgument, functionName);
}
separator = " ";
for (ParameterDefinition parameter : function.getParameters()) {
out.println("%s%s", separator, getStrategy().getJavaMemberName(parameter));
separator = ", ";
}
if (scala || kotlin)
out.println(")).fetch()");
else
out.println(")).fetch();")
.println("}");
}
protected void printRecordTypeMethod(JavaWriter out, Definition definition) {
final String className = out.ref(getStrategy().getFullJavaClassName(definition, Mode.RECORD));
out.javadoc("The class holding records for this type");
if (scala) {
out.println("override def getRecordType: %s[%s] = classOf[%s]", Class.class, className, className);
}
else if (kotlin) {
out.println("override fun getRecordType(): %s<%s> = %s::class.java", Class.class, className, className);
}
else {
out.override();
printNonnullAnnotation(out);
out.println("public %s<%s> getRecordType() {", Class.class, className);
out.println("return %s.class;", className);
out.println("}");
}
}
protected void printSingletonInstance(JavaWriter out, Definition definition) {
final String className = getStrategy().getJavaClassName(definition);
final String identifier = getStrategy().getJavaIdentifier(definition);
out.javadoc("The reference instance of <code>%s</code>", definition.getQualifiedOutputName());
if (scala)
out.println("val %s = new %s", identifier, className);
else if (kotlin)
out.println("val %s = %s()", identifier, className);
else
out.println("public static final %s %s = new %s();", className, identifier, className);
}
protected final String escapeEntities(String comment) {
if (comment == null)
return null;
return comment
.replace("&", "&")
.replace("<", "<")
.replace(">", ">");
}
protected void printClassJavadoc(JavaWriter out, Definition definition) {
printClassJavadoc(out, escapeEntities(definition.getComment()));
}
private String (Definition definition) {
return definition instanceof CatalogDefinition && generateCommentsOnCatalogs()
|| definition instanceof SchemaDefinition && generateCommentsOnSchemas()
|| definition instanceof TableDefinition && generateCommentsOnTables()
|| definition instanceof ColumnDefinition && generateCommentsOnColumns()
|| definition instanceof EmbeddableDefinition && generateCommentsOnEmbeddables()
|| definition instanceof UDTDefinition && generateCommentsOnUDTs()
|| definition instanceof AttributeDefinition && generateCommentsOnAttributes()
|| definition instanceof PackageDefinition && generateCommentsOnPackages()
|| definition instanceof RoutineDefinition && generateCommentsOnRoutines()
|| definition instanceof ParameterDefinition && generateCommentsOnParameters()
|| definition instanceof SequenceDefinition && generateCommentsOnSequences()
? StringUtils.defaultIfBlank(definition.getComment(), "")
: "";
}
private String (EmbeddableDefinition definition) {
return generateCommentsOnEmbeddables()
? StringUtils.defaultIfBlank(definition.getReferencingComment(), "")
: "";
}
protected void printClassJavadoc(JavaWriter out, String comment) {
if (generateJavadoc()) {
out.println("/**");
if (comment != null && comment.length() > 0)
printJavadocParagraph(out, comment, "");
else
out.println(" * This class is generated by jOOQ.");
out.println(" */");
}
}
@SuppressWarnings("unused")
@Deprecated
protected final void printClassAnnotations(JavaWriter out, SchemaDefinition schema) {}
@SuppressWarnings("unused")
@Deprecated
protected final void printClassAnnotations(JavaWriter out, SchemaDefinition schema, CatalogDefinition catalog) {}
protected void printClassAnnotations(JavaWriter out, Definition definition, Mode mode) {
if (generateGeneratedAnnotation()) {
SchemaDefinition schema = definition.getSchema();
CatalogDefinition catalog = definition.getCatalog();
GeneratedAnnotationType type = generateGeneratedAnnotationType();
if (type == null)
type = GeneratedAnnotationType.DETECT_FROM_JDK;
String generated;
switch (type) {
case DETECT_FROM_JDK:
try {
Reflect.on("java.util.Optional").call("of", new Object()).call("stream");
generated = "javax.annotation.processing.Generated";
}
catch (ReflectException e) {
generated = "javax.annotation.Generated";
}
break;
case JAVAX_ANNOTATION_GENERATED:
generated = "javax.annotation.Generated";
break;
case JAVAX_ANNOTATION_PROCESSING_GENERATED:
generated = "javax.annotation.processing.Generated";
break;
default:
throw new IllegalStateException("Unsupported type: " + type);
}
out.println("@%s(", out.ref(generated));
if (useSchemaVersionProvider() || useCatalogVersionProvider()) {
boolean hasCatalogVersion = !StringUtils.isBlank(catalogVersions.get(catalog));
boolean hasSchemaVersion = !StringUtils.isBlank(schemaVersions.get(schema));
if (scala)
out.println("value = %s(", out.ref("scala.Array"));
else if (kotlin)
out.println("value = [");
else
out.println("value = {");
out.println("\"https://www.jooq.org\",");
out.println("\"jOOQ version:%s\"%s", Constants.VERSION, (hasCatalogVersion || hasSchemaVersion ? "," : ""));
if (hasCatalogVersion)
out.println("\"catalog version:%s\"%s", escapeString(catalogVersions.get(catalog)), (hasSchemaVersion ? "," : ""));
if (hasSchemaVersion)
out.println("\"schema version:%s\"", escapeString(schemaVersions.get(schema)));
if (scala)
out.println("),");
else if (kotlin)
out.println("],");
else
out.println("},");
if (generateGeneratedAnnotationDate())
out.println("date = \"" + isoDate + "\",");
out.println("comments = \"This class is generated by jOOQ\"");
}
else {
if (scala)
out.println("value = %s(", out.ref("scala.Array"));
else if (kotlin)
out.println("value = [");
else
out.println("value = {");
out.println("\"https://www.jooq.org\",");
out.println("\"jOOQ version:%s\"", Constants.VERSION);
if (scala)
out.println("),");
else if (kotlin)
out.println("],");
else
out.println("},");
out.println("comments = \"This class is generated by jOOQ\"");
}
out.println(")");
}
if (scala) {}
else if (kotlin)
out.println("@Suppress(\"UNCHECKED_CAST\")");
else
out.println("@%s({ \"all\", \"unchecked\", \"rawtypes\" })", out.ref("java.lang.SuppressWarnings"));
}
private String readVersion(File file, String type) {
String result = null;
try {
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
String string = new String(bytes);
Matcher matcher = Pattern.compile("@(?:javax\\.annotation\\.)?Generated\\(\\s*?value\\s*?=\\s*?" + (scala ? "Array\\([^)]*?" : "\\{[^}]*?") + "\"" + type + " version:([^\"]*?)\"").matcher(string);
if (matcher.find()) {
result = matcher.group(1);
}
}
finally {
f.close();
}
}
catch (IOException ignore) {}
return result;
}
protected void printJavadocParagraph(JavaWriter out, String comment, String indent) {
String escaped = JavaWriter.escapeJavadoc(comment);
printParagraph(out, escaped, indent + " * ");
}
protected void printParagraph(GeneratorWriter<?> out, String comment, String indent) {
boolean newLine = true;
int lineLength = 0;
for (int i = 0; i < comment.length(); i++) {
if (newLine) {
out.print(indent);
newLine = false;
}
out.print(comment.charAt(i));
lineLength++;
if (comment.charAt(i) == '\n') {
lineLength = 0;
newLine = true;
}
else if (lineLength > 70 && Character.isWhitespace(comment.charAt(i))) {
out.println();
lineLength = 0;
newLine = true;
}
}
if (!newLine) {
out.println();
}
}
protected void printPackage(JavaWriter out, Definition definition) {
printPackage(out, definition, Mode.DEFAULT);
}
protected void printPackage(JavaWriter out, Definition definition, Mode mode) {
printPackageComment(out, definition, mode);
out.printPackageSpecification(getStrategy().getJavaPackageName(definition, mode));
out.println();
out.printImports();
out.println();
}
protected void printGlobalReferencesPackage(JavaWriter out, Definition container, Class<? extends Definition> objectType) {
printGlobalReferencesPackageComment(out, container, objectType);
out.printPackageSpecification(getStrategy().getGlobalReferencesJavaPackageName(container, objectType));
out.println();
out.printImports();
out.println();
}
protected void (JavaWriter out, Definition definition, Mode mode) {
String header = getStrategy().getFileHeader(definition, mode);
if (!StringUtils.isBlank(header)) {
out.println("/*");
printJavadocParagraph(out, header, "");
out.println(" */");
}
}
protected void (JavaWriter out, Definition container, Class<? extends Definition> objectType) {
String header = getStrategy().getGlobalReferencesFileHeader(container, objectType);
if (!StringUtils.isBlank(header)) {
out.println("/*");
printJavadocParagraph(out, header, "");
out.println(" */");
}
}
protected String refExtendsNumberType(JavaWriter out, DataTypeDefinition type) {
if (type.isGenericNumberType())
return (scala ? "_ <: " : kotlin ? "out ": "? extends ") + out.ref(Number.class);
else
return out.ref(getJavaType(type, out));
}
protected String refNumberType(JavaWriter out, DataTypeDefinition type) {
if (type.isGenericNumberType())
return out.ref(Number.class);
else
return out.ref(getJavaType(type, out));
}
protected String getJavaTypeReference(Database db, DataTypeDefinition type, JavaWriter out) {
if (database.isArrayType(type.getType())) {
Name baseType = GenerationUtil.getArrayBaseType(db.getDialect(), type.getType(), type.getQualifiedUserType());
return getTypeReference(
db,
type.getSchema(),
out,
baseType.last(),
type.getPrecision(),
type.getScale(),
type.getLength(),
true,
false,
null,
baseType
) + ".getArrayDataType()";
}
else {
return getTypeReference(
db,
type.getSchema(),
out,
type.getType(),
type.getPrecision(),
type.getScale(),
type.getLength(),
type.isNullable(),
type.isIdentity(),
type.getDefaultValue(),
type.getQualifiedUserType()
);
}
}
private class Resolver implements JavaTypeResolver {
private final JavaWriter out;
private final Mode mode;
Resolver(JavaWriter out, Mode mode) {
this.out = out;
this.mode = mode;
}
@Override
public String resolve(DataTypeDefinition type) {
return mode == null ? getJavaType(type, out) : getJavaType(type, out, mode);
}
@Override
public String classLiteral(String type) {
String rawtype = type.replaceAll("<.*>", "").replaceAll("\\[.*\\]", "");
boolean generic = !rawtype.equals(type);
switch (language) {
case SCALA:
return "classOf[" + out.ref(type) + "]";
case KOTLIN:
return out.ref(rawtype) + "::class.java" + (generic ? (" as " + out.ref(Class.class) + "<" + out.ref(type) + ">") : "");
case JAVA:
default:
return (generic ? "(" + out.ref(Class.class) + "<" + out.ref(type) + ">) (" + out.ref(Class.class) + ") " : "") + out.ref(rawtype) + ".class";
}
}
@Override
public String constructorCall(String type) {
String rawtype = type.replaceAll("<.*>", "").replaceAll("\\[.*\\]", "");
String typeParams = type.replace(rawtype, "");
switch (language) {
case SCALA:
return "new " + out.ref(rawtype) + typeParams.replace("<", "[").replace(">", "]");
case KOTLIN:
return out.ref(rawtype) + typeParams;
case JAVA:
default:
return "new " + out.ref(rawtype) + typeParams;
}
}
@Override
public String ref(String type) {
return out.ref(type);
}
@Override
public String ref(Class<?> type) {
return out.ref(type);
}
}
private static final String classLiteral(String type) {
String rawtype = type.replaceAll("<.*>", "").replaceAll("\\[.*\\]", "");
return (rawtype.equals(type) ? "" : "(java.lang.Class) ") + rawtype + ".class";
}
protected JavaTypeResolver resolver(JavaWriter out) {
return new Resolver(out, null);
}
protected JavaTypeResolver resolver(JavaWriter out, Mode mode) {
return new Resolver(out, mode);
}
protected boolean isArrayType(String javaType) {
if (scala)
return javaType.startsWith("scala.Array");
else if (kotlin)
return javaType.startsWith("kotlin.Array") || javaType.equals("kotlin.ByteArray");
else
return javaType.endsWith("[]");
}
protected String getJavaType(DataTypeDefinition type, JavaWriter out) {
return getJavaType(type, out, Mode.RECORD);
}
protected String getJavaType(DataTypeDefinition type, JavaWriter out, Mode udtMode) {
return getType(
type.getDatabase(),
type.getSchema(),
out,
type.getType(),
type.getPrecision(),
type.getScale(),
type.getQualifiedUserType(),
type.getJavaType(),
Object.class.getName(),
udtMode);
}
@Deprecated
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, String u, String javaType, String defaultType) {
return getType(db, schema, out, t, p, s, name(u), javaType, defaultType);
}
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, Name u, String javaType, String defaultType) {
return getType(db, schema, out, t, p, s, u, javaType, defaultType, Mode.RECORD);
}
@Deprecated
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, String u, String javaType, String defaultType, Mode udtMode) {
return getType(db, schema, out, t, p, s, name(u), javaType, defaultType, udtMode);
}
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, Name u, String javaType, String defaultType, Mode udtMode) {
String type = defaultType;
if (javaType != null) {
type = javaType;
}
else if (db.isArrayType(t)) {
Name baseTypeName = GenerationUtil.getArrayBaseType(db.getDialect(), t, u);
String last = t.equals(baseTypeName.last()) ? "OTHER" : baseTypeName.last();
String baseType = getType(db, schema, out, last, p, s, baseTypeName, javaType, defaultType, udtMode);
if (scala)
type = "scala.Array[" + baseType + "]";
else if (kotlin)
type = "kotlin.Array<" + baseType + "?>";
else
type = baseType + "[]";
}
else if (db.getArray(schema, u) != null) {
boolean udtArray = db.getArray(schema, u).getElementType(resolver(out)).isUDT();
if (udtMode == Mode.POJO || (udtMode == Mode.INTERFACE && !udtArray)) {
if (scala)
type = "java.util.List[" + getJavaType(db.getArray(schema, u).getElementType(resolver(out, udtMode)), out, udtMode) + "]";
else
type = "java.util.List<" + getJavaType(db.getArray(schema, u).getElementType(resolver(out, udtMode)), out, udtMode) + ">";
}
else if (udtMode == Mode.INTERFACE) {
if (scala)
type = "java.util.List[_ <:" + getJavaType(db.getArray(schema, u).getElementType(resolver(out, udtMode)), out, udtMode) + "]";
else
type = "java.util.List<? extends " + getJavaType(db.getArray(schema, u).getElementType(resolver(out, udtMode)), out, udtMode) + ">";
}
else {
type = getStrategy().getFullJavaClassName(db.getArray(schema, u), Mode.RECORD);
}
}
else if (db.getDomain(schema, u) != null) {
type = getJavaType(db.getDomain(schema, u).getDefinedType(), out);
}
else if (db.getEnum(schema, u) != null) {
type = getStrategy().getFullJavaClassName(db.getEnum(schema, u), Mode.ENUM);
}
else if (db.getUDT(schema, u) != null) {
type = getStrategy().getFullJavaClassName(db.getUDT(schema, u), udtMode);
}
else if (db.getDialect().family() == POSTGRES && db.getTable(schema, u) != null) {
type = getStrategy().getFullJavaClassName(db.getTable(schema, u), udtMode);
}
else if (u != null && db.getConfiguredCustomType(u.last()) != null) {
type = u.last();
}
else {
try {
Class<?> clazz = mapJavaTimeTypes(getDataType(db, t, p, s)).getType();
if (scala && clazz == byte[].class)
type = "scala.Array[scala.Byte]";
else if (kotlin && clazz == byte[].class)
type = "kotlin.ByteArray";
else
type = clazz.getCanonicalName();
if (clazz.getTypeParameters().length > 0) {
type += (scala ? "[" : "<");
String separator = "";
for (TypeVariable<?> var : clazz.getTypeParameters()) {
type += separator;
type += ((Class<?>) var.getBounds()[0]).getCanonicalName();
separator = ", ";
}
type += (scala ? "]" : ">");
}
}
catch (SQLDialectNotSupportedException e) {
if (defaultType == null) {
throw e;
}
}
}
if (kotlin && Object.class.getName().equals(type))
type = "Any";
return type;
}
protected String getTypeReference(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, int l, boolean n, boolean i, String d, Name u) {
StringBuilder sb = new StringBuilder();
if (db.getArray(schema, u) != null) {
ArrayDefinition array = database.getArray(schema, u);
sb.append(getJavaTypeReference(db, array.getElementType(resolver(out)), out));
sb.append(".asArrayDataType(");
sb.append(classOf(getStrategy().getFullJavaClassName(array, Mode.RECORD)));
sb.append(")");
}
else if (db.getDomain(schema, u) != null) {
sb.append(getStrategy().getFullJavaIdentifier(db.getDomain(schema, u)));
sb.append(".getDataType()");
}
else if (db.getUDT(schema, u) != null) {
sb.append(getStrategy().getFullJavaIdentifier(db.getUDT(schema, u)));
sb.append(".getDataType()");
}
else if (db.getDialect().family() == POSTGRES && db.getTable(schema, u) != null) {
sb.append(getStrategy().getFullJavaIdentifier(db.getTable(schema, u)));
sb.append(".getDataType()");
}
else if (db.getEnum(schema, u) != null) {
sb.append(getJavaTypeReference(db, new DefaultDataTypeDefinition(
db, schema, DefaultDataType.getDataType(db.getDialect(), String.class).getTypeName(), l, p, s, n, d, (Name) null
), out));
sb.append(".asEnumDataType(");
sb.append(classOf(getStrategy().getFullJavaClassName(db.getEnum(schema, u), Mode.ENUM)));
sb.append(")");
}
else {
DataType<?> dataType;
String sqlDataTypeRef;
try {
dataType = mapJavaTimeTypes(getDataType(db, t, p, s));
}
catch (SQLDialectNotSupportedException ignore) {
dataType = SQLDataType.OTHER.nullable(n).identity(i);
sb = new StringBuilder();
sb.append(DefaultDataType.class.getName());
sb.append(".getDefaultDataType(\"");
sb.append(escapeString(u != null ? u.toString() : t));
sb.append("\")");
}
dataType = dataType
.nullable(n)
.identity(i);
if (d != null)
dataType = dataType.defaultValue((Field) DSL.field(d, dataType));
if (dataType.getSQLDataType() != null && sb.length() == 0) {
DataType<?> sqlDataType = dataType.getSQLDataType();
String literal = SQLDATATYPE_LITERAL_LOOKUP.get(sqlDataType);
sqlDataTypeRef =
out.ref(SQLDataType.class)
+ '.'
+ literal;
sb.append(sqlDataTypeRef);
if (dataType.hasPrecision() && (dataType.isTimestamp() || p > 0)) {
if (SQLDATATYPE_WITH_PRECISION.contains(literal))
sb.append('(').append(p);
else
sb.append(".precision(").append(p);
if (dataType.hasScale() && s > 0)
sb.append(", ").append(s);
sb.append(')');
}
if (dataType.hasLength() && l > 0)
if (SQLDATATYPE_WITH_LENGTH.contains(literal))
sb.append("(").append(l).append(")");
else
sb.append(".length(").append(l).append(")");
}
else {
sqlDataTypeRef = SQLDataType.class.getCanonicalName() + ".OTHER";
if (sb.length() == 0)
sb.append(sqlDataTypeRef);
}
if (!dataType.nullable())
sb.append(".nullable(false)");
if (dataType.identity())
sb.append(".identity(true)");
if (dataType.defaulted()) {
sb.append(".defaultValue(");
if (asList(MYSQL).contains(db.getDialect().family()))
if (d != null && d.toLowerCase(getStrategy().getTargetLocale()).startsWith("current_timestamp"))
sb.append(out.ref(DSL.class))
.append(".field(\"")
.append(escapeString(d))
.append("\"");
else
sb.append(out.ref(DSL.class))
.append(".inline(\"")
.append(escapeString(d))
.append("\"");
else
sb.append(out.ref(DSL.class))
.append(".field(\"")
.append(escapeString(d))
.append("\"");
sb.append(", ")
.append(sqlDataTypeRef)
.append(")")
.append(kotlin && dataType.getType() == Object.class ? " as Any?" : "")
.append(")");
}
}
return sb.toString();
}
private DataType<?> mapJavaTimeTypes(DataType<?> dataType) {
DataType<?> result = dataType;
if (dataType.isDateTime() && generateJavaTimeTypes) {
if (dataType.getType() == Date.class)
result = SQLDataType.LOCALDATE;
else if (dataType.getType() == Time.class)
result = SQLDataType.LOCALTIME;
else if (dataType.getType() == Timestamp.class)
result = SQLDataType.LOCALDATETIME;
}
return result;
}
@SafeVarargs
private static final <T> List<T> list(T... objects) {
List<T> result = new ArrayList<>();
if (objects != null)
for (T object : objects)
if (object != null && !"".equals(object))
result.add(object);
return result;
}
private static final <T> List<T> list(T first, List<T> remaining) {
List<T> result = new ArrayList<>();
result.addAll(list(first));
result.addAll(remaining);
return result;
}
private static final <T> List<T> first(Collection<T> objects) {
List<T> result = new ArrayList<>();
if (objects != null) {
for (T object : objects) {
result.add(object);
break;
}
}
return result;
}
private static final <T> List<T> remaining(Collection<T> objects) {
List<T> result = new ArrayList<>();
if (objects != null) {
result.addAll(objects);
if (result.size() > 0)
result.remove(0);
}
return result;
}
private String classOf(String string) {
if (scala)
return "classOf[" + string + "]";
else if (kotlin)
return string + "::class.java";
else
return string + ".class";
}
private static final Pattern SQUARE_BRACKETS = Pattern.compile("\\[\\]$");
private String varargsIfArray(String type) {
if (!generateVarargsSetters())
return type;
else if (scala)
return type;
else
return SQUARE_BRACKETS.matcher(type).replaceFirst("...");
}
protected JavaWriter newJavaWriter(File file) {
file = fixSuffix(file);
JavaWriter result = new JavaWriter(file, generateFullyQualifiedTypes(), targetEncoding, generateJavadoc(), fileCache, generatedSerialVersionUID());
if (generateIndentation != null)
result.tabString(generateIndentation);
if (generateNewline != null)
result.newlineString(generateNewline);
return result;
}
protected File getFile(Definition definition) {
return fixSuffix(getStrategy().getFile(definition));
}
protected File getFile(Definition definition, Mode mode) {
return fixSuffix(getStrategy().getFile(definition, mode));
}
private File fixSuffix(File file) {
if (scala)
file = new File(file.getParentFile(), file.getName().replace(".java", ".scala"));
else if (kotlin)
file = new File(file.getParentFile(), file.getName().replace(".java", ".kt"));
return file;
}
private static final Pattern P_SCALA_WHITESPACE_SUFFIX = Pattern.compile("^.*[^a-zA-Z0-9]$");
private String scalaWhitespaceSuffix(String string) {
return string == null
? null
: P_SCALA_WHITESPACE_SUFFIX.matcher(string).matches()
? (string + " ")
: string;
}
protected void closeJavaWriter(JavaWriter out) {
CloseResult result = out.close();
if (result.affected)
affectedFiles.add(out.file());
if (result.modified)
modifiedFiles.add(out.file());
}
}