| package org.apache.ddlutils.model; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.util.HashSet; |
| import java.util.Iterator; |
| |
| import org.apache.commons.collections.set.ListOrderedSet; |
| import org.apache.commons.lang.builder.EqualsBuilder; |
| import org.apache.commons.lang.builder.HashCodeBuilder; |
| |
| /** |
| * Represents a database foreign key. |
| * |
| * @version $Revision$ |
| */ |
| public class ForeignKey implements Cloneable |
| { |
| /** The name of the foreign key, may be <code>null</code>. */ |
| private String _name; |
| /** The target table. */ |
| private Table _foreignTable; |
| /** The name of the foreign table. */ |
| private String _foreignTableName; |
| /** The references between local and remote columns. */ |
| private ListOrderedSet _references = new ListOrderedSet(); |
| /** Whether this foreign key has an associated auto-generated index. */ |
| private boolean _autoIndexPresent; |
| |
| /** |
| * Creates a new foreign key object that has no name. |
| */ |
| public ForeignKey() |
| { |
| this(null); |
| } |
| |
| /** |
| * Creates a new foreign key object. |
| * |
| * @param name The name of the foreign key |
| */ |
| public ForeignKey(String name) |
| { |
| _name = name; |
| } |
| |
| /** |
| * Returns the name of this foreign key. |
| * |
| * @return The name |
| */ |
| public String getName() |
| { |
| return _name; |
| } |
| |
| /** |
| * Sets the name of this foreign key. |
| * |
| * @param name The name |
| */ |
| public void setName(String name) |
| { |
| _name = name; |
| } |
| |
| /** |
| * Returns the foreign table. |
| * |
| * @return The foreign table |
| */ |
| public Table getForeignTable() |
| { |
| return _foreignTable; |
| } |
| |
| /** |
| * Sets the foreign table. |
| * |
| * @param foreignTable The foreign table |
| */ |
| public void setForeignTable(Table foreignTable) |
| { |
| _foreignTable = foreignTable; |
| _foreignTableName = (foreignTable == null ? null : foreignTable.getName()); |
| } |
| |
| /** |
| * Returns the name of the foreign table. |
| * |
| * @return The table name |
| */ |
| public String getForeignTableName() |
| { |
| return _foreignTableName; |
| } |
| |
| /** |
| * Sets the name of the foreign table. Please note that you should not use this method |
| * when manually constructing or manipulating the database model. Rather utilize the |
| * {@link #setForeignTable(Table)} method. |
| * |
| * @param foreignTableName The table name |
| */ |
| public void setForeignTableName(String foreignTableName) |
| { |
| if ((_foreignTable != null) && !_foreignTable.getName().equals(foreignTableName)) |
| { |
| _foreignTable = null; |
| } |
| _foreignTableName = foreignTableName; |
| } |
| |
| /** |
| * Returns the number of references. |
| * |
| * @return The number of references |
| */ |
| public int getReferenceCount() |
| { |
| return _references.size(); |
| } |
| |
| /** |
| * Returns the indicated reference. |
| * |
| * @param idx The index |
| * @return The reference |
| */ |
| public Reference getReference(int idx) |
| { |
| return (Reference)_references.get(idx); |
| } |
| |
| /** |
| * Returns the references. |
| * |
| * @return The references |
| */ |
| public Reference[] getReferences() |
| { |
| return (Reference[])_references.toArray(new Reference[_references.size()]); |
| } |
| |
| /** |
| * Returns the first reference if it exists. |
| * |
| * @return The first reference |
| */ |
| public Reference getFirstReference() |
| { |
| return (Reference)(_references.isEmpty() ? null : _references.get(0)); |
| } |
| |
| /** |
| * Adds a reference, ie. a mapping between a local column (in the table that owns this foreign key) |
| * and a remote column. |
| * |
| * @param reference The reference to add |
| */ |
| public void addReference(Reference reference) |
| { |
| if (reference != null) |
| { |
| for (int idx = 0; idx < _references.size(); idx++) |
| { |
| Reference curRef = getReference(idx); |
| |
| if (curRef.getSequenceValue() > reference.getSequenceValue()) |
| { |
| _references.add(idx, reference); |
| return; |
| } |
| } |
| _references.add(reference); |
| } |
| } |
| |
| /** |
| * Removes the given reference. |
| * |
| * @param reference The reference to remove |
| */ |
| public void removeReference(Reference reference) |
| { |
| if (reference != null) |
| { |
| _references.remove(reference); |
| } |
| } |
| |
| /** |
| * Removes the indicated reference. |
| * |
| * @param idx The index of the reference to remove |
| */ |
| public void removeReference(int idx) |
| { |
| _references.remove(idx); |
| } |
| |
| /** |
| * Determines whether this foreign key uses the given column as a local |
| * column in a reference. |
| * |
| * @param column The column to check |
| * @return <code>true</code> if a reference uses the column as a local |
| * column |
| */ |
| public boolean hasLocalColumn(Column column) |
| { |
| for (int idx = 0; idx < getReferenceCount(); idx++) |
| { |
| if (column.equals(getReference(idx).getLocalColumn())) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Determines whether this foreign key uses the given column as a foreign |
| * column in a reference. |
| * |
| * @param column The column to check |
| * @return <code>true</code> if a reference uses the column as a foreign |
| * column |
| */ |
| public boolean hasForeignColumn(Column column) |
| { |
| for (int idx = 0; idx < getReferenceCount(); idx++) |
| { |
| if (column.equals(getReference(idx).getForeignColumn())) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Determines whether this foreign key has an auto-generated associated index. |
| * |
| * @return <code>true</code> if an auto-generated index exists |
| */ |
| public boolean isAutoIndexPresent() |
| { |
| return _autoIndexPresent; |
| } |
| |
| /** |
| * Specifies whether this foreign key has an auto-generated associated index. |
| * |
| * @param autoIndexPresent <code>true</code> if an auto-generated index exists |
| */ |
| public void setAutoIndexPresent(boolean autoIndexPresent) |
| { |
| _autoIndexPresent = autoIndexPresent; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Object clone() throws CloneNotSupportedException |
| { |
| ForeignKey result = (ForeignKey)super.clone(); |
| |
| result._name = _name; |
| result._foreignTableName = _foreignTableName; |
| result._references = new ListOrderedSet(); |
| |
| for (Iterator it = _references.iterator(); it.hasNext();) |
| { |
| result._references.add(((Reference)it.next()).clone()); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean equals(Object obj) |
| { |
| if (obj instanceof ForeignKey) |
| { |
| ForeignKey otherFk = (ForeignKey)obj; |
| |
| // Note that this compares case sensitive |
| // Note also that we can simply compare the references regardless of their order |
| // (which is irrelevant for fks) because they are contained in a set |
| EqualsBuilder builder = new EqualsBuilder(); |
| |
| if ((_name != null) && (_name.length() > 0) && (otherFk._name != null) && (otherFk._name.length() > 0)) |
| { |
| builder.append(_name, otherFk._name); |
| } |
| return builder.append(_foreignTableName, otherFk._foreignTableName) |
| .append(_references, otherFk._references) |
| .isEquals(); |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| /** |
| * Compares this foreign key to the given one while ignoring the case of identifiers. |
| * |
| * @param otherFk The other foreign key |
| * @return <code>true</code> if this foreign key is equal (ignoring case) to the given one |
| */ |
| public boolean equalsIgnoreCase(ForeignKey otherFk) |
| { |
| boolean checkName = (_name != null) && (_name.length() > 0) && |
| (otherFk._name != null) && (otherFk._name.length() > 0); |
| |
| if ((!checkName || _name.equalsIgnoreCase(otherFk._name)) && |
| _foreignTableName.equalsIgnoreCase(otherFk._foreignTableName)) |
| { |
| HashSet otherRefs = new HashSet(); |
| |
| otherRefs.addAll(otherFk._references); |
| for (Iterator it = _references.iterator(); it.hasNext();) |
| { |
| Reference curLocalRef = (Reference)it.next(); |
| boolean found = false; |
| |
| for (Iterator otherIt = otherRefs.iterator(); otherIt.hasNext();) |
| { |
| Reference curOtherRef = (Reference)otherIt.next(); |
| |
| if (curLocalRef.equalsIgnoreCase(curOtherRef)) |
| { |
| otherIt.remove(); |
| found = true; |
| break; |
| } |
| } |
| if (!found) |
| { |
| return false; |
| } |
| } |
| return otherRefs.isEmpty(); |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public int hashCode() |
| { |
| return new HashCodeBuilder(17, 37).append(_name) |
| .append(_foreignTableName) |
| .append(_references) |
| .toHashCode(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public String toString() |
| { |
| StringBuffer result = new StringBuffer(); |
| |
| result.append("Foreign key ["); |
| if ((getName() != null) && (getName().length() > 0)) |
| { |
| result.append("name="); |
| result.append(getName()); |
| result.append("; "); |
| } |
| result.append("foreign table="); |
| result.append(getForeignTableName()); |
| result.append("; "); |
| result.append(getReferenceCount()); |
| result.append(" references]"); |
| |
| return result.toString(); |
| } |
| |
| /** |
| * Returns a verbose string representation of this foreign key. |
| * |
| * @return The string representation |
| */ |
| public String toVerboseString() |
| { |
| StringBuffer result = new StringBuffer(); |
| |
| result.append("ForeignK ky ["); |
| if ((getName() != null) && (getName().length() > 0)) |
| { |
| result.append("name="); |
| result.append(getName()); |
| result.append("; "); |
| } |
| result.append("foreign table="); |
| result.append(getForeignTableName()); |
| result.append("] references:"); |
| for (int idx = 0; idx < getReferenceCount(); idx++) |
| { |
| result.append(" "); |
| result.append(getReference(idx).toString()); |
| } |
| |
| return result.toString(); |
| } |
| } |