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 - addition of table name
018: 2005 Andy Jefferson - added primary-key, unique, and others
019: ...
020: **********************************************************************/package org.jpox.metadata;
021:
022: import java.util.ArrayList;
023: import java.util.List;
024:
025: import org.jpox.util.StringUtils;
026:
027: /**
028: * Secondary tables and join tables are mapped using a join condition that
029: * associates a column or columns in the secondary or join table with a column
030: * or columns in the primary table, typically the primary tables primary key
031: * columns. Column elements used for relationship mapping or join conditions
032: * specify the column name and optionally the target column name. The target
033: * column name is the name of the column in the associated table corresponding
034: * to the named column. The target column name is optional when the target
035: * column is the single primary key column of the associated table.
036: *
037: * @since 1.1
038: * @version $Revision: 1.24 $
039: */
040: public class JoinMetaData extends MetaData implements
041: ColumnMetaDataContainer {
042: /** the foreign-key element. */
043: ForeignKeyMetaData foreignKeyMetaData;
044:
045: /** the index element. */
046: IndexMetaData indexMetaData;
047:
048: /** the unique element. */
049: UniqueMetaData uniqueMetaData;
050:
051: /** PrimaryKey MetaData */
052: protected PrimaryKeyMetaData primaryKeyMetaData;
053:
054: /** column elements */
055: final List columns = new ArrayList();
056:
057: /** if is outer join. Outer joins return all elements from at least one of the sides joined. */
058: Boolean outer;
059:
060: /** the table name. */
061: String table;
062:
063: /** the catalog name. */
064: String catalog;
065:
066: /** the schema name. */
067: String schema;
068:
069: /** the column name. */
070: String columnName;
071:
072: /** the foreign-key column name. */
073: String foreignKey;
074:
075: /** The indexing value */
076: protected IndexedValue indexed = null;
077:
078: /** Whether to add a unique constraint. */
079: protected final boolean uniqueConstraint;
080:
081: // -------------------------------------------------------------------------
082: // Fields below here are not represented in the output MetaData. They are
083: // for use internally in the operation of the JDO system. The majority are
084: // for convenience to save iterating through the fields since the fields
085: // are fixed once initialised.
086:
087: /**
088: * Contains the metadata for column
089: */
090: protected ColumnMetaData[] columnMetaData;
091:
092: /**
093: * Constructor to create a copy of the passed JoinMetaData but with the passed parent.
094: * @param parent Parent
095: * @param joinmd Existing join metadata to copy
096: */
097: public JoinMetaData(MetaData parent, JoinMetaData joinmd) {
098: super (parent);
099: this .table = joinmd.table;
100: this .catalog = joinmd.catalog;
101: this .schema = joinmd.schema;
102: this .columnName = joinmd.columnName;
103: this .outer = joinmd.outer;
104: this .indexed = joinmd.indexed;
105: this .uniqueConstraint = joinmd.uniqueConstraint;
106: for (int i = 0; i < joinmd.columns.size(); i++) {
107: addColumn(new ColumnMetaData(this ,
108: (ColumnMetaData) joinmd.columns.get(i)));
109: }
110: }
111:
112: /**
113: * Constructor for the Join.
114: * @param parent The parent
115: * @param table The table name
116: * @param catalog The catalog name
117: * @param schema The schema name
118: * @param columnName The column name
119: * @param outer Whether it is an outer join
120: * @param fkDeleteAction Delete action on the FK
121: * @param indexed whether the join is indexed
122: * @param unique whether the join is unique
123: */
124: public JoinMetaData(final MetaData parent, final String table,
125: final String catalog, final String schema,
126: final String columnName, final String outer,
127: final String fkDeleteAction, String indexed, String unique) {
128: super (parent);
129:
130: if (table != null && parent instanceof AbstractMemberMetaData) {
131: // "table" has been specified but this join is within <field> or <property> so is not applicable
132: //TODO fix message for property and field
133: throw new InvalidMetaDataException(LOCALISER, "044130",
134: ((AbstractMemberMetaData) parent)
135: .getFullFieldName());
136: }
137:
138: this .table = (StringUtils.isWhitespace(table) ? null : table);
139: this .catalog = (StringUtils.isWhitespace(catalog) ? null
140: : catalog);
141: this .schema = (StringUtils.isWhitespace(schema) ? null : schema);
142: this .columnName = (StringUtils.isWhitespace(columnName) ? null
143: : columnName);
144:
145: if (outer != null) {
146: if (outer.equalsIgnoreCase("true")) {
147: this .outer = Boolean.TRUE;
148: } else if (outer.equalsIgnoreCase("false")) {
149: this .outer = Boolean.FALSE;
150: }
151: }
152:
153: if (!StringUtils.isWhitespace(fkDeleteAction)) {
154: this .foreignKeyMetaData = new ForeignKeyMetaData(null,
155: null, null, null, fkDeleteAction, null);
156: }
157:
158: this .indexed = IndexedValue.getIndexedValue(indexed);
159:
160: if (unique != null && unique.equalsIgnoreCase("true")) {
161: uniqueConstraint = true;
162: } else {
163: uniqueConstraint = false;
164: }
165: }
166:
167: /**
168: * Method to initialise the object, creating internal convenience arrays.
169: * Initialises all sub-objects.
170: */
171: public void initialise() {
172: // Cater for user specifying column name, or columns
173: if (columns.size() == 0 && columnName != null) {
174: columnMetaData = new ColumnMetaData[1];
175: columnMetaData[0] = new ColumnMetaData(this , columnName);
176: columnMetaData[0].initialise();
177: } else {
178: columnMetaData = new ColumnMetaData[columns.size()];
179: for (int i = 0; i < columnMetaData.length; i++) {
180: columnMetaData[i] = (ColumnMetaData) columns.get(i);
181: columnMetaData[i].initialise();
182: }
183: }
184:
185: if (foreignKeyMetaData != null) {
186: foreignKeyMetaData.initialise();
187: }
188:
189: // Interpret the "indexed" value to create our IndexMetaData where it wasn't specified that way
190: if (indexMetaData == null && columnMetaData != null
191: && indexed != null && indexed != IndexedValue.FALSE) {
192: indexMetaData = new IndexMetaData(null, null,
193: (indexed == IndexedValue.UNIQUE) ? "true" : "false");
194: for (int i = 0; i < columnMetaData.length; i++) {
195: indexMetaData.addColumn(columnMetaData[i]);
196: }
197: }
198: if (indexMetaData != null) {
199: indexMetaData.initialise();
200: }
201:
202: if (uniqueMetaData == null && uniqueConstraint) {
203: uniqueMetaData = new UniqueMetaData(null, columnName, null);
204: for (int i = 0; i < columnMetaData.length; i++) {
205: uniqueMetaData.addColumn(columnMetaData[i]);
206: }
207: }
208: if (uniqueMetaData != null) {
209: uniqueMetaData.initialise();
210: }
211:
212: if (primaryKeyMetaData != null) {
213: primaryKeyMetaData.initialise();
214: }
215:
216: setInitialised();
217: }
218:
219: // ------------------------------- Accessors -------------------------------
220:
221: /**
222: * Add a new ColumnMetaData element
223: * @param colmd The ColumnMetaData to add
224: */
225: public void addColumn(ColumnMetaData colmd) {
226: columns.add(colmd);
227: colmd.parent = this ;
228: }
229:
230: /**
231: * Accessor for the table name
232: * @return Returns the table name
233: */
234: public final String getTable() {
235: return table;
236: }
237:
238: /**
239: * Accessor for the catalog name
240: * @return Returns the catalog name
241: */
242: public final String getCatalog() {
243: return catalog;
244: }
245:
246: /**
247: * Accessor for the schema name
248: * @return Returns the schema name
249: */
250: public final String getSchema() {
251: return schema;
252: }
253:
254: /**
255: * Accessor for the column name
256: * @return Returns the column.
257: */
258: public final String getColumnName() {
259: return columnName;
260: }
261:
262: /**
263: * Accessor for columnMetaData
264: * @return Returns the columnMetaData.
265: */
266: public final ColumnMetaData[] getColumnMetaData() {
267: return columnMetaData;
268: }
269:
270: /**
271: * @return Returns the outer.
272: */
273: public final boolean isOuter() {
274: if (outer == null) {
275: return false;
276: } else {
277: return outer.booleanValue();
278: }
279: }
280:
281: /**
282: * @return Returns the indexMetaData.
283: */
284: public final IndexMetaData getIndexMetaData() {
285: return indexMetaData;
286: }
287:
288: /**
289: * @return Returns the uniquexMetaData.
290: */
291: public final UniqueMetaData getUniqueMetaData() {
292: return uniqueMetaData;
293: }
294:
295: /**
296: * @return Returns the foreignKeyMetaData.
297: */
298: public final ForeignKeyMetaData getForeignKeyMetaData() {
299: return foreignKeyMetaData;
300: }
301:
302: /**
303: * Accessor for primaryKeyMetaData
304: * @return Returns the primaryKey MetaData.
305: */
306: public final PrimaryKeyMetaData getPrimaryKeyMetaData() {
307: return primaryKeyMetaData;
308: }
309:
310: // ----------------------------- Mutators ----------------------------------
311:
312: /**
313: * @param foreignKeyMetaData The foreignKeyMetaData to set.
314: */
315: public final void setForeignKeyMetaData(
316: ForeignKeyMetaData foreignKeyMetaData) {
317: this .foreignKeyMetaData = foreignKeyMetaData;
318: }
319:
320: /**
321: * @param indexMetaData The indexMetaData to set.
322: */
323: public final void setIndexMetaData(IndexMetaData indexMetaData) {
324: this .indexMetaData = indexMetaData;
325: }
326:
327: /**
328: * @param uniqueMetaData The uniqueMetaData to set.
329: */
330: public final void setUniqueMetaData(UniqueMetaData uniqueMetaData) {
331: this .uniqueMetaData = uniqueMetaData;
332: }
333:
334: /**
335: * Mutator for the PrimaryKey MetaData.
336: * @param primaryKeyMetaData The PrimaryKey MetaData to set.
337: */
338: public final void setPrimaryKeyMetaData(
339: PrimaryKeyMetaData primaryKeyMetaData) {
340: this .primaryKeyMetaData = primaryKeyMetaData;
341: }
342:
343: // ----------------------------- Utilities ---------------------------------
344:
345: /**
346: * Returns a string representation of the object using a prefix
347: * @param prefix prefix string
348: * @param indent indent string
349: * @return a string representation of the object.
350: */
351: public String toString(String prefix, String indent) {
352: StringBuffer sb = new StringBuffer();
353: sb.append(prefix).append("<join");
354: if (table != null) {
355: sb.append(" table=\"" + table + "\"");
356: }
357: if (columnName != null) {
358: sb.append(" column=\"" + columnName + "\"");
359: }
360: if (outer != null) {
361: sb.append(" outer=\"" + outer + "\"");
362: }
363: sb.append(">\n");
364:
365: // Primary-key
366: if (primaryKeyMetaData != null) {
367: sb.append(primaryKeyMetaData.toString(prefix + indent,
368: indent));
369: }
370:
371: // Add columns
372: if (columnMetaData != null) {
373: for (int i = 0; i < columnMetaData.length; i++) {
374: sb.append(columnMetaData[i].toString(prefix + indent,
375: indent));
376: }
377: }
378:
379: // Foreign-key
380: if (foreignKeyMetaData != null) {
381: sb.append(foreignKeyMetaData.toString(prefix + indent,
382: indent));
383: }
384:
385: // Index
386: if (indexMetaData != null) {
387: sb.append(indexMetaData.toString(prefix + indent, indent));
388: }
389:
390: // Unique
391: if (uniqueMetaData != null) {
392: sb.append(uniqueMetaData.toString(prefix + indent, indent));
393: }
394:
395: // Add extensions
396: sb.append(super .toString(prefix + indent, indent));
397:
398: sb.append(prefix).append("</join>\n");
399: return sb.toString();
400: }
401: }
|