001: /**********************************************************************
002: Copyright (c) 2004 Erik Bengtson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015:
016: Contributors:
017: 2004 Andy Jefferson- added toString(), "column", MetaData, javadocs
018: ...
019: **********************************************************************/package org.jpox.metadata;
020:
021: /**
022: * Foreign keys in metadata serve two quite different purposes. First, when
023: * generating schema, the foreign key element identifies foreign keys to be
024: * generated. Second, when using the database, foreign key elements identify
025: * foreign keys that are assumed to exist in the database. This is important for
026: * the runtime to properly order insert, update, and delete statements to avoid
027: * constraint violations. A foreign-key element can be contained by a field,
028: * element, key, value, or join element, if all of the columns mapped are to be
029: * part of the same foreign key. A foreign-key element can be contained within a
030: * class element. In this case, the column elements are mapped elsewhere, and
031: * the column elements contained in the foreign-key element have only the column
032: * name.
033: *
034: * @since 1.1
035: * @version $Revision: 1.21 $
036: */
037: public class ForeignKeyMetaData extends AbstractConstraintMetaData
038: implements ColumnMetaDataContainer {
039: /**
040: * The unique attribute specifies whether the foreign key constraint is
041: * defined to be a unique constraint as well. This is most often used with
042: * one-to-one mappings.
043: */
044: protected boolean unique;
045:
046: /**
047: * The deferred attribute specifies whether the foreign key constraint is
048: * defined to be checked only at commit time.
049: */
050: protected boolean deferred;
051:
052: /**
053: * Foreign keys represent a consistency constraint in the database that must
054: * be maintained. The user can specify by the value of the delete-action
055: * attribute what happens if the target row of a foreign key is deleted.
056: */
057: protected ForeignKeyAction deleteAction;
058:
059: /**
060: * Foreign keys represent a consistency constraint in the database that must
061: * be maintained. The user can specify by the update-action attribute what
062: * happens if the target row of a foreign key is updated.
063: */
064: protected ForeignKeyAction updateAction;
065:
066: /**
067: * Constructor to create a copy of the passed metadata using the provided parent.
068: * @param fkmd The metadata to copy
069: */
070: public ForeignKeyMetaData(ForeignKeyMetaData fkmd) {
071: super (null, fkmd.name, fkmd.table); // Ignore parent
072:
073: this .deferred = fkmd.deferred;
074: this .deleteAction = fkmd.deleteAction;
075: this .updateAction = fkmd.updateAction;
076: this .unique = fkmd.unique;
077:
078: if (fkmd.isInitialised()) {
079: if (fkmd.getMemberMetaData() != null) {
080: for (int i = 0; i < fkmd.getMemberMetaData().length; i++) {
081: if (fkmd.getMemberMetaData()[i] instanceof PropertyMetaData) {
082: addMember(new PropertyMetaData(this ,
083: (PropertyMetaData) fkmd
084: .getMemberMetaData()[i]));
085: } else {
086: addMember(new FieldMetaData(this , fkmd
087: .getMemberMetaData()[i]));
088: }
089: }
090: }
091: if (fkmd.getColumnMetaData() != null) {
092: for (int i = 0; i < fkmd.getColumnMetaData().length; i++) {
093: addColumn(new ColumnMetaData(this , fkmd
094: .getColumnMetaData()[i]));
095: }
096: }
097: } else {
098: for (int i = 0; i < fkmd.members.size(); i++) {
099: if (fkmd.members.get(i) instanceof PropertyMetaData) {
100: addMember(new PropertyMetaData(this ,
101: (PropertyMetaData) fkmd.members.get(i)));
102: } else {
103: addMember(new FieldMetaData(this ,
104: (AbstractMemberMetaData) fkmd.members
105: .get(i)));
106: }
107: }
108: for (int i = 0; i < fkmd.columns.size(); i++) {
109: addColumn(new ColumnMetaData(this ,
110: (ColumnMetaData) fkmd.columns.get(i)));
111: }
112: }
113: }
114:
115: /**
116: * Constructor.
117: * @param name Name of the foreign key
118: * @param table Table to apply the FK to
119: * @param unique Whether the key is unique
120: * @param deferred Whether the key is deferred
121: * @param delete_action Action to perform on deletion
122: * @param update_action Action to perform on update
123: */
124: public ForeignKeyMetaData(final String name, final String table,
125: final String unique, final String deferred,
126: final String delete_action, final String update_action) {
127: super (null, name, table); // Ignore parent
128:
129: if (unique != null) {
130: if (unique.equalsIgnoreCase("true")) {
131: this .unique = true;
132: } else if (unique.equalsIgnoreCase("false")) {
133: this .unique = false;
134: }
135: }
136: if (deferred != null) {
137: if (deferred.equalsIgnoreCase("true")) {
138: this .deferred = true;
139: } else if (deferred.equalsIgnoreCase("false")) {
140: this .deferred = false;
141: }
142: }
143:
144: this .deleteAction = ForeignKeyAction
145: .getForeignKeyAction(delete_action);
146: this .updateAction = ForeignKeyAction
147: .getForeignKeyAction(update_action);
148: }
149:
150: /**
151: * Method to initialise the object, setting up all internal arrays.
152: * Initialises all sub-objects.
153: */
154: public void initialise() {
155: if (isInitialised()) {
156: return;
157: }
158:
159: // Set up the columnMetaData
160: if (members.size() == 0) {
161: memberMetaData = null;
162: } else {
163: memberMetaData = new AbstractMemberMetaData[members.size()];
164: for (int i = 0; i < memberMetaData.length; i++) {
165: memberMetaData[i] = (AbstractMemberMetaData) members
166: .get(i);
167: memberMetaData[i].initialise();
168: }
169: }
170:
171: // Set up the columnMetaData
172: if (columns.size() == 0) {
173: columnMetaData = null;
174: } else {
175: columnMetaData = new ColumnMetaData[columns.size()];
176: for (int i = 0; i < columnMetaData.length; i++) {
177: columnMetaData[i] = (ColumnMetaData) columns.get(i);
178: columnMetaData[i].initialise();
179: }
180: }
181:
182: // Clear out parsing data
183: columns.clear();
184: columns = null;
185: members.clear();
186: members = null;
187:
188: setInitialised();
189: }
190:
191: // ---------------------------- Mutators -----------------------------------
192:
193: /**
194: * Accessor for whether the FK is deferred
195: * @return Returns the deferred.
196: */
197: public final boolean isDeferred() {
198: return deferred;
199: }
200:
201: /**
202: * Accessor for the delete action
203: * @return Returns the deleteAction.
204: */
205: public final ForeignKeyAction getDeleteAction() {
206: return deleteAction;
207: }
208:
209: /**
210: * Accessor for the unique flag
211: * @return Returns the unique.
212: */
213: public final boolean isUnique() {
214: return unique;
215: }
216:
217: /**
218: * Accessor for the update action
219: * @return Returns the updateAction.
220: */
221: public final ForeignKeyAction getUpdateAction() {
222: return updateAction;
223: }
224:
225: // ---------------------------- Utilities ----------------------------------
226:
227: /**
228: * Returns a string representation of the object using a prefix
229: * This can be used as part of a facility to output a MetaData file.
230: * @param prefix prefix string
231: * @param indent indent string
232: * @return a string representation of the object.
233: */
234: public String toString(String prefix, String indent) {
235: // Field needs outputting so generate metadata
236: StringBuffer sb = new StringBuffer();
237: sb.append(prefix).append(
238: "<foreign-key deferred=\"" + deferred + "\"\n");
239: sb.append(prefix).append(" unique=\"" + unique + "\"");
240: if (updateAction != null) {
241: sb.append("\n").append(prefix).append(
242: " update-action=\"" + updateAction + "\"");
243: }
244: if (deleteAction != null) {
245: sb.append("\n").append(prefix).append(
246: " delete-action=\"" + deleteAction + "\"");
247: }
248: if (table != null) {
249: sb.append("\n").append(prefix).append(
250: " table=\"" + table + "\"");
251: }
252: if (name != null) {
253: sb.append("\n").append(prefix).append(
254: " name=\"" + name + "\"");
255: }
256: sb.append(">\n");
257:
258: // Add fields
259: if (memberMetaData != null) {
260: for (int i = 0; i < memberMetaData.length; i++) {
261: sb.append(memberMetaData[i].toString(prefix + indent,
262: indent));
263: }
264: }
265:
266: // Add columns
267: if (columnMetaData != null) {
268: for (int i = 0; i < columnMetaData.length; i++) {
269: sb.append(columnMetaData[i].toString(prefix + indent,
270: indent));
271: }
272: }
273:
274: // Add extensions
275: sb.append(super .toString(prefix + indent, indent));
276:
277: sb.append(prefix).append("</foreign-key>\n");
278: return sb.toString();
279: }
280: }
|