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

org.jooq.util.JavaGenerator Maven / Gradle / Ivy

There is a newer version: 3.19.18
Show newest version
/**
 * Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Other licenses:
 * -----------------------------------------------------------------------------
 * Commercial licenses for this work are available. These replace the above
 * ASL 2.0 and offer limited warranties, support, maintenance, and commercial
 * database integrations.
 *
 * For more information, please visit: http://www.jooq.org/licenses
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package org.jooq.util;


import static java.util.Arrays.asList;
import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.tools.StringUtils.defaultIfBlank;
import static org.jooq.tools.StringUtils.defaultString;
import static org.jooq.util.AbstractGenerator.Language.JAVA;
import static org.jooq.util.AbstractGenerator.Language.SCALA;
import static org.jooq.util.GenerationUtil.convertToIdentifier;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.TypeVariable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
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.Configuration;
import org.jooq.Constants;
import org.jooq.DataType;
import org.jooq.EnumType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
// ...
import org.jooq.Package;
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.Table;
import org.jooq.TableField;
import org.jooq.UDT;
import org.jooq.UDTField;
import org.jooq.UniqueKey;
import org.jooq.exception.SQLDialectNotSupportedException;
import org.jooq.impl.AbstractKeys;
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.PackageImpl;
import org.jooq.impl.SQLDataType;
import org.jooq.impl.SchemaImpl;
import org.jooq.impl.SequenceImpl;
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.tools.JooqLogger;
import org.jooq.tools.StopWatch;
import org.jooq.tools.StringUtils;
import org.jooq.tools.reflect.Reflect;
import org.jooq.tools.reflect.ReflectException;
import org.jooq.util.GeneratorStrategy.Mode;
// ...
// ...
// ...
// ...
// ...
// ...
import org.jooq.util.postgres.PostgresDatabase;


/**
 * A default implementation for code generation.
 * 

* Replace this code with your own logic, if you need your database schema * represented in a different way. *

* Note that you can also extend this class to generate POJO's or other stuff * entirely independent of jOOQ. * * @author Lukas Eder */ public class JavaGenerator extends AbstractGenerator { private static final JooqLogger log = JooqLogger.getLogger(JavaGenerator.class); /** * The Javadoc to be used for private constructors */ private static final String NO_FURTHER_INSTANCES_ALLOWED = "No further instances allowed"; /** * [#1459] Prevent large static initialisers by splitting nested classes */ private static final int INITIALISER_SIZE = 500; /** * An overall stop watch to measure the speed of source code generation */ private final StopWatch watch = new StopWatch(); /** * The underlying database of this generator */ private Database database; /** * The code generation date, if needed. */ private String isoDate; /** * The cached schema version numbers. */ private Map schemaVersions; /** * The cached catalog version numbers. */ private Map catalogVersions; /** * All files modified by this generator */ private Set files = new LinkedHashSet(); private final boolean scala; private final String tokenVoid; public JavaGenerator() { this(JAVA); } JavaGenerator(Language language) { super(language); this.scala = (language == SCALA); this.tokenVoid = (scala ? "Unit" : "void"); } @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()); String url = ""; try { Connection connection = database.getConnection(); if (connection != null) url = connection.getMetaData().getURL(); } catch (SQLException ignore) {} log.info("License parameters"); log.info("----------------------------------------------------------"); log.info(" Thank you for using jOOQ and jOOQ's code generator"); log.info(""); log.info("Database parameters"); log.info("----------------------------------------------------------"); log.info(" dialect", database.getDialect()); log.info(" URL", url); log.info(" target dir", getTargetDirectory()); log.info(" target package", getTargetPackage()); log.info(" includes", Arrays.asList(database.getIncludes())); log.info(" excludes", Arrays.asList(database.getExcludes())); log.info(" includeExcludeColumns", database.getIncludeExcludeColumns()); log.info("----------------------------------------------------------"); log.info(""); log.info("DefaultGenerator parameters"); log.info("----------------------------------------------------------"); log.info(" strategy", strategy.delegate.getClass()); log.info(" deprecated", generateDeprecated()); log.info(" generated annotation", generateGeneratedAnnotation() + ((!generateGeneratedAnnotation && (useSchemaVersionProvider || useCatalogVersionProvider)) ? " (forced to true because of or )" : "")); log.info(" JPA annotations", generateJPAAnnotations()); log.info(" validation annotations", generateValidationAnnotations()); log.info(" instance fields", generateInstanceFields()); log.info(" records", generateRecords() + ((!generateRecords && generateDaos) ? " (forced to true because of )" : "")); log.info(" pojos", generatePojos() + ((!generatePojos && generateDaos) ? " (forced to true because of )" : ((!generatePojos && generateImmutablePojos) ? " (forced to true because of )" : ""))); log.info(" immutable pojos", generateImmutablePojos()); log.info(" interfaces", generateInterfaces()); log.info(" daos", generateDaos()); log.info(" relations", generateRelations() + ((!generateRelations && generateDaos) ? " (forced to true because of )" : "")); log.info(" table-valued functions", generateTableValuedFunctions()); log.info(" global references", generateGlobalObjectReferences()); log.info("----------------------------------------------------------"); if (!generateInstanceFields()) { log.warn(""); log.warn("Deprecation warnings"); log.warn("----------------------------------------------------------"); log.warn(" = false is deprecated! Please adapt your configuration."); } log.info(""); log.info("Generation remarks"); log.info("----------------------------------------------------------"); if (generateImmutablePojos && generateInterfaces) log.info(" immutable pojos", "Immutable POJOs do not have any setters. Hence, setters are also missing from interfaces"); else log.info(" none"); log.info(""); log.info("----------------------------------------------------------"); // ---------------------------------------------------------------------- // XXX Generating catalogs // ---------------------------------------------------------------------- log.info("Generating catalogs", "Total: " + database.getCatalogs().size()); for (CatalogDefinition catalog : database.getCatalogs()) { try { generate(catalog); } catch (Exception e) { throw new GeneratorException("Error generating code for catalog " + catalog, e); } } } private final 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(getStrategy().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."); return; } } generateCatalog(catalog); log.info("Generating schemata", "Total: " + catalog.getSchemata().size()); for (SchemaDefinition schema : catalog.getSchemata()) { try { generate(schema); } catch (Exception e) { throw new GeneratorException("Error generating code for schema " + schema, e); } } } private final 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(getStrategy().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."); return; } } // ---------------------------------------------------------------------- // XXX Initialising // ---------------------------------------------------------------------- generateSchema(schema); if (generateGlobalObjectReferences() && generateGlobalSequenceReferences() && database.getSequences(schema).size() > 0) { generateSequences(schema); } if (database.getTables(schema).size() > 0) { generateTables(schema); } if (generatePojos() && database.getTables(schema).size() > 0) { generatePojos(schema); } if (generateDaos() && database.getTables(schema).size() > 0) { generateDaos(schema); } if (generateGlobalObjectReferences() && generateGlobalTableReferences() && database.getTables(schema).size() > 0) { generateTableReferences(schema); } if (generateRelations() && database.getTables(schema).size() > 0) { generateRelations(schema); } if (generateRecords() && database.getTables(schema).size() > 0) { generateRecords(schema); } if (generateInterfaces() && database.getTables(schema).size() > 0) { generateInterfaces(schema); } if (database.getUDTs(schema).size() > 0) { generateUDTs(schema); } if (generatePojos() && database.getUDTs(schema).size() > 0) { generateUDTPojos(schema); } if (database.getUDTs(schema).size() > 0) { generateUDTRecords(schema); } if (generateInterfaces() && database.getUDTs(schema).size() > 0) { generateUDTInterfaces(schema); } if (database.getUDTs(schema).size() > 0) { generateUDTRoutines(schema); } if (generateGlobalObjectReferences() && generateGlobalUDTReferences() && database.getUDTs(schema).size() > 0) { generateUDTReferences(schema); } if (database.getArrays(schema).size() > 0) { generateArrays(schema); } if (database.getEnums(schema).size() > 0) { generateEnums(schema); } if (database.getDomains(schema).size() > 0) { generateDomains(schema); } if (generateGlobalObjectReferences() && generateGlobalRoutineReferences() && database.getRoutines(schema).size() > 0 || hasTableValuedFunctions(schema)) { generateRoutines(schema); } log.info("Removing excess files"); empty(getStrategy().getFile(schema).getParentFile(), (scala ? ".scala" : ".java"), files); files.clear(); // XXX [#651] Refactoring-cursor watch.splitInfo("Generation finished: " + schema.getQualifiedName()); log.info(""); } private class AvoidAmbiguousClassesFilter implements Database.Filter { private Map included = new HashMap(); @Override public boolean exclude(Definition definition) { // These definitions don't generate types of their own. if ( definition instanceof ColumnDefinition || definition instanceof AttributeDefinition || definition instanceof ParameterDefinition) return false; // Check if we've previously encountered a Java type of the same case-insensitive, fully-qualified name. String name = getStrategy().getFullJavaClassName(definition); String nameLC = name.toLowerCase(); 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"); JavaWriter out = newJavaWriter(new File(getStrategy().getFile(schema).getParentFile(), "Keys.java")); printPackage(out, schema); printClassJavadoc(out, "A class modelling foreign key relationships between tables of the " + schema.getOutputName() + " schema"); printClassAnnotations(out, schema); if (scala) out.println("object Keys {"); else out.println("public class Keys {"); out.tab(1).header("IDENTITY definitions"); out.println(); List allIdentities = new ArrayList(); List allUniqueKeys = new ArrayList(); List allForeignKeys = new ArrayList(); for (TableDefinition table : database.getTables(schema)) { try { IdentityDefinition identity = table.getIdentity(); if (identity != null) { final String identityType = out.ref(getStrategy().getFullJavaClassName(identity.getColumn().getContainer(), Mode.RECORD)); final String columnType = out.ref(getJavaType(identity.getColumn().getType())); final String identityId = getStrategy().getJavaIdentifier(identity.getColumn().getContainer()); final int block = allIdentities.size() / INITIALISER_SIZE; if (scala) out.tab(1).println("val IDENTITY_%s = Identities%s.IDENTITY_%s", identityId, block, identityId); else out.tab(1).println("public static final %s<%s, %s> IDENTITY_%s = Identities%s.IDENTITY_%s;", Identity.class, identityType, columnType, identityId, block, identityId); allIdentities.add(identity); } } catch (Exception e) { log.error("Error while generating table " + table, e); } } // Unique keys out.tab(1).header("UNIQUE and PRIMARY KEY definitions"); out.println(); for (TableDefinition table : database.getTables(schema)) { try { List uniqueKeys = table.getUniqueKeys(); for (UniqueKeyDefinition uniqueKey : uniqueKeys) { final String keyType = out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)); final String keyId = getStrategy().getJavaIdentifier(uniqueKey); final int block = allUniqueKeys.size() / INITIALISER_SIZE; if (scala) out.tab(1).println("val %s = UniqueKeys%s.%s", keyId, block, keyId); else out.tab(1).println("public static final %s<%s> %s = UniqueKeys%s.%s;", UniqueKey.class, keyType, keyId, block, keyId); allUniqueKeys.add(uniqueKey); } } catch (Exception e) { log.error("Error while generating table " + table, e); } } // Foreign keys out.tab(1).header("FOREIGN KEY definitions"); out.println(); for (TableDefinition table : database.getTables(schema)) { try { List foreignKeys = table.getForeignKeys(); for (ForeignKeyDefinition foreignKey : foreignKeys) { 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() / INITIALISER_SIZE; if (scala) out.tab(1).println("val %s = ForeignKeys%s.%s", keyId, block, keyId); else out.tab(1).println("public static final %s<%s, %s> %s = ForeignKeys%s.%s;", ForeignKey.class, keyType, referencedType, keyId, block, keyId); allForeignKeys.add(foreignKey); } } catch (Exception e) { log.error("Error while generating reference " + table, e); } } // [#1459] Print nested classes for actual static field initialisations // keeping top-level initialiser small int identityCounter = 0; int uniqueKeyCounter = 0; int foreignKeyCounter = 0; out.tab(1).header("[#1459] distribute members to avoid static initialisers > 64kb"); // Identities // ---------- for (IdentityDefinition identity : allIdentities) { printIdentity(out, identityCounter, identity); identityCounter++; } if (identityCounter > 0) { out.tab(1).println("}"); } // UniqueKeys // ---------- for (UniqueKeyDefinition uniqueKey : allUniqueKeys) { printUniqueKey(out, uniqueKeyCounter, uniqueKey); uniqueKeyCounter++; } if (uniqueKeyCounter > 0) { out.tab(1).println("}"); } // ForeignKeys // ----------- for (ForeignKeyDefinition foreignKey : allForeignKeys) { printForeignKey(out, foreignKeyCounter, foreignKey); foreignKeyCounter++; } if (foreignKeyCounter > 0) { out.tab(1).println("}"); } out.println("}"); closeJavaWriter(out); watch.splitInfo("Keys generated"); } protected void printIdentity(JavaWriter out, int identityCounter, IdentityDefinition identity) { final int block = identityCounter / INITIALISER_SIZE; // Print new nested class if (identityCounter % INITIALISER_SIZE == 0) { if (identityCounter > 0) { out.tab(1).println("}"); } out.println(); if (scala) out.tab(1).println("private object Identities%s extends %s {", block, AbstractKeys.class); else out.tab(1).println("private static class Identities%s extends %s {", block, AbstractKeys.class); } if (scala) out.tab(2).println("val %s : %s[%s, %s] = %s.createIdentity(%s, %s)", getStrategy().getJavaIdentifier(identity), Identity.class, out.ref(getStrategy().getFullJavaClassName(identity.getTable(), Mode.RECORD)), out.ref(getJavaType(identity.getColumn().getType())), AbstractKeys.class, out.ref(getStrategy().getFullJavaIdentifier(identity.getColumn().getContainer()), 2), out.ref(getStrategy().getFullJavaIdentifier(identity.getColumn()), colRefSegments(identity.getColumn()))); else out.tab(2).println("public static %s<%s, %s> %s = createIdentity(%s, %s);", Identity.class, out.ref(getStrategy().getFullJavaClassName(identity.getTable(), Mode.RECORD)), out.ref(getJavaType(identity.getColumn().getType())), getStrategy().getJavaIdentifier(identity), out.ref(getStrategy().getFullJavaIdentifier(identity.getColumn().getContainer()), 2), out.ref(getStrategy().getFullJavaIdentifier(identity.getColumn()), colRefSegments(identity.getColumn()))); } protected void printUniqueKey(JavaWriter out, int uniqueKeyCounter, UniqueKeyDefinition uniqueKey) { final int block = uniqueKeyCounter / INITIALISER_SIZE; // Print new nested class if (uniqueKeyCounter % INITIALISER_SIZE == 0) { if (uniqueKeyCounter > 0) { out.tab(1).println("}"); } out.println(); if (scala) out.tab(1).println("private object UniqueKeys%s extends %s {", block, AbstractKeys.class); else out.tab(1).println("private static class UniqueKeys%s extends %s {", block, AbstractKeys.class); } if (scala) out.tab(2).println("val %s : %s[%s] = %s.createUniqueKey(%s, \"%s\", [[%s]])", getStrategy().getJavaIdentifier(uniqueKey), UniqueKey.class, out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)), AbstractKeys.class, out.ref(getStrategy().getFullJavaIdentifier(uniqueKey.getTable()), 2), escapeString(uniqueKey.getOutputName()), out.ref(getStrategy().getFullJavaIdentifiers(uniqueKey.getKeyColumns()), colRefSegments(null))); else out.tab(2).println("public static final %s<%s> %s = createUniqueKey(%s, \"%s\", [[%s]]);", UniqueKey.class, out.ref(getStrategy().getFullJavaClassName(uniqueKey.getTable(), Mode.RECORD)), getStrategy().getJavaIdentifier(uniqueKey), out.ref(getStrategy().getFullJavaIdentifier(uniqueKey.getTable()), 2), escapeString(uniqueKey.getOutputName()), out.ref(getStrategy().getFullJavaIdentifiers(uniqueKey.getKeyColumns()), colRefSegments(null))); } protected void printForeignKey(JavaWriter out, int foreignKeyCounter, ForeignKeyDefinition foreignKey) { final int block = foreignKeyCounter / INITIALISER_SIZE; // Print new nested class if (foreignKeyCounter % INITIALISER_SIZE == 0) { if (foreignKeyCounter > 0) { out.tab(1).println("}"); } out.println(); if (scala) out.tab(1).println("private object ForeignKeys%s extends %s {", block, AbstractKeys.class); else out.tab(1).println("private static class ForeignKeys%s extends %s {", block, AbstractKeys.class); } if (scala) out.tab(2).println("val %s : %s[%s, %s] = %s.createForeignKey(%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)), AbstractKeys.class, out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getReferencedKey()), 2), out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getKeyTable()), 2), escapeString(foreignKey.getOutputName()), out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getKeyColumns()), colRefSegments(null))); else out.tab(2).println("public static final %s<%s, %s> %s = createForeignKey(%s, %s, \"%s\", [[%s]]);", ForeignKey.class, out.ref(getStrategy().getFullJavaClassName(foreignKey.getKeyTable(), Mode.RECORD)), out.ref(getStrategy().getFullJavaClassName(foreignKey.getReferencedTable(), Mode.RECORD)), getStrategy().getJavaIdentifier(foreignKey), out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getReferencedKey()), 2), out.ref(getStrategy().getFullJavaIdentifier(foreignKey.getKeyTable()), 2), escapeString(foreignKey.getOutputName()), out.ref(getStrategy().getFullJavaIdentifiers(foreignKey.getKeyColumns()), colRefSegments(null))); } 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(getStrategy().getFile(table, Mode.RECORD)); log.info("Generating record", out.file().getName()); generateRecord(table, out); closeJavaWriter(out); } protected void generateUDTRecord(UDTDefinition udt) { JavaWriter out = newJavaWriter(getStrategy().getFile(udt, Mode.RECORD)); log.info("Generating record", out.file().getName()); generateRecord(udt, out); closeJavaWriter(out); } protected void generateRecord(TableDefinition table, JavaWriter out) { generateRecord((Definition) table, out); } protected void generateUDTRecord(UDTDefinition udt, JavaWriter out) { generateRecord(udt, out); } private void generateRecord(Definition tableOrUdt, JavaWriter out) { final UniqueKeyDefinition key = (tableOrUdt instanceof TableDefinition) ? ((TableDefinition) tableOrUdt).getPrimaryKey() : null; final String className = getStrategy().getJavaClassName(tableOrUdt, Mode.RECORD); final String tableIdentifier = out.ref(getStrategy().getFullJavaIdentifier(tableOrUdt), 2); final List interfaces = out.ref(getStrategy().getJavaClassImplements(tableOrUdt, Mode.RECORD)); final List> columns = getTypedElements(tableOrUdt); printPackage(out, tableOrUdt, Mode.RECORD); if (tableOrUdt instanceof TableDefinition) generateRecordClassJavadoc((TableDefinition) tableOrUdt, out); else generateUDTRecordClassJavadoc((UDTDefinition) tableOrUdt, out); printClassAnnotations(out, tableOrUdt.getSchema()); if (tableOrUdt instanceof TableDefinition) printTableJPAAnnotation(out, (TableDefinition) tableOrUdt); Class baseClass; if (tableOrUdt instanceof UDTDefinition) baseClass = UDTRecordImpl.class; else if (generateRelations() && key != null) baseClass = UpdatableRecordImpl.class; else baseClass = TableRecordImpl.class; int degree = columns.size(); String rowType = null; String rowTypeRecord = null; // [#3130] Invalid UDTs may have a degree of 0 if (degree > 0 && degree <= Constants.MAX_ROW_DEGREE) { rowType = refRowType(out, columns); 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(tableOrUdt, Mode.INTERFACE))); } if (scala) out.println("class %s extends %s[%s](%s)[[before= with ][separator= with ][%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 (int i = 0; i < degree; i++) { TypedElementDefinition column = columns.get(i); final String comment = StringUtils.defaultString(column.getComment()); final String setterReturnType = fluentSetters() ? className : tokenVoid; final String setter = getStrategy().getJavaSetterName(column, Mode.RECORD); final String getter = getStrategy().getJavaGetterName(column, Mode.RECORD); final String type = out.ref(getJavaType(column.getType())); final String name = column.getQualifiedOutputName(); final boolean isUDT = column.getType().isUDT(); final boolean isArray = column.getType().isArray(); final boolean isUDTArray = column.getType().isArray() && database.getArray(column.getType().getSchema(), column.getType().getUserType()).getElementType().isUDT(); // We cannot have covariant setters for arrays because of type erasure if (!(generateInterfaces() && isArray)) { out.tab(1).javadoc("Setter for %s.%s", name, defaultIfBlank(" " + comment, "")); if (scala) { out.tab(1).println("def %s(value : %s) : %s = {", setter, type, setterReturnType); out.tab(2).println("set(%s, value)", i); if (fluentSetters()) out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).overrideIf(generateInterfaces() && !generateImmutablePojos() && !isUDT); out.tab(1).println("public %s %s(%s value) {", setterReturnType, setter, type); out.tab(2).println("set(%s, value);", i); if (fluentSetters()) out.tab(2).println("return this;"); out.tab(1).println("}"); } } // [#3117] Avoid covariant setters for UDTs when generating interfaces if (generateInterfaces() && !generateImmutablePojos() && (isUDT || isArray)) { final String columnType = out.ref(getJavaType(column.getType(), Mode.RECORD)); final String columnTypeInterface = out.ref(getJavaType(column.getType(), Mode.INTERFACE)); out.tab(1).javadoc("Setter for %s.%s", name, defaultIfBlank(" " + comment, "")); out.tab(1).override(); if (scala) { // [#3082] TODO Handle + ARRAY also for Scala out.tab(1).println("def %s(value : %s) : %s = {", setter, columnTypeInterface, setterReturnType); out.tab(2).println("if (value == null)"); out.tab(3).println("set(%s, null)", i); out.tab(2).println("else"); out.tab(3).println("set(%s, value.into(new %s()))", i, type); if (fluentSetters()) out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).println("public %s %s(%s value) {", setterReturnType, setter, columnTypeInterface); out.tab(2).println("if (value == null)"); out.tab(3).println("set(%s, null);", i); if (isUDT) { out.tab(2).println("else"); out.tab(3).println("set(%s, value.into(new %s()));", i, type); } else if (isArray) { final ArrayDefinition array = database.getArray(column.getType().getSchema(), column.getType().getUserType()); final String componentType = out.ref(getJavaType(array.getElementType(), Mode.RECORD)); final String componentTypeInterface = out.ref(getJavaType(array.getElementType(), Mode.INTERFACE)); out.tab(2).println("else {"); out.tab(3).println("%s a = new %s();", columnType, columnType); out.println(); out.tab(3).println("for (%s i : value)", componentTypeInterface); if (isUDTArray) out.tab(4).println("a.add(i.into(new %s()));", componentType); else out.tab(4).println("a.add(i);", componentType); out.println(); out.tab(3).println("set(1, a);"); out.tab(2).println("}"); } if (fluentSetters()) out.tab(2).println("return this;"); out.tab(1).println("}"); } } out.tab(1).javadoc("Getter for %s.%s", name, defaultIfBlank(" " + comment, "")); if (tableOrUdt instanceof TableDefinition) printColumnJPAAnnotation(out, (ColumnDefinition) column); printValidationAnnotation(out, column); if (scala) { out.tab(1).println("def %s : %s = {", getter, type); out.tab(2).println("val r = get(%s)", i); out.tab(2).println("if (r == null) null else r.asInstanceOf[%s]", type); out.tab(1).println("}"); } else { out.tab(1).overrideIf(generateInterfaces()); out.tab(1).println("public %s %s() {", type, getter); out.tab(2).println("return (%s) get(%s);", type, i); out.tab(1).println("}"); } } if (generateRelations() && key != null) { int keyDegree = key.getKeyColumns().size(); if (keyDegree <= Constants.MAX_ROW_DEGREE) { String keyType = refRowType(out, key.getKeyColumns()); out.tab(1).header("Primary key information"); if (scala) { out.tab(1).println("override def key() : %s[%s] = {", out.ref(Record.class.getName() + keyDegree), keyType); out.tab(2).println("return super.key.asInstanceOf[ %s[%s] ]", out.ref(Record.class.getName() + keyDegree), keyType); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s> key() {", out.ref(Record.class.getName() + keyDegree), keyType); out.tab(2).println("return (%s) super.key();", out.ref(Record.class.getName() + keyDegree)); out.tab(1).println("}"); } } } if (tableOrUdt instanceof UDTDefinition) { // [#799] Oracle UDT's can have member procedures for (RoutineDefinition routine : ((UDTDefinition) tableOrUdt).getRoutines()) { // Instance methods ship with a SELF parameter at the first position // [#1584] Static methods don't have that boolean instance = routine.getInParameters().size() > 0 && routine.getInParameters().get(0).getInputName().toUpperCase().equals("SELF"); try { if (!routine.isSQLUsable()) { // Instance execute() convenience method printConvenienceMethodProcedure(out, routine, instance); } else { // Instance execute() convenience method if (!routine.isAggregate()) { printConvenienceMethodFunction(out, routine, instance); } } } catch (Exception e) { log.error("Error while generating routine " + routine, e); } } } // [#3130] Invalid UDTs may have a degree of 0 if (degree > 0 && degree <= Constants.MAX_ROW_DEGREE) { out.tab(1).header("Record%s type implementation", degree); // fieldsRow() if (scala) { out.println(); out.tab(1).println("override def fieldsRow : %s[%s] = {", out.ref(Row.class.getName() + degree), rowType); out.tab(2).println("super.fieldsRow.asInstanceOf[ %s[%s] ]", out.ref(Row.class.getName() + degree), rowType); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s> fieldsRow() {", out.ref(Row.class.getName() + degree), rowType); out.tab(2).println("return (%s) super.fieldsRow();", out.ref(Row.class.getName() + degree)); out.tab(1).println("}"); } // valuesRow() if (scala) { out.println(); out.tab(1).println("override def valuesRow : %s[%s] = {", out.ref(Row.class.getName() + degree), rowType); out.tab(2).println("super.valuesRow.asInstanceOf[ %s[%s] ]", out.ref(Row.class.getName() + degree), rowType); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s> valuesRow() {", out.ref(Row.class.getName() + degree), rowType); out.tab(2).println("return (%s) super.valuesRow();", out.ref(Row.class.getName() + degree)); out.tab(1).println("}"); } // field[N]() for (int i = 1; i <= degree; i++) { TypedElementDefinition column = columns.get(i - 1); final String colType = out.ref(getJavaType(column.getType())); final String colIdentifier = out.ref(getStrategy().getFullJavaIdentifier(column), colRefSegments(column)); if (scala) { out.tab(1).println("override def field%s : %s[%s] = %s", i, Field.class, colType, colIdentifier); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s> field%s() {", Field.class, colType, i); out.tab(2).println("return %s;", colIdentifier); out.tab(1).println("}"); } } // value[N]() for (int i = 1; i <= degree; i++) { TypedElementDefinition column = columns.get(i - 1); final String colType = out.ref(getJavaType(column.getType())); final String colGetter = getStrategy().getJavaGetterName(column, Mode.RECORD); if (scala) { out.tab(1).println("override def value%s : %s = %s", i, colType, colGetter); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s value%s() {", colType, i); out.tab(2).println("return %s();", colGetter); out.tab(1).println("}"); } } // value[N](T[N]) for (int i = 1; i <= degree; i++) { TypedElementDefinition column = columns.get(i - 1); final String colType = out.ref(getJavaType(column.getType())); final String colSetter = getStrategy().getJavaSetterName(column, Mode.RECORD); if (scala) { out.println(); out.tab(1).println("override def value%s(value : %s) : %s = {", i, colType, className); out.tab(2).println("%s(value)", colSetter); out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s value%s(%s value) {", className, i, colType); out.tab(2).println("%s(value);", colSetter); out.tab(2).println("return this;"); out.tab(1).println("}"); } } List arguments = new ArrayList(); List calls = new ArrayList(); for (int i = 1; i <= degree; i++) { TypedElementDefinition column = columns.get(i - 1); final String colType = out.ref(getJavaType(column.getType())); if (scala) { arguments.add("value" + i + " : " + colType); calls.add("this.value" + i + "(value" + i + ")"); } else { arguments.add(colType + " value" + i); calls.add("value" + i + "(value" + i + ");"); } } if (scala) { out.println(); out.tab(1).println("override def values([[%s]]) : %s = {", arguments, className); for (String call : calls) out.tab(2).println(call); out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s values([[%s]]) {", className, arguments); for (String call : calls) out.tab(2).println(call); out.tab(2).println("return this;"); out.tab(1).println("}"); } } if (generateInterfaces() && !generateImmutablePojos()) { printFromAndInto(out, tableOrUdt); } if (scala) { } else { out.tab(1).header("Constructors"); out.tab(1).javadoc("Create a detached %s", className); out.tab(1).println("public %s() {", className); out.tab(2).println("super(%s);", tableIdentifier); out.tab(1).println("}"); } // [#3130] Invalid UDTs may have a degree of 0 // [#3176] Avoid generating constructors for tables with more than 255 columns (Java's method argument limit) if (degree > 0 && degree < 256) { List arguments = new ArrayList(); for (int i = 0; i < degree; i++) { final TypedElementDefinition column = columns.get(i); final String columnMember = getStrategy().getJavaMemberName(column, Mode.DEFAULT); final String type = out.ref(getJavaType(column.getType())); if (scala) arguments.add(columnMember + " : " + type); else arguments.add(type + " " + columnMember); } out.tab(1).javadoc("Create a detached, initialised %s", className); if (scala) { out.tab(1).println("def this([[%s]]) = {", arguments); out.tab(2).println("this()", tableIdentifier); } else { out.tab(1).println("public %s([[%s]]) {", className, arguments); out.tab(2).println("super(%s);", tableIdentifier); } out.println(); for (int i = 0; i < degree; i++) { final TypedElementDefinition column = columns.get(i); final String columnMember = getStrategy().getJavaMemberName(column, Mode.DEFAULT); if (scala) out.tab(2).println("set(%s, %s)", i, columnMember); else out.tab(2).println("set(%s, %s);", i, columnMember); } out.tab(1).println("}"); } if (tableOrUdt instanceof TableDefinition) generateRecordClassFooter((TableDefinition) tableOrUdt, out); else generateUDTRecordClassFooter((UDTDefinition) tableOrUdt, out); out.println("}"); } private int colRefSegments(TypedElementDefinition column) { if (column != null && column.getContainer() instanceof UDTDefinition) return 2; if (!getStrategy().getInstanceFields()) return 2; return 3; } /** * Subclasses may override this method to provide record class footer code. */ @SuppressWarnings("unused") protected void generateRecordClassFooter(TableDefinition table, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateRecordClassJavadoc(TableDefinition table, JavaWriter out) { printClassJavadoc(out, table); } private final String refRowType(JavaWriter out, Collection> columns) { StringBuilder result = new StringBuilder(); String separator = ""; for (TypedElementDefinition column : columns) { result.append(separator); result.append(out.ref(getJavaType(column.getType()))); 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(getStrategy().getFile(table, Mode.INTERFACE)); log.info("Generating interface", out.file().getName()); generateInterface(table, out); closeJavaWriter(out); } protected void generateUDTInterface(UDTDefinition udt) { JavaWriter out = newJavaWriter(getStrategy().getFile(udt, Mode.INTERFACE)); log.info("Generating interface", out.file().getName()); generateInterface(udt, out); closeJavaWriter(out); } protected void generateInterface(TableDefinition table, JavaWriter out) { generateInterface((Definition) table, out); } protected void generateUDTInterface(UDTDefinition udt, JavaWriter out) { generateInterface(udt, out); } private void generateInterface(Definition tableOrUDT, JavaWriter out) { final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.INTERFACE); final List interfaces = out.ref(getStrategy().getJavaClassImplements(tableOrUDT, Mode.INTERFACE)); printPackage(out, tableOrUDT, Mode.INTERFACE); if (tableOrUDT instanceof TableDefinition) generateInterfaceClassJavadoc((TableDefinition) tableOrUDT, out); else generateUDTInterfaceClassJavadoc((UDTDefinition) tableOrUDT, out); printClassAnnotations(out, tableOrUDT.getSchema()); if (tableOrUDT instanceof TableDefinition) printTableJPAAnnotation(out, (TableDefinition) tableOrUDT); if (scala) out.println("trait %s [[before=extends ][%s]] {", className, interfaces); else out.println("public interface %s [[before=extends ][%s]] {", className, interfaces); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String comment = StringUtils.defaultString(column.getComment()); final String setterReturnType = fluentSetters() ? className : "void"; final String setter = getStrategy().getJavaSetterName(column, Mode.INTERFACE); final String getter = getStrategy().getJavaGetterName(column, Mode.INTERFACE); final String type = out.ref(getJavaType(column.getType(), Mode.INTERFACE)); final String name = column.getQualifiedOutputName(); if (!generateImmutablePojos()) { out.tab(1).javadoc("Setter for %s.%s", name, defaultIfBlank(" " + comment, "")); if (scala) out.tab(1).println("def %s(value : %s) : %s", setter, type, setterReturnType); else out.tab(1).println("public %s %s(%s value);", setterReturnType, setter, type); } out.tab(1).javadoc("Getter for %s.%s", name, defaultIfBlank(" " + comment, "")); if (column instanceof ColumnDefinition) printColumnJPAAnnotation(out, (ColumnDefinition) column); printValidationAnnotation(out, column); if (scala) out.tab(1).println("def %s : %s", getter, type); else out.tab(1).println("public %s %s();", type, getter); } if (!generateImmutablePojos()) { String local = getStrategy().getJavaClassName(tableOrUDT, Mode.INTERFACE); String qualified = out.ref(getStrategy().getFullJavaClassName(tableOrUDT, Mode.INTERFACE)); out.tab(1).header("FROM and INTO"); out.tab(1).javadoc("Load data from another generated Record/POJO implementing the common interface %s", local); if (scala) out.tab(1).println("def from(from : %s)", qualified); else out.tab(1).println("public void from(%s from);", qualified); out.tab(1).javadoc("Copy data into another generated Record/POJO implementing the common interface %s", local); if (scala) out.tab(1).println("def into [E <: %s](into : E) : E", qualified); else out.tab(1).println("public E into(E into);", qualified); } if (tableOrUDT instanceof TableDefinition) generateInterfaceClassFooter((TableDefinition) tableOrUDT, out); else generateUDTInterfaceClassFooter((UDTDefinition) tableOrUDT, out); out.println("}"); } /** * Subclasses may override this method to provide interface class footer * code. */ @SuppressWarnings("unused") protected void generateInterfaceClassFooter(TableDefinition table, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateInterfaceClassJavadoc(TableDefinition table, JavaWriter out) { printClassJavadoc(out, table); } 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(getStrategy().getFile(udt)); log.info("Generating UDT ", out.file().getName()); generateUDT(udt, out); closeJavaWriter(out); } protected void generateUDT(UDTDefinition udt, JavaWriter out) { final SchemaDefinition schema = udt.getSchema(); final String className = getStrategy().getJavaClassName(udt); final String recordType = out.ref(getStrategy().getFullJavaClassName(udt, Mode.RECORD)); final List interfaces = out.ref(getStrategy().getJavaClassImplements(udt, Mode.DEFAULT)); final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 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); final String attrComment = StringUtils.defaultString(attribute.getComment()); out.tab(1).javadoc("The attribute %s.%s", attribute.getQualifiedOutputName(), defaultIfBlank(" " + attrComment, "")); out.tab(1).println("val %s = %s.%s", attrId, udtId, attrId); } out.println("}"); out.println(); } generateUDTClassJavadoc(udt, out); printClassAnnotations(out, schema); // [#799] Oracle UDTs with member procedures have similarities with packages if (udt.getRoutines().size() > 0) { interfaces.add(out.ref(Package.class)); } if (scala) { out.println("class %s extends %s[%s](\"%s\", null)[[before= with ][separator= with ][%s]] {", className, UDTImpl.class, recordType, udt.getOutputName(), interfaces); } 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 attrType = out.ref(getJavaType(attribute.getType())); final String attrTypeRef = getJavaTypeReference(attribute.getDatabase(), attribute.getType()); final String attrId = out.ref(getStrategy().getJavaIdentifier(attribute), 2); final String attrName = attribute.getName(); final String attrComment = StringUtils.defaultString(attribute.getComment()); final List converters = out.ref(list( attribute.getType().getConverter(), attribute.getType().getBinding() )); if (scala) { out.tab(1).println("private val %s : %s[%s, %s] = %s.createField(\"%s\", %s, this, \"%s\"[[before=, ][new %s]])", attrId, UDTField.class, recordType, attrType, UDTImpl.class, attrName, attrTypeRef, escapeString(""), converters); } else { out.tab(1).javadoc("The attribute %s.%s", attribute.getQualifiedOutputName(), defaultIfBlank(" " + attrComment, "")); out.tab(1).println("public static final %s<%s, %s> %s = createField(\"%s\", %s, %s, \"%s\"[[before=, ][new %s()]]);", UDTField.class, recordType, attrType, attrId, attrName, attrTypeRef, udtId, escapeString(""), converters); } } // [#799] Oracle UDT's can have member procedures for (RoutineDefinition routine : udt.getRoutines()) { try { if (!routine.isSQLUsable()) { // Static execute() convenience method printConvenienceMethodProcedure(out, routine, false); } else { // Static execute() convenience method if (!routine.isAggregate()) { printConvenienceMethodFunction(out, routine, false); } // Static asField() convenience method printConvenienceMethodFunctionAsField(out, routine, false); printConvenienceMethodFunctionAsField(out, routine, true); } } catch (Exception e) { log.error("Error while generating routine " + routine, e); } } if (scala) { } else { out.tab(1).javadoc(NO_FURTHER_INSTANCES_ALLOWED); out.tab(1).println("private %s() {", className); out.tab(2).println("super(\"%s\", null);", udt.getOutputName()); out.tab(1).println("}"); } if (scala) { out.println(); out.tab(1).println("override def getSchema : %s = %s", Schema.class, schemaId); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s getSchema() {", Schema.class); out.tab(2).println("return %s;", schemaId); out.tab(1).println("}"); } generateUDTClassFooter(udt, out); out.println("}"); closeJavaWriter(out); } /** * Subclasses may override this method to provide udt class footer code. */ @SuppressWarnings("unused") protected void generateUDTClassFooter(UDTDefinition udt, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateUDTClassJavadoc(UDTDefinition udt, JavaWriter out) { printClassJavadoc(out, udt); } 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"); } /** * Subclasses may override this method to provide UDT POJO class footer code. */ @SuppressWarnings("unused") protected void generateUDTPojoClassFooter(UDTDefinition udt, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateUDTPojoClassJavadoc(UDTDefinition udt, JavaWriter out) { printClassJavadoc(out, udt); } 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"); } /** * Subclasses may override this method to provide UDT interface class footer code. */ @SuppressWarnings("unused") protected void generateUDTInterfaceClassFooter(UDTDefinition udt, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateUDTInterfaceClassJavadoc(UDTDefinition udt, JavaWriter out) { printClassJavadoc(out, udt); } /** * Generating UDT record classes */ 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"); } /** * Subclasses may override this method to provide udt record class footer code. */ @SuppressWarnings("unused") protected void generateUDTRecordClassFooter(UDTDefinition udt, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateUDTRecordClassJavadoc(UDTDefinition udt, JavaWriter out) { printClassJavadoc(out, udt); } 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"); } } } /** * Generating central static udt access */ protected void generateUDTReferences(SchemaDefinition schema) { log.info("Generating UDT references"); JavaWriter out = newJavaWriter(new File(getStrategy().getFile(schema).getParentFile(), "UDTs.java")); printPackage(out, schema); printClassJavadoc(out, "Convenience access to all UDTs in " + schema.getOutputName()); printClassAnnotations(out, schema); if (scala) out.println("object UDTs {"); else out.println("public class UDTs {"); for (UDTDefinition udt : database.getUDTs(schema)) { final String className = out.ref(getStrategy().getFullJavaClassName(udt)); final String id = getStrategy().getJavaIdentifier(udt); final String fullId = getStrategy().getFullJavaIdentifier(udt); out.tab(1).javadoc("The type %s", udt.getQualifiedOutputName()); if (scala) out.tab(1).println("val %s = %s", id, fullId); else out.tab(1).println("public static %s %s = %s;", className, id, fullId); } out.println("}"); closeJavaWriter(out); watch.splitInfo("UDT references generated"); } 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(getStrategy().getFile(array, Mode.RECORD)); log.info("Generating ARRAY", out.file().getName()); generateArray(array, out); closeJavaWriter(out); } protected void generateArray(ArrayDefinition array, JavaWriter out) { } /** * Subclasses may override this method to provide array class footer code. */ @SuppressWarnings("unused") protected void generateArrayClassFooter(ArrayDefinition array, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateArrayClassJavadoc(ArrayDefinition array, JavaWriter out) { printClassJavadoc(out, array); } 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"); } protected void generateDomains(SchemaDefinition schema) { log.info("Generating DOMAINs"); for (DomainDefinition d : database.getDomains(schema)) { try { generateDomain(d); } catch (Exception ex) { log.error("Error while generating domain " + d, ex); } } watch.splitInfo("Domains generated"); } protected void generateEnum(EnumDefinition e) { JavaWriter out = newJavaWriter(getStrategy().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 interfaces = out.ref(getStrategy().getJavaClassImplements(e, Mode.ENUM)); final List literals = e.getLiterals(); final List identifiers = new ArrayList(); for (int i = 0; i < literals.size(); i++) { String identifier = convertToIdentifier(literals.get(i), language); // [#2781] Disambiguate collisions with the leading package name if (identifier.equals(getStrategy().getJavaPackageName(e).replaceAll("\\..*", ""))) identifier += "_"; identifiers.add(identifier); } printPackage(out, e); generateEnumClassJavadoc(e, out); printClassAnnotations(out, e.getSchema()); if (scala) { out.println("object %s {", className); out.println(); for (int i = 0; i < identifiers.size(); i++) { out.tab(1).println("val %s : %s = %s.%s", identifiers.get(i), className, getStrategy().getJavaPackageName(e), identifiers.get(i)); } out.println(); out.tab(1).println("def values() : %s[%s] = %s(", out.ref("scala.Array"), className, out.ref("scala.Array")); for (int i = 0; i < identifiers.size(); i++) { out.tab(2).print((i > 0 ? ", " : " ")); out.println(identifiers.get(i)); } out.tab(1).println(")"); out.println(); out.tab(1).println("def valueOf(s : %s) : %s = s match {", String.class, className); for (int i = 0; i < identifiers.size(); i++) { out.tab(2).println("case \"%s\" => %s", literals.get(i), identifiers.get(i)); } out.tab(2).println("case _ => throw new %s()", IllegalArgumentException.class); out.tab(1).println("}"); out.println("}"); out.println(); out.println("sealed trait %s extends %s[[before= with ][%s]] {", className, EnumType.class, interfaces); // [#2135] Only the PostgreSQL database supports schema-scoped enum types out.tab(1).println("override def getSchema : %s = %s", Schema.class, (e.isSynthetic() || !(e.getDatabase() instanceof PostgresDatabase)) ? "null" : out.ref(getStrategy().getFullJavaIdentifier(e.getSchema()), 2)); out.tab(1).println("override def getName : %s = %s", String.class, e.isSynthetic() ? "null" : "\"" + e.getName().replace("\"", "\\\"") + "\""); 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.tab(1).println("override def getLiteral : %s = \"%s\"", String.class, literals.get(i)); 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.tab(1).println("%s(\"%s\")%s", identifiers.get(i), literals.get(i), (i == literals.size() - 1) ? ";" : ","); } out.println(); out.tab(1).println("private final %s literal;", String.class); out.println(); out.tab(1).println("private %s(%s literal) {", className, String.class); out.tab(2).println("this.literal = literal;"); out.tab(1).println("}"); // [#2135] Only the PostgreSQL database supports schema-scoped enum types out.tab(1).overrideInherit(); out.tab(1).println("public %s getSchema() {", Schema.class); out.tab(2).println("return %s;", (e.isSynthetic() || !(e.getDatabase() instanceof PostgresDatabase)) ? "null" : out.ref(getStrategy().getFullJavaIdentifier(e.getSchema()), 2)); out.tab(1).println("}"); out.tab(1).overrideInherit(); out.tab(1).println("public %s getName() {", String.class); out.tab(2).println("return %s;", e.isSynthetic() ? "null" : "\"" + e.getName().replace("\"", "\\\"") + "\""); out.tab(1).println("}"); out.tab(1).overrideInherit(); out.tab(1).println("public %s getLiteral() {", String.class); out.tab(2).println("return literal;"); out.tab(1).println("}"); generateEnumClassFooter(e, out); out.println("}"); } } /** * Subclasses may override this method to provide enum class footer code. */ @SuppressWarnings("unused") protected void generateEnumClassFooter(EnumDefinition e, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateEnumClassJavadoc(EnumDefinition e, JavaWriter out) { printClassJavadoc(out, e); } protected void generateDomain(DomainDefinition d) { JavaWriter out = newJavaWriter(getStrategy().getFile(d, Mode.DOMAIN)); log.info("Generating DOMAIN", out.file().getName()); generateDomain(d, out); closeJavaWriter(out); } protected void generateDomain(DomainDefinition d, JavaWriter out) { final String className = getStrategy().getJavaClassName(d, Mode.DOMAIN); final String superName = out.ref(getStrategy().getJavaClassExtends(d, Mode.DOMAIN)); final List interfaces = out.ref(getStrategy().getJavaClassImplements(d, Mode.DOMAIN)); final List superTypes = list(superName, interfaces); printPackage(out, d); generateDomainClassJavadoc(d, out); printClassAnnotations(out, d.getSchema()); for (String clause : d.getCheckClauses()) out.println("// " + clause); if (scala) out.println("class %s[[before= extends ][%s]][[before= with ][separator= with ][%s]] {", className, first(superTypes), remaining(superTypes)); else out.println("public class %s[[before= extends ][%s]][[before= implements ][%s]] {", className, list(superName), interfaces); generateDomainClassFooter(d, out); out.println("}"); } /** * Subclasses may override this method to provide enum class footer code. */ @SuppressWarnings("unused") protected void generateDomainClassFooter(DomainDefinition d, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateDomainClassJavadoc(DomainDefinition e, JavaWriter out) { printClassJavadoc(out, e); } protected void generateRoutines(SchemaDefinition schema) { log.info("Generating routines and table-valued functions"); JavaWriter out = newJavaWriter(new File(getStrategy().getFile(schema).getParentFile(), "Routines.java")); printPackage(out, schema); printClassJavadoc(out, "Convenience access to all stored procedures and functions in " + schema.getOutputName()); printClassAnnotations(out, schema); if (scala) out.println("object Routines {"); else out.println("public class Routines {"); for (RoutineDefinition routine : database.getRoutines(schema)) { printRoutine(out, routine); try { generateRoutine(schema, routine); } catch (Exception e) { log.error("Error while generating routine " + routine, e); } } for (TableDefinition table : database.getTables(schema)) { if (table.isTableValuedFunction()) { printTableValuedFunction(out, table, getStrategy().getJavaMethodName(table, Mode.DEFAULT)); } } out.println("}"); closeJavaWriter(out); watch.splitInfo("Routines generated"); } protected void printConstant(JavaWriter out, AttributeDefinition constant) { } protected void printRoutine(JavaWriter out, RoutineDefinition routine) { if (!routine.isSQLUsable()) { // Static execute() convenience method printConvenienceMethodProcedure(out, routine, false); } else { // Static execute() convenience method // [#457] This doesn't make any sense for user-defined aggregates if (!routine.isAggregate()) { printConvenienceMethodFunction(out, routine, false); } // Static asField() convenience method 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) { } /** * Subclasses may override this method to provide package class footer code. */ @SuppressWarnings("unused") protected void generatePackageClassFooter(PackageDefinition pkg, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generatePackageClassJavadoc(PackageDefinition pkg, JavaWriter out) { printClassJavadoc(out, "Convenience access to all stored procedures and functions in " + pkg.getName()); } /** * Generating central static table access */ protected void generateTableReferences(SchemaDefinition schema) { log.info("Generating table references"); JavaWriter out = newJavaWriter(new File(getStrategy().getFile(schema).getParentFile(), "Tables.java")); printPackage(out, schema); printClassJavadoc(out, "Convenience access to all tables in " + schema.getOutputName()); printClassAnnotations(out, schema); if (scala) out.println("object Tables {"); else out.println("public class Tables {"); for (TableDefinition table : database.getTables(schema)) { final String className = out.ref(getStrategy().getFullJavaClassName(table)); final String id = getStrategy().getJavaIdentifier(table); final String fullId = getStrategy().getFullJavaIdentifier(table); final String comment = !StringUtils.isBlank(table.getComment()) ? table.getComment() : "The table " + table.getQualifiedOutputName() + "."; // [#4883] Scala doesn't have separate namespaces for val and def if (scala && table.isTableValuedFunction() && table.getParameters().isEmpty()) ; else { out.tab(1).javadoc(comment); if (scala) out.tab(1).println("val %s = %s", id, fullId); else out.tab(1).println("public static final %s %s = %s;", className, id, fullId); } // [#3797] Table-valued functions generate two different literals in // globalObjectReferences if (table.isTableValuedFunction()) printTableValuedFunction(out, table, getStrategy().getJavaIdentifier(table)); } out.println("}"); closeJavaWriter(out); watch.splitInfo("Table refs generated"); } 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(getStrategy().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 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 ? "Unit" : "Void"); String pType = out.ref(getStrategy().getFullJavaClassName(table, Mode.POJO)); List keyColumns = key.getKeyColumns(); if (keyColumns.size() == 1) { tType = getJavaType(keyColumns.get(0).getType()); } else if (keyColumns.size() <= Constants.MAX_ROW_DEGREE) { String generics = ""; String separator = ""; for (ColumnDefinition column : keyColumns) { generics += separator + out.ref(getJavaType(column.getType())); 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.getSchema()); 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 out.println("public class %s extends %s<%s, %s, %s>[[before= implements ][%s]] {", className, daoImpl, tableRecord, pType, tType, interfaces); // Default constructor // ------------------- out.tab(1).javadoc("Create a new %s without any configuration", className); if (scala) { out.tab(1).println("def this() = {"); out.tab(2).println("this(null)"); out.tab(1).println("}"); } else { out.tab(1).println("public %s() {", className); out.tab(2).println("super(%s, %s.class);", tableIdentifier, pType); out.tab(1).println("}"); } // Initialising constructor // ------------------------ if (scala) { } else { out.tab(1).javadoc("Create a new %s with an attached configuration", className); if (generateSpringAnnotations()) out.tab(1).println("@%s", out.ref("org.springframework.beans.factory.annotation.Autowired")); out.tab(1).println("public %s(%s configuration) {", className, Configuration.class); out.tab(2).println("super(%s, %s.class, configuration);", tableIdentifier, pType); out.tab(1).println("}"); } // Template method implementations // ------------------------------- if (scala) { out.println(); out.tab(1).println("override protected def getId(o : %s) : %s = {", pType, tType); } else { out.tab(1).overrideInherit(); out.tab(1).println("protected %s getId(%s object) {", tType, pType); } if (keyColumns.size() == 1) { if (scala) out.tab(2).println("o.%s", getStrategy().getJavaGetterName(keyColumns.get(0), Mode.POJO)); else out.tab(2).println("return object.%s();", getStrategy().getJavaGetterName(keyColumns.get(0), Mode.POJO)); } // [#2574] This should be replaced by a call to a method on the target table's Key type else { String params = ""; String separator = ""; for (ColumnDefinition column : keyColumns) { if (scala) params += separator + "o." + getStrategy().getJavaGetterName(column, Mode.POJO); else params += separator + "object." + getStrategy().getJavaGetterName(column, Mode.POJO) + "()"; separator = ", "; } if (scala) out.tab(2).println("compositeKeyRecord(%s)", params); else out.tab(2).println("return compositeKeyRecord(%s);", params); } out.tab(1).println("}"); for (ColumnDefinition column : table.getColumns()) { final String colName = column.getOutputName(); final String colClass = getStrategy().getJavaClassName(column); final String colType = out.ref(getJavaType(column.getType())); final String colIdentifier = out.ref(getStrategy().getFullJavaIdentifier(column), colRefSegments(column)); // fetchBy[Column]([T]...) // ----------------------- out.tab(1).javadoc("Fetch records that have %s IN (values)", colName); if (scala) { out.tab(1).println("def fetchBy%s(values : %s*) : %s[%s] = {", colClass, colType, List.class, pType); out.tab(2).println("fetch(%s, values:_*)", colIdentifier); out.tab(1).println("}"); } else { out.tab(1).println("public %s<%s> fetchBy%s(%s... values) {", List.class, pType, colClass, colType); out.tab(2).println("return fetch(%s, values);", colIdentifier); out.tab(1).println("}"); } // fetchOneBy[Column]([T]) // ----------------------- ukLoop: for (UniqueKeyDefinition uk : column.getUniqueKeys()) { // If column is part of a single-column unique key... if (uk.getKeyColumns().size() == 1 && uk.getKeyColumns().get(0).equals(column)) { out.tab(1).javadoc("Fetch a unique record that has %s = value", colName); if (scala) { out.tab(1).println("def fetchOneBy%s(value : %s) : %s = {", colClass, colType, pType); out.tab(2).println("fetchOne(%s, value)", colIdentifier); out.tab(1).println("}"); } else { out.tab(1).println("public %s fetchOneBy%s(%s value) {", pType, colClass, colType); out.tab(2).println("return fetchOne(%s, value);", colIdentifier); out.tab(1).println("}"); } break ukLoop; } } } generateDaoClassFooter(table, out); out.println("}"); } /** * Subclasses may override this method to provide dao class footer code. */ @SuppressWarnings("unused") protected void generateDaoClassFooter(TableDefinition table, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateDaoClassJavadoc(TableDefinition table, JavaWriter out) { printClassJavadoc(out, table); } 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(getStrategy().getFile(table, Mode.POJO)); log.info("Generating POJO", out.file().getName()); generatePojo(table, out); closeJavaWriter(out); } protected void generateUDTPojo(UDTDefinition udt) { JavaWriter out = newJavaWriter(getStrategy().getFile(udt, Mode.POJO)); log.info("Generating POJO", out.file().getName()); generatePojo(udt, out); closeJavaWriter(out); } protected void generatePojo(TableDefinition table, JavaWriter out) { generatePojo((Definition) table, out); } protected void generateUDTPojo(UDTDefinition udt, JavaWriter out) { generatePojo(udt, out); } private void generatePojo(Definition tableOrUDT, JavaWriter out) { final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO); final String superName = out.ref(getStrategy().getJavaClassExtends(tableOrUDT, Mode.POJO)); final List interfaces = out.ref(getStrategy().getJavaClassImplements(tableOrUDT, Mode.POJO)); final List superTypes = list(superName, interfaces); if (generateInterfaces()) { interfaces.add(out.ref(getStrategy().getFullJavaClassName(tableOrUDT, Mode.INTERFACE))); } printPackage(out, tableOrUDT, Mode.POJO); if (tableOrUDT instanceof TableDefinition) generatePojoClassJavadoc((TableDefinition) tableOrUDT, out); else generateUDTPojoClassJavadoc((UDTDefinition) tableOrUDT, out); printClassAnnotations(out, tableOrUDT.getSchema()); if (tableOrUDT instanceof TableDefinition) printTableJPAAnnotation(out, (TableDefinition) tableOrUDT); int maxLength = 0; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { maxLength = Math.max(maxLength, out.ref(getJavaType(column.getType(), Mode.POJO)).length()); } if (scala) { out.println("%sclass %s(", (generateImmutablePojos() ? "case " : ""), className); String separator = " "; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { out.tab(1).println("%s%s%s : %s", separator, generateImmutablePojos() ? "" : "private var ", getStrategy().getJavaMemberName(column, Mode.POJO), StringUtils.rightPad(out.ref(getJavaType(column.getType(), Mode.POJO)), maxLength)); separator = ", "; } out.println(")[[before= extends ][%s]][[before= with ][separator= with ][%s]] {", first(superTypes), remaining(superTypes)); } else { out.println("public class %s[[before= extends ][%s]][[before= implements ][%s]] {", className, list(superName), interfaces); out.printSerial(); out.println(); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { out.tab(1).println("private %s%s %s;", generateImmutablePojos() ? "final " : "", StringUtils.rightPad(out.ref(getJavaType(column.getType(), Mode.POJO)), maxLength), getStrategy().getJavaMemberName(column, Mode.POJO)); } } // Constructors // --------------------------------------------------------------------- // Default constructor if (!generateImmutablePojos()) { out.println(); if (scala) { // [#3010] Invalid UDTs may have no attributes. Avoid generating this constructor in that case int size = getTypedElements(tableOrUDT).size(); if (size > 0) { List nulls = new ArrayList(); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) // Avoid ambiguities between a single-T-value constructor // and the copy constructor if (size == 1) nulls.add("null : " + out.ref(getJavaType(column.getType(), Mode.POJO))); else nulls.add("null"); out.tab(1).println("def this() = {", className); out.tab(2).println("this([[%s]])", nulls); out.tab(1).println("}"); } } else { out.tab(1).println("public %s() {}", className); } } // [#1363] copy constructor out.println(); if (scala) { out.tab(1).println("def this (value : %s) = {", className, className); out.tab(2).println("this("); String separator = " "; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { out.tab(3).println("%svalue.%s", separator, getStrategy().getJavaMemberName(column, Mode.POJO), getStrategy().getJavaMemberName(column, Mode.POJO)); separator = ", "; } out.tab(2).println(")"); out.tab(1).println("}"); } else { out.tab(1).println("public %s(%s value) {", className, className); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { out.tab(2).println("this.%s = value.%s;", getStrategy().getJavaMemberName(column, Mode.POJO), getStrategy().getJavaMemberName(column, Mode.POJO)); } out.tab(1).println("}"); } // Multi-constructor if (scala) { } // [#3010] Invalid UDTs may have no attributes. Avoid generating this constructor in that case // [#3176] Avoid generating constructors for tables with more than 255 columns (Java's method argument limit) else if (getTypedElements(tableOrUDT).size() > 0 && getTypedElements(tableOrUDT).size() < 256) { out.println(); out.tab(1).print("public %s(", className); String separator1 = ""; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { out.println(separator1); out.tab(2).print("%s %s", StringUtils.rightPad(out.ref(getJavaType(column.getType(), Mode.POJO)), maxLength), getStrategy().getJavaMemberName(column, Mode.POJO)); separator1 = ","; } out.println(); out.tab(1).println(") {"); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); out.tab(2).println("this.%s = %s;", columnMember, columnMember); } out.tab(1).println("}"); } for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnType = out.ref(getJavaType(column.getType(), Mode.POJO)); final String columnSetterReturnType = fluentSetters() ? className : (scala ? "Unit" : "void"); final String columnSetter = getStrategy().getJavaSetterName(column, Mode.POJO); final String columnGetter = getStrategy().getJavaGetterName(column, Mode.POJO); final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); final boolean isUDT = column.getType().isUDT(); final boolean isUDTArray = column.getType().isArray() && database.getArray(column.getType().getSchema(), column.getType().getUserType()).getElementType().isUDT(); // Getter out.println(); if (column instanceof ColumnDefinition) printColumnJPAAnnotation(out, (ColumnDefinition) column); printValidationAnnotation(out, column); if (scala) { out.tab(1).println("def %s : %s = {", columnGetter, columnType); out.tab(2).println("this.%s", columnMember); out.tab(1).println("}"); } else { out.tab(1).overrideIf(generateInterfaces()); out.tab(1).println("public %s %s() {", columnType, columnGetter); out.tab(2).println("return this.%s;", columnMember); out.tab(1).println("}"); } // Setter if (!generateImmutablePojos()) { // We cannot have covariant setters for arrays because of type erasure if (!(generateInterfaces() && isUDTArray)) { out.println(); if (scala) { out.tab(1).println("def %s(%s : %s) : %s = {", columnSetter, columnMember, columnType, columnSetterReturnType); out.tab(2).println("this.%s = %s", columnMember, columnMember); if (fluentSetters()) out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).overrideIf(generateInterfaces() && !isUDT); out.tab(1).println("public %s %s(%s %s) {", columnSetterReturnType, columnSetter, columnType, columnMember); out.tab(2).println("this.%s = %s;", columnMember, columnMember); if (fluentSetters()) out.tab(2).println("return this;"); out.tab(1).println("}"); } } // [#3117] To avoid covariant setters on POJOs, we need to generate two setter overloads if (generateInterfaces() && (isUDT || isUDTArray)) { final String columnTypeInterface = out.ref(getJavaType(column.getType(), Mode.INTERFACE)); out.println(); if (scala) { // [#3082] TODO Handle + ARRAY also for Scala out.tab(1).println("def %s(%s : %s) : %s = {", columnSetter, columnMember, columnTypeInterface, columnSetterReturnType); out.tab(2).println("if (%s == null)", columnMember); out.tab(3).println("this.%s = null", columnMember); out.tab(2).println("else"); out.tab(3).println("this.%s = %s.into(new %s)", columnMember, columnMember, columnType); if (fluentSetters()) out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).override(); out.tab(1).println("public %s %s(%s %s) {", columnSetterReturnType, columnSetter, columnTypeInterface, columnMember); out.tab(2).println("if (%s == null)", columnMember); out.tab(3).println("this.%s = null;", columnMember); if (isUDT) { out.tab(2).println("else"); out.tab(3).println("this.%s = %s.into(new %s());", columnMember, columnMember, columnType); } else if (isUDTArray) { final ArrayDefinition array = database.getArray(column.getType().getSchema(), column.getType().getUserType()); final String componentType = out.ref(getJavaType(array.getElementType(), Mode.POJO)); final String componentTypeInterface = out.ref(getJavaType(array.getElementType(), Mode.INTERFACE)); out.tab(2).println("else {"); out.tab(3).println("this.%s = new %s();", columnMember, ArrayList.class); out.println(); out.tab(3).println("for (%s i : %s)", componentTypeInterface, columnMember); out.tab(4).println("this.%s.add(i.into(new %s()));", columnMember, componentType); out.tab(2).println("}"); } if (fluentSetters()) out.tab(2).println("return this;"); out.tab(1).println("}"); } } } } if (generatePojosEqualsAndHashCode()) { generatePojoEqualsAndHashCode(tableOrUDT, out); } if (generatePojosToString()) { generatePojoToString(tableOrUDT, out); } if (generateInterfaces() && !generateImmutablePojos()) { printFromAndInto(out, tableOrUDT); } if (tableOrUDT instanceof TableDefinition) generatePojoClassFooter((TableDefinition) tableOrUDT, out); else generateUDTPojoClassFooter((UDTDefinition) tableOrUDT, out); out.println("}"); closeJavaWriter(out); } protected void generatePojoEqualsAndHashCode(Definition tableOrUDT, JavaWriter out) { final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO); out.println(); if (scala) { out.tab(1).println("override def equals(obj : Any) : scala.Boolean = {"); out.tab(2).println("if (this == obj)"); out.tab(3).println("return true"); out.tab(2).println("if (obj == null)"); out.tab(3).println("return false"); out.tab(2).println("if (getClass() != obj.getClass())"); out.tab(3).println("return false"); out.tab(2).println("val other = obj.asInstanceOf[%s]", className); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); out.tab(2).println("if (%s == null) {", columnMember); out.tab(3).println("if (other.%s != null)", columnMember); out.tab(4).println("return false"); out.tab(2).println("}"); if (getJavaType(column.getType()).endsWith("[]")) { out.tab(2).println("else if (!%s.equals(%s, other.%s))", Arrays.class, columnMember, columnMember); } else { out.tab(2).println("else if (!%s.equals(other.%s))", columnMember, columnMember); } out.tab(3).println("return false"); } out.tab(2).println("return true"); out.tab(1).println("}"); } else { out.tab(1).println("@Override"); out.tab(1).println("public boolean equals(%s obj) {", Object.class); out.tab(2).println("if (this == obj)"); out.tab(3).println("return true;"); out.tab(2).println("if (obj == null)"); out.tab(3).println("return false;"); out.tab(2).println("if (getClass() != obj.getClass())"); out.tab(3).println("return false;"); out.tab(2).println("final %s other = (%s) obj;", className, className); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); out.tab(2).println("if (%s == null) {", columnMember); out.tab(3).println("if (other.%s != null)", columnMember); out.tab(4).println("return false;"); out.tab(2).println("}"); if (getJavaType(column.getType()).endsWith("[]")) { out.tab(2).println("else if (!%s.equals(%s, other.%s))", Arrays.class, columnMember, columnMember); } else { out.tab(2).println("else if (!%s.equals(other.%s))", columnMember, columnMember); } out.tab(3).println("return false;"); } out.tab(2).println("return true;"); out.tab(1).println("}"); } out.println(); if (scala) { out.tab(1).println("override def hashCode : Int = {"); out.tab(2).println("val prime = 31"); out.tab(2).println("var result = 1"); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); if (getJavaType(column.getType()).endsWith("[]")) { out.tab(2).println("result = prime * result + (if (%s == null) 0 else %s.hashCode(%s))", columnMember, Arrays.class, columnMember); } else { out.tab(2).println("result = prime * result + (if (%s == null) 0 else %s.hashCode())", columnMember, columnMember); } } out.tab(2).println("return result"); out.tab(1).println("}"); } else { out.tab(1).println("@Override"); out.tab(1).println("public int hashCode() {"); out.tab(2).println("final int prime = 31;"); out.tab(2).println("int result = 1;"); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); if (getJavaType(column.getType()).endsWith("[]")) { out.tab(2).println("result = prime * result + ((%s == null) ? 0 : %s.hashCode(%s));", columnMember, Arrays.class, columnMember); } else { out.tab(2).println("result = prime * result + ((%s == null) ? 0 : %s.hashCode());", columnMember, columnMember); } } out.tab(2).println("return result;"); out.tab(1).println("}"); } } protected void generatePojoToString(Definition tableOrUDT, JavaWriter out) { final String className = getStrategy().getJavaClassName(tableOrUDT, Mode.POJO); out.println(); if (scala) { out.tab(1).println("override def toString : String = {"); out.tab(2).println("val sb = new %s(\"%s (\")", StringBuilder.class, className); out.tab(2).println(); String separator = ""; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); final String columnType = getJavaType(column.getType()); if (columnType.equals("scala.Array[scala.Byte]")) { out.tab(2).println("sb%s.append(\"[binary...]\")", separator); } else { out.tab(2).println("sb%s.append(%s)", separator, columnMember); } separator = ".append(\", \")"; } out.tab(2).println(); out.tab(2).println("sb.append(\")\");"); out.tab(2).println("return sb.toString"); out.tab(1).println("}"); } else { out.tab(1).println("@Override"); out.tab(1).println("public String toString() {"); out.tab(2).println("%s sb = new %s(\"%s (\");", StringBuilder.class, StringBuilder.class, className); out.tab(2).println(); String separator = ""; for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { final String columnMember = getStrategy().getJavaMemberName(column, Mode.POJO); final String columnType = getJavaType(column.getType()); final boolean array = columnType.endsWith("[]"); if (array && columnType.equals("byte[]")) { out.tab(2).println("sb%s.append(\"[binary...]\");", separator); } else if (array) { out.tab(2).println("sb%s.append(%s.toString(%s));", separator, Arrays.class, columnMember); } else { out.tab(2).println("sb%s.append(%s);", separator, columnMember); } separator = ".append(\", \")"; } out.tab(2).println(); out.tab(2).println("sb.append(\")\");"); out.tab(2).println("return sb.toString();"); out.tab(1).println("}"); } } private List> getTypedElements(Definition definition) { if (definition instanceof TableDefinition) { return ((TableDefinition) 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); } } /** * Subclasses may override this method to provide POJO class footer code. */ @SuppressWarnings("unused") protected void generatePojoClassFooter(TableDefinition table, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generatePojoClassJavadoc(TableDefinition table, JavaWriter out) { printClassJavadoc(out, table); } 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(getStrategy().getFile(table)); generateTable(table, out); closeJavaWriter(out); } protected void generateTable(TableDefinition table, JavaWriter out) { final SchemaDefinition schema = table.getSchema(); final UniqueKeyDefinition primaryKey = table.getPrimaryKey(); final boolean updatable = generateRelations() && primaryKey != null; 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 interfaces = out.ref(getStrategy().getJavaClassImplements(table, Mode.DEFAULT)); final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2); final String comment = defaultString(table.getComment()); log.info("Generating table", out.file().getName() + " [input=" + table.getInputName() + ", output=" + table.getOutputName() + ", pk=" + (primaryKey != null ? primaryKey.getName() : "N/A") + "]"); printPackage(out, table); if (scala) { out.println("object %s {", className); printSingletonInstance(out, table); out.println("}"); out.println(); } generateTableClassJavadoc(table, out); printClassAnnotations(out, schema); if (scala) { out.println("class %s(alias : String, aliased : %s[%s], parameters : %s[ %s[_] ]) extends %s[%s](alias, %s, aliased, parameters, \"%s\")[[before= with ][separator= with ][%s]] {", className, Table.class, recordType, out.ref("scala.Array"), Field.class, TableImpl.class, recordType, schemaId, escapeString(comment), interfaces); } 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 columnType = out.ref(getJavaType(column.getType())); final String columnTypeRef = getJavaTypeReference(column.getDatabase(), column.getType()); final String columnId = out.ref(getStrategy().getJavaIdentifier(column), colRefSegments(column)); final String columnName = column.getName(); final String columnComment = StringUtils.defaultString(column.getComment()); final List converters = out.ref(list( column.getType().getConverter(), column.getType().getBinding() )); out.tab(1).javadoc("The column %s.%s", column.getQualifiedOutputName(), defaultIfBlank(" " + columnComment, "")); if (scala) { out.tab(1).println("val %s : %s[%s, %s] = createField(\"%s\", %s, \"%s\"[[before=, ][new %s()]])", columnId, TableField.class, recordType, columnType, columnName, columnTypeRef, escapeString(columnComment), converters); } else { String isStatic = generateInstanceFields() ? "" : "static "; String tableRef = generateInstanceFields() ? "this" : out.ref(getStrategy().getJavaIdentifier(table), 2); out.tab(1).println("public %sfinal %s<%s, %s> %s = createField(\"%s\", %s, %s, \"%s\"[[before=, ][new %s()]]);", isStatic, TableField.class, recordType, columnType, columnId, columnName, columnTypeRef, tableRef, escapeString(columnComment), converters); } } if (scala) { out.tab(1).javadoc("Create a %s table reference", table.getQualifiedOutputName()); out.tab(1).println("def this() = {"); out.tab(2).println("this(\"%s\", null, null)", table.getOutputName()); out.tab(1).println("}"); } else { // [#1255] With instance fields, the table constructor may // be public, as tables are no longer singletons if (generateInstanceFields()) { out.tab(1).javadoc("Create a %s table reference", table.getQualifiedOutputName()); out.tab(1).println("public %s() {", className); } else { out.tab(1).javadoc(NO_FURTHER_INSTANCES_ALLOWED); out.tab(1).println("private %s() {", className); } out.tab(2).println("this(\"%s\", null);", table.getOutputName()); out.tab(1).println("}"); } if (scala) { out.tab(1).javadoc("Create an aliased %s table reference", table.getQualifiedOutputName()); out.tab(1).println("def this(alias : %s) = {", String.class); out.tab(2).println("this(alias, %s, null)", tableId); out.tab(1).println("}"); } // [#117] With instance fields, it makes sense to create a // type-safe table alias // [#1255] With instance fields, the table constructor may // be public, as tables are no longer singletons else if (generateInstanceFields()) { out.tab(1).javadoc("Create an aliased %s table reference", table.getQualifiedOutputName()); out.tab(1).println("public %s(%s alias) {", className, String.class); out.tab(2).println("this(alias, %s);", tableId); out.tab(1).println("}"); } out.println(); if (scala) { out.tab(1).println("private def this(alias : %s, aliased : %s[%s]) = {", String.class, Table.class, recordType); if (table.isTableValuedFunction()) out.tab(2).println("this(alias, aliased, new %s[ %s[_] ](%s))", out.ref("scala.Array"), Field.class, table.getParameters().size()); else out.tab(2).println("this(alias, aliased, null)"); out.tab(1).println("}"); } else { out.tab(1).println("private %s(%s alias, %s<%s> aliased) {", className, String.class, Table.class, recordType); if (table.isTableValuedFunction()) out.tab(2).println("this(alias, aliased, new %s[%s]);", Field.class, table.getParameters().size()); else out.tab(2).println("this(alias, aliased, null);"); out.tab(1).println("}"); out.println(); out.tab(1).println("private %s(%s alias, %s<%s> aliased, %s[] parameters) {", className, String.class, Table.class, recordType, Field.class); out.tab(2).println("super(alias, null, aliased, parameters, \"%s\");", escapeString(comment)); out.tab(1).println("}"); } if (scala) { out.println(); out.tab(1).println("override def getSchema : %s = %s", Schema.class, schemaId); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s getSchema() {", Schema.class); out.tab(2).println("return %s;", schemaId); out.tab(1).println("}"); } // Add primary / unique / foreign key information if (generateRelations()) { IdentityDefinition identity = table.getIdentity(); // The identity column if (identity != null) { final String identityType = out.ref(getJavaType(identity.getColumn().getType())); final String identityFullId = out.ref(getStrategy().getFullJavaIdentifier(identity), 2); if (scala) { out.println(); out.tab(1).println("override def getIdentity : %s[%s, %s] = {", Identity.class, recordType, identityType); out.tab(2).println("%s", identityFullId); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s, %s> getIdentity() {", Identity.class, recordType, identityType); out.tab(2).println("return %s;", identityFullId); out.tab(1).println("}"); } } // The primary / main unique key if (primaryKey != null) { final String keyFullId = out.ref(getStrategy().getFullJavaIdentifier(primaryKey), 2); if (scala) { out.println(); out.tab(1).println("override def getPrimaryKey : %s[%s] = {", UniqueKey.class, recordType); out.tab(2).println("%s", keyFullId); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s> getPrimaryKey() {", UniqueKey.class, recordType); out.tab(2).println("return %s;", keyFullId); out.tab(1).println("}"); } } // The remaining unique keys List uniqueKeys = table.getUniqueKeys(); if (uniqueKeys.size() > 0) { final List keyFullIds = out.ref(getStrategy().getFullJavaIdentifiers(uniqueKeys), 2); if (scala) { out.println(); out.tab(1).println("override def getKeys : %s[ %s[%s] ] = {", List.class, UniqueKey.class, recordType); out.tab(2).println("return %s.asList[ %s[%s] ]([[%s]])", Arrays.class, UniqueKey.class, recordType, keyFullIds); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s<%s>> getKeys() {", List.class, UniqueKey.class, recordType); out.tab(2).println("return %s.<%s<%s>>asList([[%s]]);", Arrays.class, UniqueKey.class, recordType, keyFullIds); out.tab(1).println("}"); } } // Foreign keys List foreignKeys = table.getForeignKeys(); if (foreignKeys.size() > 0) { final List keyFullIds = out.ref(getStrategy().getFullJavaIdentifiers(foreignKeys), 2); if (scala) { out.println(); out.tab(1).println("override def getReferences : %s[ %s[%s, _] ] = {", List.class, ForeignKey.class, recordType); out.tab(2).println("return %s.asList[ %s[%s, _] ]([[%s]])", Arrays.class, ForeignKey.class, recordType, keyFullIds); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s<%s, ?>> getReferences() {", List.class, ForeignKey.class, recordType); out.tab(2).println("return %s.<%s<%s, ?>>asList([[%s]]);", Arrays.class, ForeignKey.class, recordType, keyFullIds); out.tab(1).println("}"); } } } // [#1596] Updatable tables can provide fields for optimistic locking // if properly configured if (updatable) { patternLoop: 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 columnType = out.ref(getJavaType(column.getType())); final String columnId = getStrategy().getJavaIdentifier(column); if (scala) { out.println(); out.tab(1).println("override def getRecordVersion : %s[%s, %s] = {", TableField.class, recordType, columnType); out.tab(2).println("%s", columnId); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s, %s> getRecordVersion() {", TableField.class, recordType, columnType); out.tab(2).println("return %s;", columnId); out.tab(1).println("}"); } // Avoid generating this method twice break patternLoop; } } } 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 columnType = out.ref(getJavaType(column.getType())); final String columnId = getStrategy().getJavaIdentifier(column); if (scala) { out.println(); out.tab(1).println("override def getRecordTimestamp : %s[%s, %s] = {", TableField.class, recordType, columnType); out.tab(2).println("%s", columnId); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s<%s, %s> getRecordTimestamp() {", TableField.class, recordType, columnType); out.tab(2).println("return %s;", columnId); out.tab(1).println("}"); } // Avoid generating this method twice break timestampLoop; } } } } if (scala) { out.println(); out.tab(1).println("override def as(alias : %s) : %s = {", String.class, className); if (table.isTableValuedFunction()) out.tab(2).println("new %s(alias, this, parameters)", className); else out.tab(2).println("new %s(alias, this)", className); out.tab(1).println("}"); } // [#117] With instance fields, it makes sense to create a // type-safe table alias else if (generateInstanceFields()) { out.tab(1).overrideInherit(); out.tab(1).println("public %s as(%s alias) {", className, String.class); if (table.isTableValuedFunction()) out.tab(2).println("return new %s(alias, this, parameters);", className); else out.tab(2).println("return new %s(alias, this);", className); out.tab(1).println("}"); } if (scala) { out.tab(1).javadoc("Rename this table"); out.tab(1).println("def rename(name : %s) : %s = {", String.class, className); if (table.isTableValuedFunction()) out.tab(2).println("new %s(name, null, parameters)", className); else out.tab(2).println("new %s(name, null)", className); out.tab(1).println("}"); } // [#2921] With instance fields, tables can be renamed. else if (generateInstanceFields()) { out.tab(1).javadoc("Rename this table"); out.tab(1).println("public %s rename(%s name) {", className, String.class); if (table.isTableValuedFunction()) out.tab(2).println("return new %s(name, null, parameters);", className); else out.tab(2).println("return new %s(name, null);", className); out.tab(1).println("}"); } // [#1070] Table-valued functions should generate an additional set of call() methods if (table.isTableValuedFunction()) { for (boolean parametersAsField : new boolean[] { false, true }) { // Don't overload no-args call() methods if (parametersAsField && table.getParameters().size() == 0) break; out.tab(1).javadoc("Call this table-valued function"); if (scala) { out.tab(1).print("def call("); printParameterDeclarations(out, table, parametersAsField); out.println(") : %s = {", className); out.tab(2).print("return new %s(getName(), null, %s(", className, out.ref("scala.Array")); String separator = ""; for (ParameterDefinition parameter : table.getParameters()) { out.print(separator); if (parametersAsField) { out.print("%s", getStrategy().getJavaMemberName(parameter)); } else { out.print("%s.value(%s)", DSL.class, getStrategy().getJavaMemberName(parameter)); } separator = ", "; } out.println("));"); out.tab(1).println("}"); } else { out.tab(1).print("public %s call(", className); printParameterDeclarations(out, table, parametersAsField); out.println(") {"); out.tab(2).print("return new %s(getName(), null, new %s[] { ", className, Field.class); String separator = ""; for (ParameterDefinition parameter : table.getParameters()) { out.print(separator); if (parametersAsField) { out.print("%s", getStrategy().getJavaMemberName(parameter)); } else { out.print("%s.val(%s)", DSL.class, getStrategy().getJavaMemberName(parameter)); } separator = ", "; } out.println(" });"); out.tab(1).println("}"); } } } generateTableClassFooter(table, out); out.println("}"); closeJavaWriter(out); } private String escapeString(String comment) { // [#3450] Escape also the escape sequence, among other things that break Java strings. return comment.replace("\\", "\\\\") .replace("\"", "\\\"") .replace("\n", "\\n") .replace("\r", "\\r"); } /** * Subclasses may override this method to provide table class footer code. */ @SuppressWarnings("unused") protected void generateTableClassFooter(TableDefinition table, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateTableClassJavadoc(TableDefinition table, JavaWriter out) { printClassJavadoc(out, table); } protected void generateSequences(SchemaDefinition schema) { log.info("Generating sequences"); JavaWriter out = newJavaWriter(new File(getStrategy().getFile(schema).getParentFile(), "Sequences.java")); printPackage(out, schema); printClassJavadoc(out, "Convenience access to all sequences in " + schema.getOutputName()); printClassAnnotations(out, schema); if (scala) out.println("object Sequences {"); else out.println("public class Sequences {"); for (SequenceDefinition sequence : database.getSequences(schema)) { final String seqType = out.ref(getJavaType(sequence.getType())); 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()); out.tab(1).javadoc("The sequence %s", sequence.getQualifiedOutputName()); if (scala) out.tab(1).println("val %s : %s[%s] = new %s[%s](\"%s\", %s, %s)", seqId, Sequence.class, seqType, SequenceImpl.class, seqType, seqName, schemaId, typeRef); else out.tab(1).println("public static final %s<%s> %s = new %s<%s>(\"%s\", %s, %s);", Sequence.class, seqType, seqId, SequenceImpl.class, seqType, seqName, schemaId, typeRef); } out.println("}"); closeJavaWriter(out); watch.splitInfo("Sequences generated"); } protected void generateCatalog(CatalogDefinition catalog) { JavaWriter out = newJavaWriter(getStrategy().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 catalogName = catalog.getQualifiedOutputName(); final String catalogId = getStrategy().getJavaIdentifier(catalog); final String className = getStrategy().getJavaClassName(catalog); final List interfaces = out.ref(getStrategy().getJavaClassImplements(catalog, Mode.DEFAULT)); printPackage(out, catalog); if (scala) { out.println("object %s {", className); out.tab(1).javadoc("The reference instance of %s", catalogName); out.tab(1).println("val %s = new %s", catalogId, className); out.println("}"); out.println(); } generateCatalogClassJavadoc(catalog, out); printClassAnnotations(out, null, catalog); if (scala) { out.println("class %s extends %s(\"%s\")[[before= with ][separator= with ][%s]] {", className, CatalogImpl.class, catalog.getOutputName(), interfaces); } else { out.println("public class %s extends %s[[before= implements ][%s]] {", className, CatalogImpl.class, interfaces); out.printSerial(); out.tab(1).javadoc("The reference instance of %s", catalogName); out.tab(1).println("public static final %s %s = new %s();", className, catalogId, className); } if (generateGlobalObjectReferences() && generateGlobalSchemaReferences()) { for (SchemaDefinition schema : catalog.getSchemata()) { final String schemaClassName = out.ref(getStrategy().getFullJavaClassName(schema)); final String schemaId = getStrategy().getJavaIdentifier(schema); final String schemaFullId = getStrategy().getFullJavaIdentifier(schema); final String schemaComment = !StringUtils.isBlank(schema.getComment()) ? schema.getComment() : "The schema " + schema.getQualifiedOutputName() + "."; out.tab(1).javadoc(schemaComment); if (scala) out.tab(1).println("val %s = %s", schemaId, schemaFullId); else out.tab(1).println("public final %s %s = %s;", schemaClassName, schemaId, schemaFullId); } } if (scala) ; else { out.tab(1).javadoc(NO_FURTHER_INSTANCES_ALLOWED); out.tab(1).println("private %s() {", className); out.tab(2).println("super(\"%s\");", catalog.getOutputName()); out.tab(1).println("}"); } printReferences(out, database.getSchemata(catalog), Schema.class, false); generateCatalogClassFooter(catalog, out); out.println("}"); } /** * Subclasses may override this method to provide catalog class footer code. */ @SuppressWarnings("unused") protected void generateCatalogClassFooter(CatalogDefinition schema, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateCatalogClassJavadoc(CatalogDefinition schema, JavaWriter out) { printClassJavadoc(out, schema); } protected void generateSchema(SchemaDefinition schema) { JavaWriter out = newJavaWriter(getStrategy().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 schemaName = schema.getQualifiedOutputName(); final String schemaId = getStrategy().getJavaIdentifier(schema); final String className = getStrategy().getJavaClassName(schema); final List interfaces = out.ref(getStrategy().getJavaClassImplements(schema, Mode.DEFAULT)); printPackage(out, schema); if (scala) { out.println("object %s {", className); out.tab(1).javadoc("The reference instance of %s", schemaName); out.tab(1).println("val %s = new %s", schemaId, className); out.println("}"); out.println(); } generateSchemaClassJavadoc(schema, out); printClassAnnotations(out, schema); if (scala) { out.println("class %s extends %s(\"%s\", %s)[[before= with ][separator= with ][%s]] {", className, SchemaImpl.class, schema.getOutputName(), catalogId, interfaces); } else { out.println("public class %s extends %s[[before= implements ][%s]] {", className, SchemaImpl.class, interfaces); out.printSerial(); out.tab(1).javadoc("The reference instance of %s", schemaName); out.tab(1).println("public static final %s %s = new %s();", className, schemaId, className); if (generateGlobalObjectReferences() && generateGlobalTableReferences()) { for (TableDefinition table : schema.getTables()) { final String tableClassName = out.ref(getStrategy().getFullJavaClassName(table)); final String tableId = getStrategy().getJavaIdentifier(table); final String tableFullId = getStrategy().getFullJavaIdentifier(table); final String tableComment = !StringUtils.isBlank(table.getComment()) ? table.getComment() : "The table " + table.getQualifiedOutputName() + "."; out.tab(1).javadoc(tableComment); if (scala) out.tab(1).println("val %s = %s", tableId, tableFullId); else out.tab(1).println("public final %s %s = %s;", tableClassName, tableId, tableFullId); // [#3797] Table-valued functions generate two different literals in // globalObjectReferences if (table.isTableValuedFunction()) { printTableValuedFunction(out, table, getStrategy().getJavaIdentifier(table)); } } } out.tab(1).javadoc(NO_FURTHER_INSTANCES_ALLOWED); out.tab(1).println("private %s() {", className); out.tab(2).println("super(\"%s\", null);", schema.getOutputName()); out.tab(1).println("}"); } out.println(); if (scala) { out.tab(1).println("override def getCatalog : %s = %s", Catalog.class, catalogId); } else { out.tab(1).overrideInherit(); out.tab(1).println("public %s getCatalog() {", Catalog.class); out.tab(2).println("return %s;", catalogId); out.tab(1).println("}"); } // [#2255] Avoid referencing sequence literals, if they're not generated if (generateGlobalObjectReferences() && generateGlobalSequenceReferences()) { printReferences(out, database.getSequences(schema), Sequence.class, true); } printReferences(out, database.getTables(schema), Table.class, true); printReferences(out, database.getUDTs(schema), UDT.class, true); generateSchemaClassFooter(schema, out); out.println("}"); } /** * Subclasses may override this method to provide schema class footer code. */ @SuppressWarnings("unused") protected void generateSchemaClassFooter(SchemaDefinition schema, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateSchemaClassJavadoc(SchemaDefinition schema, JavaWriter out) { printClassJavadoc(out, schema); } protected void printFromAndInto(JavaWriter out, TableDefinition table) { printFromAndInto(out, (Definition) table); } private void printFromAndInto(JavaWriter out, Definition tableOrUDT) { String qualified = out.ref(getStrategy().getFullJavaClassName(tableOrUDT, Mode.INTERFACE)); out.tab(1).header("FROM and INTO"); out.tab(1).overrideInherit(); out.tab(1).println("public void from(%s from) {", qualified); for (TypedElementDefinition column : getTypedElements(tableOrUDT)) { String setter = getStrategy().getJavaSetterName(column, Mode.INTERFACE); String getter = getStrategy().getJavaGetterName(column, Mode.INTERFACE); if (scala) out.tab(2).println("%s(from.%s)", setter, getter); else out.tab(2).println("%s(from.%s());", setter, getter); } out.tab(1).println("}"); if (scala) { out.tab(1).println("public E into(E into) {", qualified); out.tab(2).println("into.from(this)"); out.tab(2).println("return into"); out.tab(1).println("}"); } else { out.tab(1).overrideInherit(); out.tab(1).println("public E into(E into) {", qualified); out.tab(2).println("into.from(this);"); out.tab(2).println("return into;"); out.tab(1).println("}"); } } protected void printReferences(JavaWriter out, List definitions, Class type, boolean isGeneric) { if (out != null && !definitions.isEmpty()) { final String generic = isGeneric ? (scala ? "[_]" : "") : ""; final List references = out.ref(getStrategy().getFullJavaIdentifiers(definitions), 2); out.println(); if (scala) { out.tab(1).println("override def get%ss : %s[%s%s] = {", type.getSimpleName(), List.class, type, generic); out.tab(2).println("val result = new %s[%s%s]", ArrayList.class, type, generic); for (int i = 0; i < definitions.size(); i += INITIALISER_SIZE) { out.tab(2).println("result.addAll(get%ss%s)", type.getSimpleName(), i / INITIALISER_SIZE); } out.tab(2).println("result"); out.tab(1).println("}"); } else { out.tab(1).override(); out.tab(1).println("public final %s<%s%s> get%ss() {", List.class, type, generic, type.getSimpleName()); out.tab(2).println("%s result = new %s();", List.class, ArrayList.class); for (int i = 0; i < definitions.size(); i += INITIALISER_SIZE) { out.tab(2).println("result.addAll(get%ss%s());", type.getSimpleName(), i / INITIALISER_SIZE); } out.tab(2).println("return result;"); out.tab(1).println("}"); } for (int i = 0; i < definitions.size(); i += INITIALISER_SIZE) { out.println(); if (scala) { out.tab(1).println("private def get%ss%s() : %s[%s%s] = {", type.getSimpleName(), i / INITIALISER_SIZE, List.class, type, generic); out.tab(2).println("return %s.asList[%s%s]([[before=\n\t\t\t][separator=,\n\t\t\t][%s]])", Arrays.class, type, generic, references.subList(i, Math.min(i + INITIALISER_SIZE, references.size()))); out.tab(1).println("}"); } else { out.tab(1).println("private final %s<%s%s> get%ss%s() {", List.class, type, generic, type.getSimpleName(), i / INITIALISER_SIZE); out.tab(2).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 + INITIALISER_SIZE, references.size()))); out.tab(1).println("}"); } } } } protected void printTableJPAAnnotation(JavaWriter out, TableDefinition table) { SchemaDefinition schema = table.getSchema(); if (generateJPAAnnotations()) { out.println("@%s", out.ref("javax.persistence.Entity")); out.print("@%s(name = \"", out.ref("javax.persistence.Table")); out.print(table.getName().replace("\"", "\\\"")); out.print("\""); if (!schema.isDefaultSchema()) { out.print(", schema = \""); out.print(schema.getOutputName().replace("\"", "\\\"")); out.print("\""); } StringBuilder sb = new StringBuilder(); String glue1 = "\n"; for (UniqueKeyDefinition uk : table.getUniqueKeys()) { // Single-column keys are annotated on the column itself if (uk.getKeyColumns().size() > 1) { sb.append(glue1); sb.append("\t") .append(scala ? "new " : "@") .append(out.ref("javax.persistence.UniqueConstraint")).append("(columnNames = ").append(scala ? "Array(" : "{"); String glue2 = ""; for (ColumnDefinition column : uk.getKeyColumns()) { sb.append(glue2); sb.append("\""); sb.append(column.getName().replace("\"", "\\\"")); sb.append("\""); glue2 = ", "; } sb.append(scala ? ")" : "}").append(")"); glue1 = ",\n"; } } if (sb.length() > 0) { out.print(", uniqueConstraints = ") .print(scala ? "Array(" : "{"); out.println(sb.toString()); out.print(scala ? ")" : "}"); } out.println(")"); } } protected void printColumnJPAAnnotation(JavaWriter out, ColumnDefinition column) { if (generateJPAAnnotations()) { UniqueKeyDefinition pk = column.getPrimaryKey(); List uks = column.getUniqueKeys(); if (pk != null) { if (pk.getKeyColumns().size() == 1) { out.tab(1).println("@%s", out.ref("javax.persistence.Id")); if (pk.getKeyColumns().get(0).isIdentity()) out.tab(1).println("@%s(strategy = %s.IDENTITY)", out.ref("javax.persistence.GeneratedValue"), out.ref("javax.persistence.GenerationType")); } } String unique = ""; for (UniqueKeyDefinition uk : uks) { if (uk.getKeyColumns().size() == 1) { unique = ", unique = true"; break; } } String nullable = ""; if (!column.getType().isNullable()) { nullable = ", nullable = false"; } String length = ""; String precision = ""; String scale = ""; if (column.getType().getLength() > 0) { length = ", length = " + column.getType().getLength(); } else if (column.getType().getPrecision() > 0) { precision = ", precision = " + column.getType().getPrecision(); if (column.getType().getScale() > 0) { scale = ", scale = " + column.getType().getScale(); } } out.print("\t@%s(name = \"", out.ref("javax.persistence.Column")); out.print(column.getName().replace("\"", "\\\"")); out.print("\""); out.print(unique); out.print(nullable); out.print(length); out.print(precision); out.print(scale); out.println(")"); } } /** * @deprecated - This method is no longer used by the generator. */ @Deprecated protected void printColumnValidationAnnotation(JavaWriter out, ColumnDefinition column) { printValidationAnnotation(out, column); } private void printValidationAnnotation(JavaWriter out, TypedElementDefinition column) { if (generateValidationAnnotations()) { DataTypeDefinition type = column.getType(); // [#5128] defaulted columns are nullable in Java if (!column.getType().isNullable() && !column.getType().isDefaulted()) out.tab(1).println("@%s", out.ref("javax.validation.constraints.NotNull")); if ("java.lang.String".equals(getJavaType(type))) { int length = type.getLength(); if (length > 0) out.tab(1).println("@%s(max = %s)", out.ref("javax.validation.constraints.Size"), length); } } } @SuppressWarnings("unused") protected void generateRoutine(SchemaDefinition schema, RoutineDefinition routine) { JavaWriter out = newJavaWriter(getStrategy().getFile(routine)); log.info("Generating routine", out.file().getName()); 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 returnType = (routine.getReturnValue() == null) ? Void.class.getName() : out.ref(getJavaType(routine.getReturnType())); final List returnTypeRef = list((routine.getReturnValue() != null) ? getJavaTypeReference(database, routine.getReturnType()) : null); final List returnConverterType = out.ref(list( (routine.getReturnValue() != null) ? routine.getReturnType().getConverter() : null, (routine.getReturnValue() != null) ? routine.getReturnType().getBinding() : null )); final List interfaces = out.ref(getStrategy().getJavaClassImplements(routine, Mode.DEFAULT)); final String schemaId = out.ref(getStrategy().getFullJavaIdentifier(schema), 2); final List 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 paramType = out.ref(getJavaType(parameter.getType())); final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType()); final String paramId = out.ref(getStrategy().getJavaIdentifier(parameter), 2); final String paramName = parameter.getName(); final String paramComment = StringUtils.defaultString(parameter.getComment()); final String isDefaulted = parameter.isDefaulted() ? "true" : "false"; final String isUnnamed = parameter.isUnnamed() ? "true" : "false"; final List converters = out.ref(list( parameter.getType().getConverter(), parameter.getType().getBinding() )); out.tab(1).javadoc("The parameter %s.%s", parameter.getQualifiedOutputName(), defaultIfBlank(" " + paramComment, "")); out.tab(1).println("val %s : %s[%s] = %s.createParameter(\"%s\", %s, %s, %s[[before=, ][new %s]])", paramId, Parameter.class, paramType, AbstractRoutine.class, paramName, paramTypeRef, isDefaulted, isUnnamed, converters); } out.println("}"); out.println(); } generateRoutineClassJavadoc(routine, out); printClassAnnotations(out, schema); if (scala) { out.println("class %s extends %s[%s](\"%s\", %s[[before=, ][%s]][[before=, ][%s]][[before=, ][new %s()]])[[before= with ][separator= with ][%s]] {", className, AbstractRoutine.class, returnType, routine.getName(), schemaId, packageId, returnTypeRef, returnConverterType, interfaces); } else { out.println("public class %s extends %s<%s>[[before= implements ][%s]] {", className, AbstractRoutine.class, returnType, interfaces); out.printSerial(); for (ParameterDefinition parameter : routine.getAllParameters()) { final String paramType = out.ref(getJavaType(parameter.getType())); final String paramTypeRef = getJavaTypeReference(parameter.getDatabase(), parameter.getType()); final String paramId = out.ref(getStrategy().getJavaIdentifier(parameter), 2); final String paramName = parameter.getName(); final String paramComment = StringUtils.defaultString(parameter.getComment()); final String isDefaulted = parameter.isDefaulted() ? "true" : "false"; final String isUnnamed = parameter.isUnnamed() ? "true" : "false"; final List converters = out.ref(list( parameter.getType().getConverter(), parameter.getType().getBinding() )); out.tab(1).javadoc("The parameter %s.%s", parameter.getQualifiedOutputName(), defaultIfBlank(" " + paramComment, "")); out.tab(1).println("public static final %s<%s> %s = createParameter(\"%s\", %s, %s, %s[[before=, ][new %s()]]);", Parameter.class, paramType, paramId, paramName, paramTypeRef, isDefaulted, isUnnamed, converters); } } if (scala) { out.tab(1).println("{"); } else { out.tab(1).javadoc("Create a new routine call instance"); out.tab(1).println("public %s() {", className); out.tab(2).println("super(\"%s\", %s[[before=, ][%s]][[before=, ][%s]][[before=, ][new %s()]]);", routine.getName(), schemaId, packageId, returnTypeRef, returnConverterType); if (routine.getAllParameters().size() > 0) { out.println(); } } for (ParameterDefinition parameter : routine.getAllParameters()) { final String paramId = getStrategy().getJavaIdentifier(parameter); if (parameter.equals(routine.getReturnValue())) { if (scala) out.tab(2).println("setReturnParameter(%s.%s)", className, paramId); else out.tab(2).println("setReturnParameter(%s);", paramId); } else if (routine.getInParameters().contains(parameter)) { if (routine.getOutParameters().contains(parameter)) { if (scala) out.tab(2).println("addInOutParameter(%s.%s)", className, paramId); else out.tab(2).println("addInOutParameter(%s);", paramId); } else { if (scala) out.tab(2).println("addInParameter(%s.%s)", className, paramId); else out.tab(2).println("addInParameter(%s);", paramId); } } else { if (scala) out.tab(2).println("addOutParameter(%s.%s)", className, paramId); else out.tab(2).println("addOutParameter(%s);", paramId); } } if (routine.getOverload() != null) { if (scala) out.tab(2).println("setOverloaded(true)"); else out.tab(2).println("setOverloaded(true);"); } out.tab(1).println("}"); for (ParameterDefinition parameter : routine.getInParameters()) { final String setterReturnType = fluentSetters() ? className : (scala ? "Unit" : "void"); final String setter = getStrategy().getJavaSetterName(parameter, Mode.DEFAULT); final String numberValue = parameter.getType().isGenericNumberType() ? "Number" : "Value"; final String numberField = parameter.getType().isGenericNumberType() ? "Number" : "Field"; final String paramId = getStrategy().getJavaIdentifier(parameter); final String paramName = "value".equals(paramId) ? "value_" : "value"; out.tab(1).javadoc("Set the %s parameter IN value to the routine", parameter.getOutputName()); if (scala) { out.tab(1).println("def %s(%s : %s) : Unit = {", setter, paramName, refNumberType(out, parameter.getType())); out.tab(2).println("set%s(%s.%s, %s)", numberValue, className, paramId, paramName); out.tab(1).println("}"); } else { out.tab(1).println("public void %s(%s %s) {", setter, refNumberType(out, parameter.getType()), paramName); out.tab(2).println("set%s(%s, %s);", numberValue, paramId, paramName); out.tab(1).println("}"); } if (routine.isSQLUsable()) { out.tab(1).javadoc("Set the %s parameter to the function to be used with a {@link org.jooq.Select} statement", parameter.getOutputName()); if (scala) { out.tab(1).println("def %s(field : %s[%s]) : %s = {", setter, Field.class, refExtendsNumberType(out, parameter.getType()), setterReturnType); out.tab(2).println("set%s(%s.%s, field)", numberField, className, paramId); if (fluentSetters()) out.tab(2).println("this"); out.tab(1).println("}"); } else { out.tab(1).println("public %s %s(%s<%s> field) {", setterReturnType, setter, Field.class, refExtendsNumberType(out, parameter.getType())); out.tab(2).println("set%s(%s, field);", numberField, paramId); if (fluentSetters()) out.tab(2).println("return this;"); out.tab(1).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 paramType = out.ref(getJavaType(parameter.getType())); final String paramGetter = getStrategy().getJavaGetterName(parameter, Mode.DEFAULT); final String paramId = getStrategy().getJavaIdentifier(parameter); out.tab(1).javadoc("Get the %s parameter OUT value from the routine", paramName); if (scala) { out.tab(1).println("def %s : %s = {", paramGetter, paramType); out.tab(2).println("get(%s.%s)", className, paramId); out.tab(1).println("}"); } else { out.tab(1).println("public %s %s() {", paramType, paramGetter); out.tab(2).println("return get(%s);", paramId); out.tab(1).println("}"); } } } generateRoutineClassFooter(routine, out); out.println("}"); } /** * Subclasses may override this method to provide routine class footer code. */ @SuppressWarnings("unused") protected void generateRoutineClassFooter(RoutineDefinition routine, JavaWriter out) {} /** * Subclasses may override this method to provide their own Javadoc. */ protected void generateRoutineClassJavadoc(RoutineDefinition routine, JavaWriter out) { printClassJavadoc(out, routine); } protected void printConvenienceMethodFunctionAsField(JavaWriter out, RoutineDefinition function, boolean parametersAsField) { // [#281] - Java can't handle more than 255 method parameters if (function.getInParameters().size() > 254) { log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method."); return; } // Do not generate separate convenience methods, if there are no IN // parameters. They would have the same signature and no additional // meaning if (parametersAsField && function.getInParameters().isEmpty()) { return; } final String className = out.ref(getStrategy().getFullJavaClassName(function)); final String localVar = disambiguateJavaMemberName(function.getInParameters(), "f"); out.tab(1).javadoc("Get %s as a field.", function.getQualifiedOutputName()); if (scala) out.tab(1).print("def %s(", getStrategy().getJavaMethodName(function, Mode.DEFAULT)); else out.tab(1).print("public static %s<%s> %s(", function.isAggregate() ? AggregateFunction.class : Field.class, out.ref(getJavaType(function.getReturnType())), getStrategy().getJavaMethodName(function, Mode.DEFAULT)); String separator = ""; for (ParameterDefinition parameter : function.getInParameters()) { out.print(separator); if (scala) { out.print("%s : ", getStrategy().getJavaMemberName(parameter)); if (parametersAsField) { out.print("%s[%s]", Field.class, refExtendsNumberType(out, parameter.getType())); } else { out.print(refNumberType(out, parameter.getType())); } } else { if (parametersAsField) { out.print("%s<%s>", Field.class, refExtendsNumberType(out, parameter.getType())); } else { out.print(refNumberType(out, parameter.getType())); } out.print(" %s", getStrategy().getJavaMemberName(parameter)); } separator = ", "; } if (scala) { out.println(") : %s[%s] = {", function.isAggregate() ? AggregateFunction.class : Field.class, out.ref(getJavaType(function.getReturnType()))); out.tab(2).println("val %s = new %s", localVar, className); } else { out.println(") {"); out.tab(2).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); if (scala) out.tab(2).println("%s.%s(%s)", localVar, paramSetter, paramMember); else out.tab(2).println("%s.%s(%s);", localVar, paramSetter, paramMember); } out.println(); if (scala) out.tab(2).println("return %s.as%s", localVar, function.isAggregate() ? "AggregateFunction" : "Field"); else out.tab(2).println("return %s.as%s();", localVar, function.isAggregate() ? "AggregateFunction" : "Field"); out.tab(1).println("}"); } protected void printConvenienceMethodTableValuedFunctionAsField(JavaWriter out, TableDefinition function, boolean parametersAsField, String javaMethodName) { // [#281] - Java can't handle more than 255 method parameters if (function.getParameters().size() > 254) { log.warn("Too many parameters", "Function " + function + " has more than 254 in parameters. Skipping generation of convenience method."); return; } // Do not generate separate convenience methods, if there are no IN // parameters. They would have the same signature and no additional // meaning if (parametersAsField && function.getParameters().isEmpty()) { return; } final String className = out.ref(getStrategy().getFullJavaClassName(function)); out.tab(1).javadoc("Get %s as a table.", function.getQualifiedOutputName()); if (scala) out.tab(1).print("def %s(", javaMethodName); else out.tab(1).print("public static %s %s(", className, javaMethodName); printParameterDeclarations(out, function, parametersAsField); if (scala) { out.println(") : %s = {", className); out.tab(2).print("%s.call(", out.ref(getStrategy().getFullJavaIdentifier(function), 2)); } else { out.println(") {"); out.tab(2).print("return %s.call(", out.ref(getStrategy().getFullJavaIdentifier(function), 2)); } String separator = ""; for (ParameterDefinition parameter : function.getParameters()) { out.print(separator); out.print("%s", getStrategy().getJavaMemberName(parameter)); separator = ", "; } if (scala) out.println(")"); else out.println(");"); out.tab(1).println("}"); } private void printParameterDeclarations(JavaWriter out, TableDefinition function, boolean parametersAsField) { String sep1 = ""; for (ParameterDefinition parameter : function.getParameters()) { out.print(sep1); if (scala) { out.print("%s : ", getStrategy().getJavaMemberName(parameter)); if (parametersAsField) { out.print("%s[%s]", Field.class, refExtendsNumberType(out, parameter.getType())); } else { out.print(refNumberType(out, parameter.getType())); } } else { if (parametersAsField) { out.print("%s<%s>", Field.class, refExtendsNumberType(out, parameter.getType())); } else { out.print(refNumberType(out, parameter.getType())); } out.print(" %s", getStrategy().getJavaMemberName(parameter)); } sep1 = ", "; } } private String disambiguateJavaMemberName(Collection definitions, String defaultName) { // [#2502] - Some name mangling in the event of procedure arguments // called "configuration" Set 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) { // [#281] - Java can't handle more than 255 method parameters 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 functionType = out.ref(getJavaType(function.getReturnType())); final String methodName = getStrategy().getJavaMethodName(function, Mode.DEFAULT); // [#3456] Local variables should not collide with actual function arguments final String configurationArgument = disambiguateJavaMemberName(function.getInParameters(), "configuration"); final String localVar = disambiguateJavaMemberName(function.getInParameters(), "f"); out.tab(1).javadoc("Call %s", functionName); if (scala) out.tab(1).print("def %s(", methodName); else out.tab(1).print("public %s%s %s(", !instance ? "static " : "", functionType, methodName); String glue = ""; if (!instance) { if (scala) out.print("%s : %s", configurationArgument, Configuration.class); else out.print("%s %s", Configuration.class, configurationArgument); glue = ", "; } for (ParameterDefinition parameter : function.getInParameters()) { // Skip SELF parameter if (instance && parameter.equals(function.getInParameters().get(0))) { continue; } final String paramType = refNumberType(out, parameter.getType()); final String paramMember = getStrategy().getJavaMemberName(parameter); if (scala) out.print("%s%s : %s", glue, paramMember, paramType); else out.print("%s%s %s", glue, paramType, paramMember); glue = ", "; } if (scala) { out.println(") : %s = {", functionType); out.tab(2).println("val %s = new %s()", localVar, className); } else { out.println(") {"); out.tab(2).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); if (scala) out.tab(2).println("%s.%s(%s)", localVar, paramSetter, paramMember); else out.tab(2).println("%s.%s(%s);", localVar, paramSetter, paramMember); } out.println(); if (scala) out.tab(2).println("%s.execute(%s)", localVar, instance ? "configuration()" : configurationArgument); else out.tab(2).println("%s.execute(%s);", localVar, instance ? "configuration()" : configurationArgument); // TODO [#956] Find a way to register "SELF" as OUT parameter // in case this is a UDT instance (member) function if (scala) out.tab(2).println("%s.getReturnValue", localVar); else out.tab(2).println("return %s.getReturnValue();", localVar); out.tab(1).println("}"); } protected void printConvenienceMethodProcedure(JavaWriter out, RoutineDefinition procedure, boolean instance) { // [#281] - Java can't handle more than 255 method parameters 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 outParams = list(procedure.getReturnValue(), procedure.getOutParameters()); out.tab(1).javadoc("Call %s", procedure.getQualifiedOutputName()); if (scala) { out.tab(1).print("def "); } else { out.tab(1).print("public "); if (!instance) { out.print("static "); } if (outParams.size() == 0) { out.print("void "); } else if (outParams.size() == 1) { out.print(out.ref(getJavaType(outParams.get(0).getType()))); out.print(" "); } else { out.print(className + " "); } } out.print(getStrategy().getJavaMethodName(procedure, Mode.DEFAULT)); out.print("("); String glue = ""; if (!instance) { if (scala) out.print("%s : %s", configurationArgument, Configuration.class); else out.print("%s %s", Configuration.class, configurationArgument); glue = ", "; } for (ParameterDefinition parameter : procedure.getInParameters()) { // Skip SELF parameter if (instance && parameter.equals(procedure.getInParameters().get(0))) { continue; } out.print(glue); if (scala) out.print("%s : %s", getStrategy().getJavaMemberName(parameter), refNumberType(out, parameter.getType())); else out.print("%s %s", refNumberType(out, parameter.getType()), getStrategy().getJavaMemberName(parameter)); glue = ", "; } if (scala) { out.print(") : "); if (outParams.size() == 0) { out.print("Unit"); } else if (outParams.size() == 1) { out.print(out.ref(getJavaType(outParams.get(0).getType()))); } else { out.print(className); } out.println(" = {"); out.tab(2).println("val %s = new %s", localVar, className); } else { out.println(") {"); out.tab(2).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); if (scala) out.tab(2).println("%s.%s(%s)", localVar, setter, arg); else out.tab(2).println("%s.%s(%s);", localVar, setter, arg); } out.println(); if (scala) out.tab(2).println("%s.execute(%s)", localVar, instance ? "configuration()" : configurationArgument); else out.tab(2).println("%s.execute(%s);", localVar, instance ? "configuration()" : configurationArgument); if (outParams.size() > 0) { final ParameterDefinition parameter = outParams.get(0); // Avoid disambiguation for RETURN_VALUE getter final String getter = parameter == procedure.getReturnValue() ? "getReturnValue" : getStrategy().getJavaGetterName(parameter, Mode.DEFAULT); final boolean isUDT = parameter.getType().isUDT(); if (instance) { // [#3117] Avoid funny call-site ambiguity if this is a UDT that is implemented by an interface if (generateInterfaces() && isUDT) { final String columnTypeInterface = out.ref(getJavaType(parameter.getType(), Mode.INTERFACE)); if (scala) out.tab(2).println("from(%s.%s.asInstanceOf[%s])", localVar, getter, columnTypeInterface); else out.tab(2).println("from((%s) %s.%s());", columnTypeInterface, localVar, getter); } else { if (scala) out.tab(2).println("from(%s.%s)", localVar, getter); else out.tab(2).println("from(%s.%s());", localVar, getter); } } if (outParams.size() == 1) { if (scala) out.tab(2).println("return %s.%s", localVar, getter); else out.tab(2).println("return %s.%s();", localVar, getter); } else if (outParams.size() > 1) { if (scala) out.tab(2).println("return %s", localVar); else out.tab(2).println("return %s;", localVar); } } out.tab(1).println("}"); } protected void printConvenienceMethodTableValuedFunction(JavaWriter out, TableDefinition function, String javaMethodName) { // [#281] - Java can't handle more than 255 method parameters 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)); // [#3456] Local variables should not collide with actual function arguments final String configurationArgument = disambiguateJavaMemberName(function.getParameters(), "configuration"); out.tab(1).javadoc("Call %s.", function.getQualifiedOutputName()); if (scala) out.tab(1).print("def %s(%s : %s", javaMethodName, configurationArgument, Configuration.class); else out.tab(1).print("public static %s<%s> %s(%s %s", Result.class, recordClassName, javaMethodName, Configuration.class, configurationArgument); if (!function.getParameters().isEmpty()) out.print(", "); printParameterDeclarations(out, function, false); if (scala) { out.println(") : %s[%s] = {", Result.class, recordClassName); out.tab(2).print("%s.using(%s).selectFrom(%s.call(", DSL.class, configurationArgument, out.ref(getStrategy().getFullJavaIdentifier(function), 2)); } else { out.println(") {"); out.tab(2).print("return %s.using(%s).selectFrom(%s.call(", DSL.class, configurationArgument, out.ref(getStrategy().getFullJavaIdentifier(function), 2)); } String separator = ""; for (ParameterDefinition parameter : function.getParameters()) { out.print(separator); out.print("%s", getStrategy().getJavaMemberName(parameter)); separator = ", "; } out.print(")).fetch()"); if (scala) out.println(); else out.println(";"); out.tab(1).println("}"); } protected void printRecordTypeMethod(JavaWriter out, Definition definition) { final String className = out.ref(getStrategy().getFullJavaClassName(definition, Mode.RECORD)); out.tab(1).javadoc("The class holding records for this type"); if (scala) { out.tab(1).println("override def getRecordType : %s[%s] = {", Class.class, className); out.tab(2).println("classOf[%s]", className); out.tab(1).println("}"); } else { out.tab(1).override(); out.tab(1).println("public %s<%s> getRecordType() {", Class.class, className); out.tab(2).println("return %s.class;", className); out.tab(1).println("}"); } } protected void printSingletonInstance(JavaWriter out, Definition definition) { final String className = getStrategy().getJavaClassName(definition); final String identifier = getStrategy().getJavaIdentifier(definition); out.tab(1).javadoc("The reference instance of %s", definition.getQualifiedOutputName()); if (scala) out.tab(1).println("val %s = new %s", identifier, className); else out.tab(1).println("public static final %s %s = new %s();", className, identifier, className); } protected void printClassJavadoc(JavaWriter out, Definition definition) { printClassJavadoc(out, definition.getComment()); } protected void printClassJavadoc(JavaWriter out, String comment) { out.println("/**"); if (comment != null && comment.length() > 0) { printJavadocParagraph(out, comment, ""); } else { out.println(" * This class is generated by jOOQ."); } out.println(" */"); } protected void printClassAnnotations(JavaWriter out, SchemaDefinition schema) { printClassAnnotations(out, schema, schema.getCatalog()); } protected void printClassAnnotations(JavaWriter out, SchemaDefinition schema, CatalogDefinition catalog) { if (generateGeneratedAnnotation()) { out.println("@%s(", out.ref("javax.annotation.Generated")); if (useSchemaVersionProvider() || useCatalogVersionProvider()) { if (scala) out.tab(1).println("value = %s(", out.ref("scala.Array")); else out.tab(1).println("value = {"); out.tab(2).println("\"http://www.jooq.org\","); out.tab(2).println("\"jOOQ version:%s\",", Constants.VERSION); if (!StringUtils.isBlank(catalogVersions.get(catalog))) out.tab(2).println("\"catalog version:%s\",", catalogVersions.get(catalog).replace("\"", "\\\"")); if (!StringUtils.isBlank(schemaVersions.get(schema))) out.tab(2).println("\"schema version:%s\",", schemaVersions.get(schema).replace("\"", "\\\"")); if (scala) out.tab(1).println("),"); else out.tab(1).println("},"); out.tab(1).println("date = \"" + isoDate + "\","); out.tab(1).println("comments = \"This class is generated by jOOQ\""); } else { if (scala) out.tab(1).println("value = %s(", out.ref("scala.Array")); else out.tab(1).println("value = {"); out.tab(2).println("\"http://www.jooq.org\","); out.tab(2).println("\"jOOQ version:%s\"", Constants.VERSION); if (scala) out.tab(1).println("),"); else out.tab(1).println("},"); out.tab(1).println("comments = \"This class is generated by jOOQ\""); } out.println(")"); } if (!scala) out.println("@%s({ \"all\", \"unchecked\", \"rawtypes\" })", out.ref("java.lang.SuppressWarnings")); } private final 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*?\\{[^}]*?\"" + type + " version:([^\"]*?)\"").matcher(string); if (matcher.find()) { result = matcher.group(1); } } finally { f.close(); } } catch (IOException ignore) {} return result; } /** * This method is used to add line breaks in lengthy javadocs */ protected void printJavadocParagraph(JavaWriter out, String comment, String indent) { // [#3450] [#4880] Must not print */ inside Javadoc String escaped = comment.replace("/*", "/ *").replace("*/", "* /"); 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) { out.println("/**"); out.println(" * This class is generated by jOOQ"); out.println(" */"); if (scala) out.println("package %s", getStrategy().getJavaPackageName(definition, mode)); else out.println("package %s;", getStrategy().getJavaPackageName(definition, mode)); out.println(); out.printImports(); out.println(); } @Deprecated protected String getExtendsNumberType(DataTypeDefinition type) { return getNumberType(type, scala ? "_ <: " : "? extends "); } protected String refExtendsNumberType(JavaWriter out, DataTypeDefinition type) { if (type.isGenericNumberType()) { return (scala ? "_ <: " : "? extends ") + out.ref(Number.class); } else { return out.ref(getJavaType(type)); } } @Deprecated protected String getNumberType(DataTypeDefinition type) { if (type.isGenericNumberType()) { return Number.class.getName(); } else { return getJavaType(type); } } protected String refNumberType(JavaWriter out, DataTypeDefinition type) { if (type.isGenericNumberType()) { return out.ref(Number.class); } else { return out.ref(getJavaType(type)); } } @Deprecated protected String getNumberType(DataTypeDefinition type, String prefix) { if (type.isGenericNumberType()) { return prefix + Number.class.getName(); } else { return getJavaType(type); } } protected String getSimpleJavaType(DataTypeDefinition type) { return GenerationUtil.getSimpleJavaType(getJavaType(type)); } protected String getJavaTypeReference(Database db, DataTypeDefinition type) { // [#4388] TODO: Improve array handling if (database.isArrayType(type.getType())) { String baseType = GenerationUtil.getArrayBaseType(db.getDialect(), type.getType(), type.getUserType()); return getTypeReference( db, type.getSchema(), baseType, 0, 0, 0, true, null, baseType ) + ".getArrayDataType()"; } else { return getTypeReference( db, type.getSchema(), type.getType(), type.getPrecision(), type.getScale(), type.getLength(), type.isNullable(), type.getDefaultValue(), type.getUserType() ); } } protected String getJavaType(DataTypeDefinition type) { return getJavaType(type, Mode.RECORD); } protected String getJavaType(DataTypeDefinition type, Mode udtMode) { return getType( type.getDatabase(), type.getSchema(), type.getType(), type.getPrecision(), type.getScale(), type.getUserType(), type.getJavaType(), Object.class.getName(), udtMode); } protected String getType(Database db, SchemaDefinition schema, String t, int p, int s, String u, String javaType, String defaultType) { return getType(db, schema, t, p, s, u, javaType, defaultType, Mode.RECORD); } protected String getType(Database db, SchemaDefinition schema, String t, int p, int s, String u, String javaType, String defaultType, Mode udtMode) { String type = defaultType; // Custom types if (javaType != null) { type = javaType; } // Array types else if (db.isArrayType(t)) { // [#4388] TODO: Improve array handling String baseType = GenerationUtil.getArrayBaseType(db.getDialect(), t, u); if (scala) type = "scala.Array[" + getType(db, schema, baseType, p, s, baseType, javaType, defaultType, udtMode) + "]"; else type = getType(db, schema, baseType, p, s, baseType, javaType, defaultType, udtMode) + "[]"; } // Check for Oracle-style VARRAY types else if (db.getArray(schema, u) != null) { boolean udtArray = db.getArray(schema, u).getElementType().isUDT(); if (udtMode == Mode.POJO || (udtMode == Mode.INTERFACE && !udtArray)) { if (scala) type = "java.util.List[" + getJavaType(db.getArray(schema, u).getElementType(), udtMode) + "]"; else type = "java.util.List<" + getJavaType(db.getArray(schema, u).getElementType(), udtMode) + ">"; } else if (udtMode == Mode.INTERFACE) { if (scala) type = "java.util.List[_ <:" + getJavaType(db.getArray(schema, u).getElementType(), udtMode) + "]"; else type = "java.util.List"; } else { type = getStrategy().getFullJavaClassName(db.getArray(schema, u), Mode.RECORD); } } // Check for ENUM types else if (db.getEnum(schema, u) != null) { type = getStrategy().getFullJavaClassName(db.getEnum(schema, u)); } // Check for UDTs else if (db.getUDT(schema, u) != null) { type = getStrategy().getFullJavaClassName(db.getUDT(schema, u), udtMode); } // [#3942] PostgreSQL treats UDTs and table types in similar ways // [#5334] In MySQL, the user type is (ab)used for synthetic enum types. This can lead to accidental matches here else if (db.getDialect().family() == POSTGRES && db.getTable(schema, u) != null) { type = getStrategy().getFullJavaClassName(db.getTable(schema, u), udtMode); } // Check for custom types else if (db.getConfiguredCustomType(u) != null) { type = u; } // Try finding a basic standard SQL type according to the current dialect else { try { Class clazz = DefaultDataType.getType(db.getDialect(), t, p, s); if (scala && clazz == byte[].class) type = "scala.Array[scala.Byte]"; 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; } } } return type; } protected String getTypeReference(Database db, SchemaDefinition schema, String t, int p, int s, int l, boolean n, String d, String u) { StringBuilder sb = new StringBuilder(); if (db.getArray(schema, u) != null) { ArrayDefinition array = database.getArray(schema, u); sb.append(getJavaTypeReference(db, array.getElementType())); sb.append(".asArrayDataType("); sb.append(classOf(getStrategy().getFullJavaClassName(array, Mode.RECORD))); sb.append(")"); } else if (db.getUDT(schema, u) != null) { sb.append(getStrategy().getFullJavaIdentifier(db.getUDT(schema, u))); sb.append(".getDataType()"); } // [#3942] PostgreSQL treats UDTs and table types in similar ways // [#5334] In MySQL, the user type is (ab)used for synthetic enum types. This can lead to accidental matches here 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("org.jooq.util."); sb.append(db.getDialect().getName().toLowerCase()); sb.append("."); sb.append(db.getDialect().getName()); sb.append("DataType."); sb.append(DefaultDataType.normalise(DefaultDataType.getDataType(db.getDialect(), String.class).getTypeName())); sb.append(".asEnumDataType("); sb.append(classOf(getStrategy().getFullJavaClassName(db.getEnum(schema, u)))); sb.append(")"); } else { DataType dataType = null; try { dataType = DefaultDataType.getDataType(db.getDialect(), t, p, s).nullable(n); if (d != null) dataType = dataType.defaultValue((Field) DSL.field(d, dataType)); } // Mostly because of unsupported data types. Will be handled later. catch (SQLDialectNotSupportedException ignore) { } // If there is a standard SQLDataType available for the dialect- // specific DataType t, then reference that one. if (dataType != null && dataType.getSQLDataType() != null) { DataType sqlDataType = dataType.getSQLDataType(); String sqlDataTypeRef = SQLDataType.class.getCanonicalName() + '.' + DefaultDataType.normalise(sqlDataType.getTypeName()); sb.append(sqlDataTypeRef); if (dataType.hasPrecision() && p > 0) { sb.append(".precision(").append(p); if (dataType.hasScale() && s > 0) sb.append(", ").append(s); sb.append(")"); } if (dataType.hasLength() && l > 0) sb.append(".length(").append(l).append(")"); if (!dataType.nullable()) sb.append(".nullable(false)"); // [#5291] Some dialects report valid SQL expresions (e.g. PostgreSQL), others // report actual values (e.g. MySQL). if (dataType.defaulted()) { sb.append(".defaultValue("); if (asList(MYSQL).contains(db.getDialect().family())) sb.append("org.jooq.impl.DSL.inline(\"") .append(escapeString(d)) .append("\""); else sb.append("org.jooq.impl.DSL.field(\"") .append(escapeString(d)) .append("\""); sb.append(", ") .append(sqlDataTypeRef) .append("))"); } } // Otherwise, reference the dialect-specific DataType itself. else { try { // [#4173] DEFAULT and SQL99 data types String typeClass = (db.getDialect().getName() == null) ? SQLDataType.class.getName() : "org.jooq.util." + db.getDialect().getName().toLowerCase() + "." + db.getDialect().getName() + "DataType"; sb.append(typeClass); sb.append("."); String type1 = getType(db, schema, t, p, s, u, null, null); String type2 = getType(db, schema, t, 0, 0, u, null, null); String typeName = DefaultDataType.normalise(t); // [#1298] Prevent compilation errors for missing types Reflect.on(typeClass).field(typeName); sb.append(typeName); if (!type1.equals(type2)) { Class clazz = DefaultDataType.getType(db.getDialect(), t, p, s); sb.append(".asNumberDataType("); sb.append(classOf(clazz.getCanonicalName())); sb.append(")"); } } // Mostly because of unsupported data types catch (SQLDialectNotSupportedException e) { sb = new StringBuilder(); sb.append(DefaultDataType.class.getName()); sb.append(".getDefaultDataType(\""); sb.append(t.replace("\"", "\\\"")); sb.append("\")"); } // More unsupported data types catch (ReflectException e) { sb = new StringBuilder(); sb.append(DefaultDataType.class.getName()); sb.append(".getDefaultDataType(\""); sb.append(t.replace("\"", "\\\"")); sb.append("\")"); } } } return sb.toString(); } protected boolean match(DataTypeDefinition type1, DataTypeDefinition type2) { return getJavaType(type1).equals(getJavaType(type2)); } @SafeVarargs private static final List list(T... objects) { List result = new ArrayList(); if (objects != null) for (T object : objects) if (object != null && !"".equals(object)) result.add(object); return result; } @SuppressWarnings("unchecked") private static final List list(T first, List remaining) { List result = new ArrayList(); result.addAll(list(first)); result.addAll(remaining); return result; } private static final List first(Collection objects) { List result = new ArrayList(); if (objects != null) { for (T object : objects) { result.add(object); break; } } return result; } private static final List remaining(Collection objects) { List result = new ArrayList(); if (objects != null) { result.addAll(objects); if (result.size() > 0) result.remove(0); } return result; } private final String classOf(String string) { if (scala) return "classOf[" + string + "]"; else return string + ".class"; } // [#3880] Users may need to call this method protected JavaWriter newJavaWriter(File file) { if (scala) file = new File(file.getParentFile(), file.getName().replace(".java", ".scala")); return new JavaWriter(file, generateFullyQualifiedTypes(), targetEncoding); } // [#4626] Users may need to call this method protected void closeJavaWriter(JavaWriter out) { if (out.close()) files.add(out.file()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy