org.eclipse.persistence.internal.helper.DatabaseTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// tware - added handling of database delimiters
// 11/19/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
// 11/22/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (index metadata support)
// 12/07/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
package org.eclipse.persistence.internal.helper;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.persistence.internal.core.helper.CoreTable;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter;
import org.eclipse.persistence.tools.schemaframework.ForeignKeyConstraint;
import org.eclipse.persistence.tools.schemaframework.IndexDefinition;
/**
* INTERNAL:
* Purpose:
* Define a fully qualified table name.
* Responsibilities:
* - Allow specification of a qualifier to the table, i.e. creator or database.
*
*@see DatabaseField
*/
public class DatabaseTable implements CoreTable, Cloneable, Serializable {
protected String name;
protected String tableQualifier;
protected String qualifiedName;
/** JPA 2.1 Foreign key specification data */
protected Map foreignKeyConstraints;
/**
* Contains the user specified unique constraints. JPA 2.0 introduced
* the name element, therefore, if specified we will use that name
* to create the constraint. Constraints with no name will be added to the
* map under the null key and generated with a default name.
* Therefore, when a name is given the list size should only ever be
* 1. We will validate. The null key could have multiples however they will
* have their names defaulted (as we did before).
*/
protected Map>> uniqueConstraints;
/**
* Store the set of indexes defined through meta-data for the table.
*/
protected List indexes;
protected boolean useDelimiters = false;
protected String creationSuffix;
/**
* Initialize the newly allocated instance of this class.
* By default their is no qualifier.
*/
public DatabaseTable() {
name = "";
tableQualifier = "";
}
public DatabaseTable(String possiblyQualifiedName) {
this(possiblyQualifiedName, null, null);
}
public DatabaseTable(String possiblyQualifiedName, String startDelimiter, String endDelimiter) {
setPossiblyQualifiedName(possiblyQualifiedName, startDelimiter, endDelimiter);
}
public DatabaseTable(String tableName, String qualifier) {
this(tableName, qualifier, false, null, null);
}
public DatabaseTable(String tableName, String qualifier, boolean useDelimiters, String startDelimiter, String endDelimiter) {
setName(tableName, startDelimiter, endDelimiter);
this.tableQualifier = qualifier;
this.useDelimiters = useDelimiters;
}
public void addForeignKeyConstraint(ForeignKeyConstraint foreignKeyConstraint) {
if (foreignKeyConstraints == null) {
foreignKeyConstraints = new HashMap();
}
foreignKeyConstraints.put(foreignKeyConstraint.getName(), foreignKeyConstraint);
}
/**
* Add an index definition to this table.
*/
public void addIndex(IndexDefinition index) {
getIndexes().add(index);
}
/**
* Add the unique constraint for the columns names. Used for DDL generation.
* For now we just add all the unique constraints as we would have before
* when we didn't have a name.
*/
public void addUniqueConstraints(String name, List columnNames) {
if (getUniqueConstraints().containsKey(name)) {
getUniqueConstraints().get(name).add(columnNames);
} else {
List> value = new ArrayList>();
value.add(columnNames);
getUniqueConstraints().put(name, value);
}
}
/**
* Return a shallow copy of the receiver.
*/
public DatabaseTable clone() {
try {
return (DatabaseTable)super.clone();
} catch (CloneNotSupportedException exception) {
throw new InternalError(exception.getMessage());
}
}
/**
* Two tables are equal if their names and tables are equal,
* or their names are equal and one does not have a qualifier assigned.
* This allows an unqualified table to equal the same fully qualified one.
*/
public boolean equals(Object object) {
if (object instanceof DatabaseTable) {
return equals((DatabaseTable)object);
}
return false;
}
/**
* Two tables are equal if their names and tables are equal,
* or their names are equal and one does not have a qualifier assigned.
* This allows an unqualified table to equal the same fully qualified one.
*/
public boolean equals(DatabaseTable table) {
if (this == table) {
return true;
}
if (table == null) {
return false;
}
if (DatabasePlatform.shouldIgnoreCaseOnFieldComparisons) {
if (this.name.equalsIgnoreCase(table.name)) {
if ((this.tableQualifier.length() == 0) || (table.tableQualifier.length() == 0) || (this.tableQualifier.equalsIgnoreCase(table.tableQualifier))) {
return true;
}
}
} else {
if (this.name.equals(table.name)) {
if ((this.tableQualifier.length() == 0) || (table.tableQualifier.length() == 0) || (this.tableQualifier.equals(table.tableQualifier))) {
return true;
}
}
}
return false;
}
/**
* returns the suffix applied to the CREATE table statement on this field for DDL generation.
*/
public String getCreationSuffix() {
return creationSuffix;
}
public ForeignKeyConstraint getForeignKeyConstraint(String name) {
return foreignKeyConstraints.get(name);
}
public Map getForeignKeyConstraints() {
return foreignKeyConstraints;
}
/**
* Return a list of index definitions.
* Used for DDL generation.
*/
public List getIndexes() {
if (this.indexes == null) {
this.indexes = new ArrayList();
}
return this.indexes;
}
/**
* Get method for table name.
*/
public String getName() {
return name;
}
/**
* Get method for table name.
*/
public String getNameDelimited(DatasourcePlatform platform) {
if (useDelimiters){
return platform.getStartDelimiter() + name + platform.getEndDelimiter();
}
return name;
}
public String getQualifiedName() {
if (qualifiedName == null) {
if (tableQualifier.equals("")) {
qualifiedName = getName();
} else {
qualifiedName = getTableQualifier() + "." + getName();
}
}
return qualifiedName;
}
public String getQualifiedNameDelimited(DatasourcePlatform platform) {
if (tableQualifier.equals("")) {
if (useDelimiters){
return platform.getStartDelimiter() + getName() + platform.getEndDelimiter();
} else {
return getName();
}
} else {
if (useDelimiters){
return platform.getStartDelimiter() + getTableQualifier() + platform.getEndDelimiter() + "."
+ platform.getStartDelimiter() + getName() + platform.getEndDelimiter();
} else {
return getTableQualifier() + "." + getName();
}
}
}
/**
* Print the table's SQL from clause.
*/
public void printSQL(ExpressionSQLPrinter printer) throws IOException {
printer.getWriter().write(getQualifiedNameDelimited(printer.getPlatform()));
}
public String getTableQualifierDelimited(DatasourcePlatform platform) {
if (useDelimiters && tableQualifier != null && !tableQualifier.equals("")){
return platform.getStartDelimiter() + tableQualifier + platform.getEndDelimiter();
}
return tableQualifier;
}
public String getTableQualifier() {
return tableQualifier;
}
public boolean hasUniqueConstraints() {
return (this.uniqueConstraints != null) && (!this.uniqueConstraints.isEmpty());
}
public boolean hasForeignKeyConstraints() {
return foreignKeyConstraints != null;
}
/**
* Return the hashcode of the name, because it is fairly unique.
*/
public int hashCode() {
return getName().hashCode();
}
public boolean hasIndexes() {
return (this.indexes != null) && (!this.indexes.isEmpty());
}
/**
* Return a list of the unique constraints for this table.
* Used for DDL generation.
*/
public Map>> getUniqueConstraints() {
if (this.uniqueConstraints == null) {
this.uniqueConstraints = new HashMap>>();
}
return this.uniqueConstraints;
}
/**
* Determine whether the receiver has any identification information.
* Return true if the name or qualifier of the receiver are nonempty.
*/
public boolean hasName() {
if ((getName().length() == 0) && (getTableQualifier().length() == 0)) {
return false;
}
return true;
}
/**
* INTERNAL:
* Is this decorated / has an AS OF (some past time) clause.
* Example:
* SELECT ... FROM EMPLOYEE AS OF TIMESTAMP (exp) t0 ...
*/
public boolean isDecorated() {
return false;
}
protected void resetQualifiedName() {
this.qualifiedName = null;
}
public void setCreationSuffix(String creationSuffix) {
this.creationSuffix = creationSuffix;
}
/**
* Set the table name.
* Used when aliasing table names.
* @param name
*/
public void setName(String name) {
setName(name, null, null);
}
/**
* Set the table name.
* Used when aliasing table names.
*
* If the name contains database delimiters, they will be stripped and a flag will be set to have them
* added when the DatabaseTable is written to SQL
*
* @param name
*/
public void setName(String name, String startDelimiter, String endDelimiter) {
if (name != null && (startDelimiter != null) && (endDelimiter != null) && !startDelimiter.equals("")&& !endDelimiter.equals("") && name.startsWith(startDelimiter) && name.endsWith(endDelimiter)){
this.name = name.substring(startDelimiter.length(), name.length() - endDelimiter.length());
useDelimiters = true;
} else {
this.name = name ;
}
resetQualifiedName();
}
/**
* Used to map the project xml. Any time a string name is read from the
* project xml, we must check if it is fully qualified and split the
* actual name from the qualifier.
*
* @param possiblyQualifiedName
*/
public void setPossiblyQualifiedName(String possiblyQualifiedName) {
setPossiblyQualifiedName(possiblyQualifiedName, null, null);
}
public void setPossiblyQualifiedName(String possiblyQualifiedName, String startDelimiter, String endDelimiter) {
resetQualifiedName();
int index = possiblyQualifiedName.lastIndexOf('.');
if (index == -1) {
setName(possiblyQualifiedName, startDelimiter, endDelimiter);
this.tableQualifier = "";
} else {
setName(possiblyQualifiedName.substring(index + 1, possiblyQualifiedName.length()), startDelimiter, endDelimiter);
setTableQualifier(possiblyQualifiedName.substring(0, index), startDelimiter, endDelimiter);
if((startDelimiter != null) && possiblyQualifiedName.startsWith(startDelimiter) && (endDelimiter != null) && possiblyQualifiedName.endsWith(endDelimiter)) {
// It's 'Qualifier.Name' - it should be treated as a single string.
// Would that be 'Qualifier'.'Name' both setName and setTableQualifier methods would have set useDelimeters to true.
if(!this.useDelimiters) {
setName(possiblyQualifiedName);
this.tableQualifier = "";
}
}
}
}
public void setTableQualifier(String qualifier) {
setTableQualifier(qualifier, null, null);
}
public void setTableQualifier(String qualifier, String startDelimiter, String endDelimiter) {
if ((startDelimiter != null) && (endDelimiter != null) && !startDelimiter.equals("")&& !endDelimiter.equals("") && qualifier.startsWith(startDelimiter) && qualifier.endsWith(endDelimiter)){
this.tableQualifier = qualifier.substring(startDelimiter.length(), qualifier.length() - endDelimiter.length());
useDelimiters = true;
} else {
this.tableQualifier = qualifier;
}
resetQualifiedName();
}
public String toString() {
return "DatabaseTable(" + getQualifiedName() + ")";
}
public void setUseDelimiters(boolean useDelimiters) {
this.useDelimiters = useDelimiters;
}
public boolean shouldUseDelimiters() {
return useDelimiters;
}
}