Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » mapping » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.mapping;
   26   
   27   import java.util.ArrayList;
   28   import java.util.Iterator;
   29   import java.util.List;
   30   
   31   import org.hibernate.MappingException;
   32   import org.hibernate.dialect.Dialect;
   33   
   34   /**
   35    * A foreign key constraint
   36    * @author Gavin King
   37    */
   38   public class ForeignKey extends Constraint {
   39   
   40   	private Table referencedTable;
   41   	private String referencedEntityName;
   42   	private boolean cascadeDeleteEnabled;
   43   	private List referencedColumns = new ArrayList();    
   44       
   45   	public String sqlConstraintString(Dialect dialect, String constraintName, String defaultCatalog, String defaultSchema) {
   46   		String[] cols = new String[ getColumnSpan() ];
   47   		String[] refcols = new String[ getColumnSpan() ];
   48   		int i=0;
   49   		Iterator refiter = null;
   50   		if(isReferenceToPrimaryKey() ) {
   51   			refiter = referencedTable.getPrimaryKey().getColumnIterator();
   52   		} 
   53   		else {
   54   			refiter = referencedColumns.iterator();
   55   		}
   56   		
   57   		Iterator iter = getColumnIterator();
   58   		while ( iter.hasNext() ) {
   59   			cols[i] = ( (Column) iter.next() ).getQuotedName(dialect);
   60   			refcols[i] = ( (Column) refiter.next() ).getQuotedName(dialect);
   61   			i++;
   62   		}
   63   		String result = dialect.getAddForeignKeyConstraintString(
   64   			constraintName, cols, referencedTable.getQualifiedName(dialect, defaultCatalog, defaultSchema), refcols, isReferenceToPrimaryKey()
   65   		);
   66   		return cascadeDeleteEnabled && dialect.supportsCascadeDelete() ? 
   67   			result + " on delete cascade" : 
   68   			result;
   69   	}
   70   
   71   	public Table getReferencedTable() {
   72   		return referencedTable;
   73   	}
   74   
   75   	private void appendColumns(StringBuffer buf, Iterator columns) {
   76   		while( columns.hasNext() ) {
   77   			Column column = (Column) columns.next();
   78   			buf.append( column.getName() );
   79   			if ( columns.hasNext() ) buf.append(",");
   80   		}
   81   	}
   82   
   83   	public void setReferencedTable(Table referencedTable) throws MappingException {
   84   		//if( isReferenceToPrimaryKey() ) alignColumns(referencedTable); // TODO: possibly remove to allow more piecemal building of a foreignkey.  
   85   		
   86   		this.referencedTable = referencedTable;
   87   	}
   88   
   89   	/**
   90   	 * Validates that columnspan of the foreignkey and the primarykey is the same.
   91   	 * 
   92   	 * Furthermore it aligns the length of the underlying tables columns.
   93   	 * @param referencedTable
   94   	 */
   95   	public void alignColumns() {
   96   		if ( isReferenceToPrimaryKey() ) alignColumns(referencedTable);
   97   	}
   98   	
   99   	private void alignColumns(Table referencedTable) {
  100   		if ( referencedTable.getPrimaryKey().getColumnSpan()!=getColumnSpan() ) {
  101   			StringBuffer sb = new StringBuffer();
  102   			sb.append("Foreign key (")
  103                   .append( getName() + ":")
  104   				.append( getTable().getName() )
  105   				.append(" [");
  106   			appendColumns( sb, getColumnIterator() );
  107   			sb.append("])")
  108   				.append(") must have same number of columns as the referenced primary key (")
  109   				.append( referencedTable.getName() )
  110   				.append(" [");
  111   			appendColumns( sb, referencedTable.getPrimaryKey().getColumnIterator() );
  112   			sb.append("])");
  113   			throw new MappingException( sb.toString() );
  114   		}
  115   		
  116   		Iterator fkCols = getColumnIterator();
  117   		Iterator pkCols = referencedTable.getPrimaryKey().getColumnIterator();
  118   		while ( pkCols.hasNext() ) {
  119   			( (Column) fkCols.next() ).setLength( ( (Column) pkCols.next() ).getLength() );
  120   		}
  121   
  122   	}
  123   
  124   	public String getReferencedEntityName() {
  125   		return referencedEntityName;
  126   	}
  127   
  128   	public void setReferencedEntityName(String referencedEntityName) {
  129   		this.referencedEntityName = referencedEntityName;
  130   	}
  131   
  132   	public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
  133   		return "alter table " + 
  134   			getTable().getQualifiedName(dialect, defaultCatalog, defaultSchema) + 
  135   			dialect.getDropForeignKeyString() + 
  136   			getName();
  137   	}
  138   
  139   	public boolean isCascadeDeleteEnabled() {
  140   		return cascadeDeleteEnabled;
  141   	}
  142   
  143   	public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) {
  144   		this.cascadeDeleteEnabled = cascadeDeleteEnabled;
  145   	}
  146   	
  147   	public boolean isPhysicalConstraint() {
  148   		return referencedTable.isPhysicalTable() && 
  149   				getTable().isPhysicalTable() && 
  150   				!referencedTable.hasDenormalizedTables();
  151   	}
  152   
  153   	/** Returns the referenced columns if the foreignkey does not refer to the primary key */
  154   	public List getReferencedColumns() {
  155   		return referencedColumns;		
  156   	}
  157   
  158   	/** Does this foreignkey reference the primary key of the reference table */ 
  159   	public boolean isReferenceToPrimaryKey() {
  160   		return referencedColumns.isEmpty();
  161   	}
  162   
  163   	public void addReferencedColumns(Iterator referencedColumnsIterator) {
  164   		while ( referencedColumnsIterator.hasNext() ) {
  165   			Selectable col = (Selectable) referencedColumnsIterator.next();
  166   			if ( !col.isFormula() ) addReferencedColumn( (Column) col );
  167   		}
  168   	}
  169   
  170   	private void addReferencedColumn(Column column) {
  171   		if ( !referencedColumns.contains(column) ) referencedColumns.add(column);		
  172   	}
  173   	
  174   	public String toString() {
  175   		if(!isReferenceToPrimaryKey() ) {
  176   			StringBuffer result = new StringBuffer(getClass().getName() + '(' + getTable().getName() + getColumns() );
  177   			result.append( " ref-columns:" + '(' + getReferencedColumns() );
  178   			result.append( ") as " + getName() );
  179   			return result.toString();
  180   		} 
  181   		else {
  182   			return super.toString();
  183   		}
  184   		
  185   	}
  186   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » mapping » [javadoc | source]