org.eclipse.persistence.tools.schemaframework.JPAMTableDefinition Maven / Gradle / Ivy
Go to download
Jeddict is an open source Jakarta EE application development platform that accelerates developers productivity and simplifies development tasks of creating complex entity relationship models.
/** *****************************************************************************
* Copyright (c) 1998, 2014 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
* Dies Koper - avoid generating constraints on platforms that do not support constraint generation
* Dies Koper - add support for creating indices on tables
* 09/09/2011-2.3.1 Guy Pelletier
* - 356197: Add new VPD type to MultitenantType
* 09/14/2011-2.3.1 Guy Pelletier
* - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU
* 12/07/2012-2.5 Guy Pelletier
* - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
* 02/04/2013-2.5 Guy Pelletier
* - 389090: JPA 2.1 DDL Generation Support
****************************************************************************** */
package org.eclipse.persistence.tools.schemaframework;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.SQLCall;
import io.github.jeddict.relation.mapper.spec.DBBaseTable;
import io.github.jeddict.relation.mapper.spec.DBCollectionTable;
import io.github.jeddict.relation.mapper.spec.DBMapping;
import io.github.jeddict.relation.mapper.spec.DBRelationTable;
import io.github.jeddict.relation.mapper.spec.DBSecondaryTable;
import io.github.jeddict.relation.mapper.spec.DBTable;
import io.github.jeddict.jpa.spec.ElementCollection;
import io.github.jeddict.jpa.spec.Entity;
import io.github.jeddict.jpa.spec.ManagedClass;
import io.github.jeddict.jpa.spec.SecondaryTable;
import io.github.jeddict.jpa.spec.Table;
import io.github.jeddict.jpa.spec.extend.Attribute;
import io.github.jeddict.jpa.spec.extend.BaseElement;
import io.github.jeddict.jpa.spec.extend.RelationAttribute;
import org.netbeans.modeler.core.NBModelerUtil;
import org.netbeans.modeler.specification.model.document.core.IBaseElement;
/**
*
* Purpose: Allow a generic way of creating tables on the different
* platforms.
*
*/
public class JPAMTableDefinition extends TableDefinition {
private final ManagedClass managedClass;
private final List intrinsicEntity = new LinkedList<>();
private final Attribute attribute;
public JPAMTableDefinition(ManagedClass managedClass, Attribute managedAttribute, List intrinsicEntity) {
this.managedClass = (ManagedClass) getOrignalElement(managedClass);
intrinsicEntity.forEach((_class) -> {
if (_class != null && _class.getOrignalObject() != null) {
this.intrinsicEntity.add((Entity) _class.getOrignalObject());
} else {
this.intrinsicEntity.add(_class);
}
});
this.attribute = (Attribute) getOrignalElement(managedAttribute);
}
private IBaseElement getOrignalElement(BaseElement baseElement) {
return baseElement != null && baseElement.getOrignalObject() != null ? baseElement.getOrignalObject() : baseElement;
}
/**
* INTERNAL: Return the create table object.
*/
public void buildDBTable(AbstractSession session, DBMapping dbMapping) throws ValidationException {
DBTable dBTable;
Entity entity = intrinsicEntity.get(0);
Table table;
if (attribute instanceof RelationAttribute) {
dBTable = new DBRelationTable(getFullName(), entity, (RelationAttribute) attribute);//Todo pass managedClass
} else if (attribute instanceof ElementCollection) {
dBTable = new DBCollectionTable(getFullName(), entity, (ElementCollection) attribute);
} else if((table = entity.getTable(getFullName())) instanceof SecondaryTable){
dBTable = new DBSecondaryTable(getFullName(), entity, (SecondaryTable)table);
} else {
dBTable = new DBBaseTable(getFullName(), entity);
}
dBTable.setId(NBModelerUtil.getAutoGeneratedStringId());
for (Iterator itetrator = getFields().iterator(); itetrator.hasNext();) {
JPAMFieldDefinition field = (JPAMFieldDefinition) itetrator.next();
field.buildDBColumn(dBTable, session, this);
}
dbMapping.addTable(dBTable);
}
/**
* INTERNAL: Build the foreign key constraints.
*/
@Override
protected void buildFieldTypes(AbstractSession session) {
// The ForeignKeyConstraint object is the newer way of doing things.
// We support FieldDefinition.getForeignKeyFieldName() due to backwards compatibility
// by converting it. To allow mixing both ways, we just add converted one to foreignKeys list.
for (FieldDefinition field : getFields()) {
if (field.getForeignKeyFieldName() != null) {
addForeignKeyConstraint(buildForeignKeyConstraint(field, session.getPlatform()));
}
}
}
@Override
void createUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {
if ((!session.getPlatform().supportsUniqueKeyConstraints())
|| getUniqueKeys().isEmpty()
|| session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) {
return;
}
for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
session.priviledgedExecuteNonSelectingCall(new org.eclipse.persistence.queries.SQLCall(buildUniqueConstraintCreationWriter(session, uniqueKey, new StringWriter()).toString()));
}
}
@Override
void createForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {
if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeyMap().isEmpty()) {
return;
}
for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) {
if (!foreignKey.disableForeignKey()) {
session.priviledgedExecuteNonSelectingCall(new SQLCall(buildConstraintCreationWriter(session, foreignKey, new StringWriter()).toString()));
}
}
}
/**
* Build a foreign key constraint using
* FieldDefinition.getForeignKeyFieldName().
*/
@Override
protected ForeignKeyConstraint buildForeignKeyConstraint(FieldDefinition field, DatabasePlatform platform) {
Vector sourceFields = new Vector();
Vector targetFields = new Vector();
ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint();
DatabaseField tempTargetField = new DatabaseField(field.getForeignKeyFieldName());
DatabaseField tempSourceField = new DatabaseField(field.getName());
sourceFields.add(tempSourceField.getName());
targetFields.add(tempTargetField.getName());
fkConstraint.setSourceFields(sourceFields);
fkConstraint.setTargetFields(targetFields);
fkConstraint.setTargetTable(tempTargetField.getTable().getQualifiedNameDelimited(platform));
String tempName = buildForeignKeyConstraintName(this.getName(), tempSourceField.getName(), platform.getMaxForeignKeyNameSize(), platform);
fkConstraint.setName(tempName);
return fkConstraint;
}
/**
* Build a foreign key constraint.
*/
@Override
protected ForeignKeyConstraint buildForeignKeyConstraint(List fkFieldNames, List pkFieldNames, TableDefinition targetTable, DatabasePlatform platform) {
assert fkFieldNames.size() > 0 && fkFieldNames.size() == pkFieldNames.size();
ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint();
for (int i = 0; i < fkFieldNames.size(); i++) {
fkConstraint.getSourceFields().add(fkFieldNames.get(i));
fkConstraint.getTargetFields().add(pkFieldNames.get(i));
}
fkConstraint.setTargetTable(targetTable.getFullName());
String fkFieldName = fkFieldNames.get(0);
String name = buildForeignKeyConstraintName(this.getName(), fkFieldName, platform.getMaxForeignKeyNameSize(), platform);
fkConstraint.setName(name);
return fkConstraint;
}
/**
* Return foreign key constraint name built from the table and field name
* with the specified maximum length. To make the name short enough we 1.
* Drop the "FK_" prefix. 2. Drop the underscore characters if any. 3. Drop
* the vowels from the table and field name. 4. Truncate the table name to
* zero length if necessary.
*/
@Override
protected String buildForeignKeyConstraintName(String tableName, String fieldName, int maximumNameLength, DatabasePlatform platform) {
String startDelimiter = "";
String endDelimiter = "";
boolean useDelimiters = !platform.getStartDelimiter().equals("") && (tableName.startsWith(platform.getStartDelimiter()) || fieldName.startsWith(platform.getStartDelimiter()));
// we will only delimit our generated constraints if either of the names that composes them is already delimited
if (useDelimiters) {
startDelimiter = platform.getStartDelimiter();
endDelimiter = platform.getEndDelimiter();
}
String adjustedTableName = tableName;
if (adjustedTableName.indexOf(' ') != -1 || adjustedTableName.indexOf('\"') != -1 || adjustedTableName.indexOf('`') != -1) {
//if table name has spaces and/or is quoted, remove this from the constraint name.
StringBuilder buff = new StringBuilder();
for (int i = 0; i < tableName.length(); i++) {
char c = tableName.charAt(i);
if (c != ' ' && c != '\"' && c != '`') {
buff.append(c);
}
}
adjustedTableName = buff.toString();
}
StringBuilder buff = new StringBuilder();
for (int i = 0; i < fieldName.length(); i++) {
char c = fieldName.charAt(i);
if (c != ' ' && c != '\"' && c != '`') {
buff.append(c);
}
}
String adjustedFieldName = buff.toString();
String foreignKeyName = startDelimiter + "FK_" + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
if (foreignKeyName.length() > maximumNameLength) {
// First Remove the "FK_" prefix.
foreignKeyName = startDelimiter + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
if (foreignKeyName.length() > maximumNameLength) {
// Still too long: remove the underscore characters
foreignKeyName = startDelimiter + Helper.removeAllButAlphaNumericToFit(adjustedTableName + adjustedFieldName, maximumNameLength) + endDelimiter;
if (foreignKeyName.length() > maximumNameLength) {
// Still too long: remove vowels from the table name and field name.
String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(adjustedTableName, 0);
String onlyAlphaNumericFieldName = Helper.removeAllButAlphaNumericToFit(adjustedFieldName, 0);
foreignKeyName = startDelimiter + Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, onlyAlphaNumericFieldName, maximumNameLength) + endDelimiter;
if (foreignKeyName.length() > maximumNameLength) {
// Still too long: remove vowels from the table name and field name and truncate the table name.
String shortenedFieldName = Helper.removeVowels(onlyAlphaNumericFieldName);
String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName);
int delimiterLength = startDelimiter.length() + endDelimiter.length();
if (shortenedFieldName.length() + delimiterLength >= maximumNameLength) {
foreignKeyName = startDelimiter + Helper.truncate(shortenedFieldName, maximumNameLength - delimiterLength) + endDelimiter;
} else {
foreignKeyName = startDelimiter + Helper.truncate(shortenedTableName, maximumNameLength - shortenedFieldName.length() - delimiterLength) + shortenedFieldName + endDelimiter;
}
}
}
}
}
return foreignKeyName;
}
@Override
public UniqueKeyConstraint buildUniqueKeyConstraint(String name, List fieldNames, int serialNumber, DatabasePlatform platform) {
assert fieldNames.size() > 0;
UniqueKeyConstraint unqConstraint = new UniqueKeyConstraint();
for (String fieldName : fieldNames) {
unqConstraint.addSourceField(fieldName);
}
// If the name was not provided, default one, otherwise use the name provided.
if (name == null || name.equals("")) {
unqConstraint.setName(buildUniqueKeyConstraintName(getName(), serialNumber, platform.getMaxUniqueKeyNameSize()));
} else {
// Hack if off if it exceeds the max size.
if (name.length() > platform.getMaxUniqueKeyNameSize()) {
unqConstraint.setName(name.substring(0, platform.getMaxUniqueKeyNameSize() - 1));
} else {
unqConstraint.setName(name);
}
}
return unqConstraint;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy