package org.hibernate.mapping;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.StringHelper;
public class ForeignKey extends Constraint {
private Table referencedTable;
private String referencedEntityName;
private String keyDefinition;
private boolean cascadeDeleteEnabled;
private List<Column> referencedColumns = new ArrayList<Column>();
private boolean creationEnabled = true;
public ForeignKey() {
}
@Override
public String getExportIdentifier() {
return StringHelper.qualify( getTable().getName(), "FK-" + getName() );
}
public void disableCreation() {
creationEnabled = false;
}
public boolean isCreationEnabled() {
return creationEnabled;
}
@Override
public void setName(String name) {
super.setName( name );
if ( "none".equals( name ) ) {
disableCreation();
}
}
public String sqlConstraintString(
Dialect dialect,
String constraintName,
String defaultCatalog,
String defaultSchema) {
String[] columnNames = new String[getColumnSpan()];
String[] referencedColumnNames = new String[getColumnSpan()];
final Iterator<Column> referencedColumnItr;
if ( isReferenceToPrimaryKey() ) {
referencedColumnItr = referencedTable.getPrimaryKey().getColumnIterator();
}
else {
referencedColumnItr = referencedColumns.iterator();
}
Iterator columnItr = getColumnIterator();
int i = 0;
while ( columnItr.hasNext() ) {
columnNames[i] = ( (Column) columnItr.next() ).getQuotedName( dialect );
referencedColumnNames[i] = referencedColumnItr.next().getQuotedName( dialect );
i++;
}
final String result = keyDefinition != null ?
dialect.getAddForeignKeyConstraintString(
constraintName,
keyDefinition
) :
dialect.getAddForeignKeyConstraintString(
constraintName,
columnNames,
referencedTable.getQualifiedName(
dialect,
defaultCatalog,
defaultSchema
),
referencedColumnNames,
isReferenceToPrimaryKey()
);
return cascadeDeleteEnabled && dialect.supportsCascadeDelete()
? result + " on delete cascade"
: result;
}
public Table getReferencedTable() {
return referencedTable;
}
private void appendColumns(StringBuilder buf, Iterator columns) {
while ( columns.hasNext() ) {
Column column = (Column) columns.next();
buf.append( column.getName() );
if ( columns.hasNext() ) {
buf.append( "," );
}
}
}
public void setReferencedTable(Table referencedTable) throws MappingException {
this.referencedTable = referencedTable;
}
public void alignColumns() {
if ( isReferenceToPrimaryKey() ) {
alignColumns( referencedTable );
}
}
private void alignColumns(Table referencedTable) {
final int referencedPkColumnSpan = referencedTable.getPrimaryKey().getColumnSpan();
if ( referencedPkColumnSpan != getColumnSpan() ) {
StringBuilder sb = new StringBuilder();
sb.append( "Foreign key (" ).append( getName() ).append( ":" )
.append( getTable().getName() )
.append( " [" );
appendColumns( sb, getColumnIterator() );
sb.append( "])" )
.append( ") must have same number of columns as the referenced primary key (" )
.append( referencedTable.getName() )
.append( " [" );
appendColumns( sb, referencedTable.getPrimaryKey().getColumnIterator() );
sb.append( "])" );
throw new MappingException( sb.toString() );
}
Iterator fkCols = getColumnIterator();
Iterator pkCols = referencedTable.getPrimaryKey().getColumnIterator();
while ( pkCols.hasNext() ) {
( (Column) fkCols.next() ).setLength( ( (Column) pkCols.next() ).getLength() );
}
}
public String getReferencedEntityName() {
return referencedEntityName;
}
public void setReferencedEntityName(String referencedEntityName) {
this.referencedEntityName = referencedEntityName;
}
public String getKeyDefinition() {
return keyDefinition;
}
public void setKeyDefinition(String keyDefinition) {
this.keyDefinition = keyDefinition;
}
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
final StringBuilder buf = new StringBuilder( dialect.getAlterTableString( tableName ) );
buf.append( dialect.getDropForeignKeyString() );
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
buf.append( "if exists " );
}
buf.append( dialect.quote( getName() ) );
if ( dialect.supportsIfExistsAfterConstraintName() ) {
buf.append( " if exists" );
}
return buf.toString();
}
public boolean isCascadeDeleteEnabled() {
return cascadeDeleteEnabled;
}
public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) {
this.cascadeDeleteEnabled = cascadeDeleteEnabled;
}
public boolean isPhysicalConstraint() {
return referencedTable.isPhysicalTable()
&& getTable().isPhysicalTable()
&& !referencedTable.hasDenormalizedTables();
}
public List getReferencedColumns() {
return referencedColumns;
}
public boolean isReferenceToPrimaryKey() {
return referencedColumns.isEmpty();
}
public void addReferencedColumns(Iterator referencedColumnsIterator) {
while ( referencedColumnsIterator.hasNext() ) {
Selectable col = (Selectable) referencedColumnsIterator.next();
if ( !col.isFormula() ) {
addReferencedColumn( (Column) col );
}
}
}
private void addReferencedColumn(Column column) {
if ( !referencedColumns.contains( column ) ) {
referencedColumns.add( column );
}
}
public String toString() {
if ( !isReferenceToPrimaryKey() ) {
return getClass().getName()
+ '(' + getTable().getName() + getColumns()
+ " ref-columns:" + '(' + getReferencedColumns() + ") as " + getName() + ")";
}
else {
return super.toString();
}
}
public String generatedConstraintNamePrefix() {
return "FK_";
}
}