package io.ebean.config;

import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.util.AnnotationUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import javax.persistence.Table;

Provides some base implementation for NamingConventions.
Author:emcgreal
/** * Provides some base implementation for NamingConventions. * * @author emcgreal */
public abstract class AbstractNamingConvention implements NamingConvention { private static final Pattern TABLE_REPLACE = Pattern.compile("{table}", Pattern.LITERAL); private static final Pattern COLUMN_REPLACE = Pattern.compile("{column}", Pattern.LITERAL);
The Constant DEFAULT_SEQ_FORMAT.
/** * The Constant DEFAULT_SEQ_FORMAT. */
public static final String DEFAULT_SEQ_FORMAT = "{table}_seq";
The catalog.
/** * The catalog. */
private String catalog;
The schema.
/** * The schema. */
private String schema;
The sequence format.
/** * The sequence format. */
private String sequenceFormat;
The database platform.
/** * The database platform. */
protected DatabasePlatform databasePlatform;
Used to trim off extra prefix for M2M.
/** * Used to trim off extra prefix for M2M. */
protected int rhsPrefixLength = 3; protected boolean useForeignKeyPrefix;
Construct with a sequence format and useForeignKeyPrefix setting.
/** * Construct with a sequence format and useForeignKeyPrefix setting. */
public AbstractNamingConvention(String sequenceFormat, boolean useForeignKeyPrefix) { this.sequenceFormat = sequenceFormat; this.useForeignKeyPrefix = useForeignKeyPrefix; }
Construct with a sequence format.
Params:
  • sequenceFormat – the sequence format
/** * Construct with a sequence format. * * @param sequenceFormat the sequence format */
public AbstractNamingConvention(String sequenceFormat) { this.sequenceFormat = sequenceFormat; this.useForeignKeyPrefix = true; }
Construct with the default sequence format ("{table}_seq") and useForeignKeyPrefix as true.
/** * Construct with the default sequence format ("{table}_seq") and useForeignKeyPrefix as true. */
public AbstractNamingConvention() { this(DEFAULT_SEQ_FORMAT); } @Override public void setDatabasePlatform(DatabasePlatform databasePlatform) { this.databasePlatform = databasePlatform; } @Override public String getSequenceName(String tableName, String pkColumn) { String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableName)); if (pkColumn == null) { pkColumn = ""; } return COLUMN_REPLACE.matcher(s).replaceAll(Matcher.quoteReplacement(pkColumn)); }
Return the catalog.
/** * Return the catalog. */
public String getCatalog() { return catalog; }
Sets the catalog.
/** * Sets the catalog. */
public void setCatalog(String catalog) { this.catalog = catalog; }
Return the schema.
/** * Return the schema. */
public String getSchema() { return schema; }
Sets the schema.
/** * Sets the schema. */
public void setSchema(String schema) { this.schema = schema; }
Returns the sequence format.
/** * Returns the sequence format. */
public String getSequenceFormat() { return sequenceFormat; }
Set the sequence format used to generate the sequence name.

The format should include "{table}". When generating the sequence name {table} is replaced with the actual table name.

Params:
  • sequenceFormat – string containing "{table}" which is replaced with the actual table name to generate the sequence name.
/** * Set the sequence format used to generate the sequence name. * <p> * The format should include "{table}". When generating the sequence name * {table} is replaced with the actual table name. * </p> * * @param sequenceFormat string containing "{table}" which is replaced with the actual * table name to generate the sequence name. */
public void setSequenceFormat(String sequenceFormat) { this.sequenceFormat = sequenceFormat; }
Return true if a prefix should be used building a foreign key name.

This by default is true and this works well when the primary key column names are simply "ID". In this case a prefix (such as "ORDER" and "CUSTOMER" etc) is added to the foreign key column producing "ORDER_ID" and "CUSTOMER_ID".

This should return false when your primary key columns are the same as the foreign key columns. For example, when the primary key columns are "ORDER_ID", "CUST_ID" etc ... and they are the same as the foreign key column names.

/** * Return true if a prefix should be used building a foreign key name. * <p> * This by default is true and this works well when the primary key column * names are simply "ID". In this case a prefix (such as "ORDER" and * "CUSTOMER" etc) is added to the foreign key column producing "ORDER_ID" and * "CUSTOMER_ID". * </p> * <p> * This should return false when your primary key columns are the same as the * foreign key columns. For example, when the primary key columns are * "ORDER_ID", "CUST_ID" etc ... and they are the same as the foreign key * column names. * </p> */
@Override public boolean isUseForeignKeyPrefix() { return useForeignKeyPrefix; }
Set this to false when the primary key columns matching your foreign key columns.
/** * Set this to false when the primary key columns matching your foreign key * columns. */
public void setUseForeignKeyPrefix(boolean useForeignKeyPrefix) { this.useForeignKeyPrefix = useForeignKeyPrefix; }
Return the tableName using the naming convention (rather than deployed Table annotation).
/** * Return the tableName using the naming convention (rather than deployed * Table annotation). */
protected abstract TableName getTableNameByConvention(Class<?> beanClass);
Returns the table name for a given entity bean.

This first checks for the @Table annotation and if not present uses the naming convention to define the table name.

See Also:
/** * Returns the table name for a given entity bean. * <p> * This first checks for the @Table annotation and if not present uses the * naming convention to define the table name. * </p> * * @see #getTableNameFromAnnotation(Class) * @see #getTableNameByConvention(Class) */
@Override public TableName getTableName(Class<?> beanClass) { while (true) { TableName tableName = getTableNameFromAnnotation(beanClass); if (tableName == null) { Class<?> supCls = beanClass.getSuperclass(); if (hasInheritance(supCls)) { // get the table as per inherited class in case there // is not a table annotation in the inheritance hierarchy beanClass = supCls; continue; } tableName = getTableNameByConvention(beanClass); } // Use naming convention for catalog or schema, // if not set in the annotation. String catalog = tableName.getCatalog(); if (isEmpty(catalog)) { catalog = getCatalog(); } String schema = tableName.getSchema(); if (isEmpty(schema)) { schema = getSchema(); } return new TableName(catalog, schema, tableName.getName()); } }
Return true if this class is part of entity inheritance.
/** * Return true if this class is part of entity inheritance. */
protected boolean hasInheritance(Class<?> supCls) { return AnnotationUtil.findAnnotationRecursive(supCls, Inheritance.class) != null || AnnotationUtil.findAnnotation(supCls, DiscriminatorValue.class) != null; } @Override public TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable) { StringBuilder buffer = new StringBuilder(); buffer.append(lhsTable.getName()); buffer.append("_"); String rhsTableName = rhsTable.getName(); if (rhsTableName.indexOf('_') < rhsPrefixLength) { // trim off a xx_ prefix if there is one rhsTableName = rhsTableName.substring(rhsTableName.indexOf('_') + 1); } buffer.append(rhsTableName); int maxTableNameLength = databasePlatform.getMaxTableNameLength(); // maxConstraintNameLength is used as the max table name length. if (buffer.length() > maxTableNameLength) { buffer.setLength(maxTableNameLength); } return new TableName(lhsTable.getCatalog(), lhsTable.getSchema(), buffer.toString()); }
Gets the table name from annotation.
/** * Gets the table name from annotation. */
protected TableName getTableNameFromAnnotation(Class<?> beanClass) { final Table t = AnnotationUtil.findAnnotationRecursive(beanClass, Table.class); // Take the annotation if defined if (t != null && !isEmpty(t.name())) { // Note: empty catalog and schema are converted to null // Only need to convert quoted identifiers from annotations return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name())); } // No annotation return null; }
Replace back ticks (if they are used) with database platform specific quoted identifiers.
/** * Replace back ticks (if they are used) with database platform specific * quoted identifiers. */
protected String quoteIdentifiers(String s) { return databasePlatform.convertQuotedIdentifiers(s); }
Checks string is null or empty .
/** * Checks string is null or empty . */
protected boolean isEmpty(String s) { return s == null || s.trim().isEmpty(); }
Load settings from properties.
/** * Load settings from properties. */
@Override public void loadFromProperties(PropertiesWrapper properties) { useForeignKeyPrefix = properties.getBoolean("namingConvention.useForeignKeyPrefix", useForeignKeyPrefix); sequenceFormat = properties.get("namingConvention.sequenceFormat", sequenceFormat); schema = properties.get("namingConvention.schema", schema); } }