001: /**********************************************************************
002: Copyright (c) 2007 Andy Jefferson 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: Contributors:
016: ...
017: **********************************************************************/package org.jpox.metadata;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.jpox.exceptions.JPOXException;
024: import org.jpox.util.ClassUtils;
025: import org.jpox.util.JPOXLogger;
026: import org.jpox.util.Localiser;
027:
028: /**
029: * Convenience class to handle the merging of MetaData.
030: * This is used in the following situations
031: * <ul>
032: * <li>JDO : Merging ORM MetaData into JDO MetaData</li>
033: * <li>JPA : Merging Annotations information into JPA MetaData</li>
034: * <li>JDO : Merging Annotations information into JDO MetaData</li>
035: * </ul>
036: * @version $Revision: 1.17 $
037: */
038: public class MetaDataMerger {
039: protected static Localiser LOCALISER = Localiser
040: .getInstance("org.jpox.metadata.Localisation");
041:
042: /**
043: * Method to take a file JDO MetaData definition and merge in the ORM MetaData definition.
044: * If something is specified in the JDO MetaData and also in the ORM MetaData then the ORM MetaData takes precedence.
045: * @param primaryFmd The JDO Field definition (to be updated)
046: * @param ormFmd The ORM Field definition (to be merged into the JDO Field definition)
047: * @throws JPOXException if an error occurs while merging the ORM info
048: */
049: public static void mergeFileORMData(FileMetaData primaryFmd,
050: FileMetaData ormFmd) {
051: if (ormFmd == null || primaryFmd == null) {
052: return;
053: }
054: if (primaryFmd.isInitialised() || primaryFmd.isPopulated()) {
055: throw new JPOXException(LOCALISER.msg(
056: "MetaData.File.AlreadyPopulatedError", primaryFmd
057: .getFilename())).setFatal();
058: }
059: if (JPOXLogger.METADATA.isDebugEnabled()) {
060: JPOXLogger.METADATA.debug(LOCALISER.msg("044056",
061: primaryFmd.getFilename()));
062: }
063:
064: if (ormFmd.getCatalog() != null) {
065: primaryFmd.setCatalog(ormFmd.getCatalog());
066: }
067: if (ormFmd.getSchema() != null) {
068: primaryFmd.setSchema(ormFmd.getSchema());
069: }
070: }
071:
072: /**
073: * Method to take a class JDO MetaData definition and merge in the ORM MetaData definition.
074: * If something is specified in the JDO MetaData and also in the ORM MetaData then the ORM MetaData takes precedence.
075: * This is tied pretty intrinsically to the AbstractClassMetaData class and so could have been included there.
076: * @param primaryCmd The JDO Class definition (to be updated)
077: * @param ormCmd The ORM Class definition (to be merged into the JDO Class definition)
078: * @throws JPOXException if an error occurs while merging the ORM info
079: */
080: public static void mergeClassORMData(
081: AbstractClassMetaData primaryCmd,
082: AbstractClassMetaData ormCmd) {
083: if (ormCmd == null || primaryCmd == null) {
084: return;
085: }
086: if (primaryCmd.isInitialised() || primaryCmd.isPopulated()) {
087: throw new JPOXException(LOCALISER.msg("044068",
088: primaryCmd.name)).setFatal();
089: }
090: if (JPOXLogger.METADATA.isDebugEnabled()) {
091: JPOXLogger.METADATA.debug(LOCALISER.msg("044096",
092: primaryCmd.getFullClassName()));
093: }
094:
095: // Merge the attributes where they are set in the ORM
096: // A). Simple data
097: if (ormCmd.getCatalog() != null) {
098: primaryCmd.catalog = ormCmd.getCatalog();
099: }
100: if (ormCmd.getSchema() != null) {
101: primaryCmd.schema = ormCmd.getSchema();
102: }
103: if (ormCmd.getTable() != null) {
104: primaryCmd.table = ormCmd.getTable();
105: }
106: if (ormCmd.detachable) {
107: primaryCmd.detachable = true;
108: }
109: if (!ormCmd.requiresExtent) {
110: primaryCmd.requiresExtent = false;
111: }
112: if (ormCmd.embeddedOnly) {
113: primaryCmd.embeddedOnly = true;
114: }
115:
116: // B). Object data. Assume that if it exists at all we copy it all
117: if (ormCmd.getPrimaryKeyMetaData() != null) {
118: primaryCmd.setPrimaryKeyMetaData(ormCmd
119: .getPrimaryKeyMetaData());
120: }
121: if (ormCmd.getInheritanceMetaData() != null) {
122: primaryCmd.setInheritanceMetaData(ormCmd
123: .getInheritanceMetaData());
124: }
125: if (ormCmd.getIdentityMetaData() != null) {
126: primaryCmd
127: .setIdentityMetaData(ormCmd.getIdentityMetaData());
128: }
129: if (ormCmd.getVersionMetaData() != null) {
130: primaryCmd.setVersionMetaData(ormCmd.getVersionMetaData());
131: }
132: if (ormCmd.listeners != null) {
133: if (primaryCmd.listeners == null) {
134: primaryCmd.listeners = new ArrayList();
135: }
136: primaryCmd.listeners.addAll(ormCmd.listeners);
137: }
138: if (ormCmd.queries != null) {
139: if (primaryCmd.queries == null) {
140: primaryCmd.queries = new ArrayList();
141: } else {
142: primaryCmd.queries.clear();
143: }
144: primaryCmd.queries.addAll(ormCmd.queries);
145: }
146: if (ormCmd.joins.size() > 0) {
147: primaryCmd.joins.clear();
148: Iterator iter = ormCmd.joins.iterator();
149: while (iter.hasNext()) {
150: primaryCmd.addJoin((JoinMetaData) iter.next());
151: }
152: }
153: if (ormCmd.indexes.size() > 0) {
154: primaryCmd.indexes.clear();
155: Iterator iter = ormCmd.indexes.iterator();
156: while (iter.hasNext()) {
157: primaryCmd.addIndex((IndexMetaData) iter.next());
158: }
159: }
160: if (ormCmd.foreignKeys.size() > 0) {
161: primaryCmd.foreignKeys.clear();
162: Iterator iter = ormCmd.foreignKeys.iterator();
163: while (iter.hasNext()) {
164: primaryCmd.addForeignKey((ForeignKeyMetaData) iter
165: .next());
166: }
167: }
168: if (ormCmd.uniqueConstraints.size() > 0) {
169: primaryCmd.uniqueConstraints.clear();
170: Iterator iter = ormCmd.uniqueConstraints.iterator();
171: while (iter.hasNext()) {
172: primaryCmd.addUniqueConstraint((UniqueMetaData) iter
173: .next());
174: }
175: }
176: if (ormCmd.fetchGroups.size() > 0) {
177: primaryCmd.fetchGroups.clear();
178: Iterator iter = ormCmd.fetchGroups.iterator();
179: while (iter.hasNext()) {
180: primaryCmd.addFetchGroup((FetchGroupMetaData) iter
181: .next());
182: }
183: }
184:
185: // C). Add on any fields that weren't defined previously
186: for (int i = 0; i < ormCmd.getNoOfMembers(); i++) {
187: AbstractMemberMetaData ormFmd = ormCmd
188: .getMetaDataForMemberAtRelativePosition(i);
189: AbstractMemberMetaData primaryFmd = primaryCmd
190: .getMetaDataForMember(ormFmd.getName());
191: if (primaryFmd == null) {
192: // Field not specified in JDO MetaData but is in ORM MetaData
193: AbstractMemberMetaData fmd = null;
194: if (ormFmd.className != null) {
195: // Overridden field for superclass that we have no JDO field for
196: // Copy the fmd for the actual class (if any).
197: // TODO Replace this with a copy of the JDO version of the field if available
198: AbstractMemberMetaData jdoFmd = primaryCmd
199: .getMetaDataManager()
200: .readMetaDataForMember(ormFmd.className,
201: ormFmd.name);
202: if (jdoFmd == null) {
203: jdoFmd = primaryCmd.getMetaDataManager()
204: .readMetaDataForMember(
205: ormCmd.getPackageName() + "."
206: + ormFmd.className,
207: ormFmd.name);
208: }
209: if (jdoFmd != null) {
210: // Make a copy of the base field definition and merge the ORM
211: if (jdoFmd instanceof FieldMetaData) {
212: // Copy the JDO definition of the superclass since no JDO definition in this class
213: fmd = primaryCmd.getMetaDataManager()
214: .getMetaDataFactory()
215: .newFieldObject(primaryCmd, jdoFmd);
216: } else {
217: // Copy the JDO definition of the superclass since no JDO definition in this class
218: fmd = primaryCmd.getMetaDataManager()
219: .getMetaDataFactory()
220: .newPropertyObject(primaryCmd,
221: (PropertyMetaData) jdoFmd);
222: }
223: fmd.className = ormFmd.className;
224: MetaDataMerger.mergeFieldORMData(fmd, ormFmd);
225: } else {
226: // No base field definition so just copy the ORM
227: if (ormFmd instanceof FieldMetaData) {
228: // Copy ORM field since no available definition
229: fmd = primaryCmd.getMetaDataManager()
230: .getMetaDataFactory()
231: .newFieldObject(primaryCmd, ormFmd);
232: } else {
233: // Copy ORM property since no available definition
234: fmd = primaryCmd.getMetaDataManager()
235: .getMetaDataFactory()
236: .newPropertyObject(primaryCmd,
237: (PropertyMetaData) ormFmd);
238: }
239: fmd.className = ormFmd.className;
240: }
241: } else {
242: // Create a copy of the ORM field MetaData and add to JDO MetaData
243: if (ormFmd instanceof FieldMetaData) {
244: fmd = primaryCmd.getMetaDataManager()
245: .getMetaDataFactory().newFieldObject(
246: primaryCmd, ormFmd);
247: } else {
248: fmd = primaryCmd.getMetaDataManager()
249: .getMetaDataFactory()
250: .newPropertyObject(primaryCmd,
251: (PropertyMetaData) ormFmd);
252: }
253: }
254: primaryCmd.addMember(fmd);
255: } else {
256: // Field specified in JDO MetaData so merge in ORM MetaData
257: MetaDataMerger.mergeFieldORMData(primaryFmd, ormFmd);
258: }
259: }
260:
261: // Add any extensions supplied in the ORM MetaData
262: ExtensionMetaData[] ormExtensions = ormCmd.getExtensions();
263: if (ormExtensions != null) {
264: for (int i = 0; i < ormExtensions.length; i++) {
265: primaryCmd.addExtension(ormExtensions[i].vendorName,
266: ormExtensions[i].key, ormExtensions[i].value);
267: }
268: }
269: }
270:
271: /**
272: * Method to take a field JDO MetaData definition and merge in the ORM MetaData definition.
273: * This is tied pretty intrinsically to the AbstractMemberMetaData class and so could have been included there.
274: * @param primaryFmd The JDO Field definition (to be updated)
275: * @param ormFmd The ORM Field definition (to be merged into the JDO Class definition)
276: * @throws JPOXException if an error occurs while merging the ORM info
277: */
278: public static void mergeFieldORMData(
279: AbstractMemberMetaData primaryFmd,
280: AbstractMemberMetaData ormFmd) {
281: if (ormFmd == null || primaryFmd == null) {
282: return;
283: }
284:
285: if (primaryFmd.isInitialised() || primaryFmd.isPopulated()) {
286: throw new JPOXException(LOCALISER.msg("044107",
287: primaryFmd.name, ormFmd.getAbstractClassMetaData()
288: .getFullClassName())).setFatal();
289: }
290:
291: if (ormFmd.className != null) {
292: // If the ORM is an overriding field, make sure we have the (real) class name
293: primaryFmd.className = ormFmd.className;
294: }
295: if (ormFmd.container != null) {
296: primaryFmd.container = ormFmd.container;
297: primaryFmd.container.parent = primaryFmd;
298: }
299:
300: // Update our O/R mapping details
301: if (ormFmd.defaultFetchGroup != null) {
302: primaryFmd.defaultFetchGroup = ormFmd.defaultFetchGroup;
303: }
304: if (primaryFmd.primaryKey == Boolean.FALSE
305: && ormFmd.primaryKey == Boolean.TRUE) {
306: primaryFmd.primaryKey = ClassUtils.booleanValueOf(ormFmd
307: .isPrimaryKey());
308: }
309: if (ormFmd.getTable() != null) {
310: primaryFmd.table = ormFmd.getTable();
311: }
312: if (ormFmd.getCatalog() != null) {
313: primaryFmd.catalog = ormFmd.getCatalog();
314: }
315: if (ormFmd.getSchema() != null) {
316: primaryFmd.schema = ormFmd.getSchema();
317: }
318: if (ormFmd.getColumn() != null) {
319: primaryFmd.column = ormFmd.getColumn();
320: }
321: if (ormFmd.dependent != null) {
322: primaryFmd.dependent = ormFmd.dependent;
323: }
324: if (ormFmd.getMappedBy() != null) {
325: primaryFmd.mappedBy = ormFmd.getMappedBy();
326: }
327: if (ormFmd.getValueStrategy() != null) {
328: primaryFmd.valueStrategy = ormFmd.getValueStrategy();
329: }
330: if (ormFmd.getSequence() != null) {
331: primaryFmd.sequence = ormFmd.getSequence();
332: }
333: if (ormFmd.indexed != null) {
334: primaryFmd.indexed = ormFmd.indexed;
335: }
336: if (ormFmd.nullValue != NullValue.NONE) {
337: primaryFmd.nullValue = ormFmd.nullValue;
338: }
339:
340: if (ormFmd.getJoinMetaData() != null) {
341: primaryFmd.setJoinMetaData(ormFmd.joinMetaData);
342: }
343: if (ormFmd.getEmbeddedMetaData() != null) {
344: primaryFmd.setEmbeddedMetaData(ormFmd.embeddedMetaData);
345: }
346: if (ormFmd.getElementMetaData() != null) {
347: primaryFmd.setElementMetaData(ormFmd.elementMetaData);
348: }
349: if (ormFmd.getKeyMetaData() != null) {
350: primaryFmd.setKeyMetaData(ormFmd.keyMetaData);
351: }
352: if (ormFmd.getValueMetaData() != null) {
353: primaryFmd.setValueMetaData(ormFmd.valueMetaData);
354: }
355: if (ormFmd.getOrderMetaData() != null) {
356: primaryFmd.setOrderMetaData(ormFmd.orderMetaData);
357: }
358: if (ormFmd.getForeignKeyMetaData() != null) {
359: primaryFmd.foreignKeyMetaData = ormFmd
360: .getForeignKeyMetaData();
361: if (primaryFmd.foreignKeyMetaData != null) {
362: primaryFmd.foreignKeyMetaData.parent = primaryFmd;
363: }
364: }
365: if (ormFmd.getIndexMetaData() != null) {
366: primaryFmd.indexMetaData = ormFmd.getIndexMetaData();
367: if (primaryFmd.indexMetaData != null) {
368: primaryFmd.indexMetaData.parent = primaryFmd;
369: }
370: }
371: if (ormFmd.getUniqueMetaData() != null) {
372: primaryFmd.uniqueMetaData = ormFmd.getUniqueMetaData();
373: if (primaryFmd.uniqueMetaData != null) {
374: primaryFmd.uniqueMetaData.parent = primaryFmd;
375: }
376: }
377:
378: ColumnMetaData[] ormColumns = ormFmd.getColumnMetaData();
379: if (ormColumns != null) {
380: primaryFmd.columns.clear();
381: for (int i = 0; i < ormColumns.length; i++) {
382: primaryFmd.columns.add(ormColumns[i]);
383: }
384: }
385:
386: // Add any extensions supplied in the ORM file
387: ExtensionMetaData[] ormExtensions = ormFmd.getExtensions();
388: if (ormExtensions != null) {
389: for (int i = 0; i < ormExtensions.length; i++) {
390: primaryFmd.addExtension(ormExtensions[i].vendorName,
391: ormExtensions[i].key, ormExtensions[i].value);
392: }
393: }
394: }
395:
396: /**
397: * Method to take a class MetaData definition and merge in any Annotations "MetaData" definition.
398: * If something is specified in the MetaData and also in the annotations then the MetaData takes precedence.
399: * This is tied pretty intrinsically to the AbstractClassMetaData class and so could have been included there.
400: * @param primaryCmd The MetaData definition (to be updated)
401: * @param annotCmd The annotations Class definition (to be merged into the MetaData definition)
402: * @throws JPOXException if an error occurs while merging the annotations info
403: */
404: public static void mergeClassAnnotationsData(
405: AbstractClassMetaData primaryCmd,
406: AbstractClassMetaData annotCmd) {
407: if (annotCmd == null || primaryCmd == null) {
408: return;
409: }
410: if (primaryCmd.isInitialised() || primaryCmd.isPopulated()) {
411: throw new JPOXException(LOCALISER.msg("044068",
412: primaryCmd.name)).setFatal();
413: }
414:
415: if (JPOXLogger.METADATA.isDebugEnabled()) {
416: JPOXLogger.METADATA.debug(LOCALISER.msg("044095",
417: primaryCmd.getFullClassName()));
418: }
419:
420: // Merge the attributes where they arent set on the primary and are on the annotations
421: // A). Simple attributes
422: if (primaryCmd.entityName == null
423: && annotCmd.entityName != null) {
424: primaryCmd.entityName = annotCmd.entityName;
425: }
426: if (annotCmd.detachable) {
427: primaryCmd.detachable = true;
428: }
429: if (!annotCmd.requiresExtent) {
430: primaryCmd.requiresExtent = false;
431: }
432: if (annotCmd.embeddedOnly) {
433: primaryCmd.embeddedOnly = true;
434: }
435: if (primaryCmd.identityType == null
436: && annotCmd.identityType != null) {
437: primaryCmd.identityType = annotCmd.identityType;
438: }
439: if (primaryCmd.objectidClass == null
440: && annotCmd.objectidClass != null) {
441: primaryCmd.objectidClass = annotCmd.objectidClass;
442: }
443:
444: if (primaryCmd.catalog == null && annotCmd.catalog != null) {
445: primaryCmd.catalog = annotCmd.catalog;
446: }
447: if (primaryCmd.schema == null && annotCmd.schema != null) {
448: primaryCmd.schema = annotCmd.schema;
449: }
450: if (primaryCmd.table == null && annotCmd.table != null) {
451: primaryCmd.table = annotCmd.table;
452: }
453:
454: // B). Object data - assume that we copy it all if not set at all
455: if (primaryCmd.versionMetaData == null
456: && annotCmd.versionMetaData != null) {
457: primaryCmd.setVersionMetaData(annotCmd.versionMetaData);
458: }
459: if (primaryCmd.identityMetaData == null
460: && annotCmd.identityMetaData != null) {
461: primaryCmd.setIdentityMetaData(annotCmd.identityMetaData);
462: }
463: if (primaryCmd.inheritanceMetaData == null
464: && annotCmd.inheritanceMetaData != null) {
465: primaryCmd
466: .setInheritanceMetaData(annotCmd.inheritanceMetaData);
467: }
468: if (primaryCmd.primaryKeyMetaData == null
469: && annotCmd.primaryKeyMetaData != null) {
470: primaryCmd
471: .setPrimaryKeyMetaData(annotCmd.primaryKeyMetaData);
472: }
473: if (primaryCmd.listeners == null && annotCmd.listeners != null) {
474: // No MetaData listeners so just use those of the annotations
475: Iterator iter = annotCmd.listeners.iterator();
476: while (iter.hasNext()) {
477: primaryCmd.addListener((EventListenerMetaData) iter
478: .next());
479: }
480: } else if (primaryCmd.listeners != null
481: && annotCmd.listeners != null) {
482: // We have listeners in MetaData and also in Annotations. Listeners can be for the actual class, or for
483: // any EntityListener, so use overriding in those two groups
484: if (primaryCmd.getListenerForClass(primaryCmd
485: .getFullClassName()) == null) {
486: // Primary has just Listeners and no callbacks
487: if (annotCmd.getListenerForClass(primaryCmd
488: .getFullClassName()) != null) {
489: // Add on callbacks from annotations
490: primaryCmd.addListener(annotCmd
491: .getListenerForClass(primaryCmd
492: .getFullClassName()));
493: }
494: } else if (primaryCmd.getListenerForClass(primaryCmd
495: .getFullClassName()) != null
496: && primaryCmd.getListeners().size() == 1) {
497: // Primary has just callbacks and no listeners so take any listeners from annotations
498: List annotListeners = annotCmd.getListeners();
499: Iterator annotIter = annotListeners.iterator();
500: while (annotIter.hasNext()) {
501: EventListenerMetaData elmd = (EventListenerMetaData) annotIter
502: .next();
503: if (!elmd.getClassName().equals(
504: primaryCmd.getFullClassName())) {
505: // Add on listeners from annotations
506: primaryCmd.addListener(elmd);
507: }
508: }
509: }
510: }
511: if (annotCmd.excludeDefaultListeners != null
512: && primaryCmd.excludeDefaultListeners == null) {
513: primaryCmd.excludeDefaultListeners = annotCmd.excludeDefaultListeners;
514: }
515: if (annotCmd.excludeSuperClassListeners != null
516: && primaryCmd.excludeSuperClassListeners == null) {
517: primaryCmd.excludeSuperClassListeners = annotCmd.excludeSuperClassListeners;
518: }
519:
520: if (primaryCmd.queries == null && annotCmd.queries != null) {
521: Iterator iter = annotCmd.queries.iterator();
522: while (iter.hasNext()) {
523: primaryCmd.addQuery((QueryMetaData) iter.next());
524: }
525: }
526: if (primaryCmd.joins.size() == 0 && annotCmd.joins.size() > 0) {
527: Iterator iter = annotCmd.joins.iterator();
528: while (iter.hasNext()) {
529: primaryCmd.addJoin((JoinMetaData) iter.next());
530: }
531: }
532: if (primaryCmd.indexes.size() == 0
533: && annotCmd.indexes.size() > 0) {
534: Iterator iter = annotCmd.indexes.iterator();
535: while (iter.hasNext()) {
536: primaryCmd.addIndex((IndexMetaData) iter.next());
537: }
538: }
539: if (primaryCmd.foreignKeys.size() == 0
540: && annotCmd.foreignKeys.size() > 0) {
541: Iterator iter = annotCmd.foreignKeys.iterator();
542: while (iter.hasNext()) {
543: primaryCmd.addForeignKey((ForeignKeyMetaData) iter
544: .next());
545: }
546: }
547: if (primaryCmd.uniqueConstraints.size() == 0
548: && annotCmd.uniqueConstraints.size() > 0) {
549: Iterator iter = annotCmd.uniqueConstraints.iterator();
550: while (iter.hasNext()) {
551: primaryCmd.addUniqueConstraint((UniqueMetaData) iter
552: .next());
553: }
554: }
555: if (primaryCmd.fetchGroups.size() == 0
556: && annotCmd.fetchGroups.size() > 0) {
557: Iterator iter = annotCmd.fetchGroups.iterator();
558: while (iter.hasNext()) {
559: primaryCmd.addFetchGroup((FetchGroupMetaData) iter
560: .next());
561: }
562: }
563:
564: // C). Add on any fields that weren't defined previously
565: for (int i = 0; i < annotCmd.getNoOfMembers(); i++) {
566: AbstractMemberMetaData annotFmd = annotCmd
567: .getMetaDataForMemberAtRelativePosition(i);
568: AbstractMemberMetaData primaryFmd = primaryCmd
569: .getMetaDataForMember(annotFmd.getName());
570: if (primaryFmd == null) {
571: // Field not specified in MetaData but is in Annotations
572: AbstractMemberMetaData fmd = null;
573: if (annotFmd.className != null) {
574: // Overridden field for superclass that we have no MetaData field for
575: // Copy the fmd for the actual class (if any).
576: // TODO Replace this with a copy of the metadata version of the field if available
577: AbstractMemberMetaData baseFmd = primaryCmd
578: .getMetaDataManager()
579: .readMetaDataForMember(annotFmd.className,
580: annotFmd.name);
581: if (baseFmd == null) {
582: baseFmd = primaryCmd.getMetaDataManager()
583: .readMetaDataForMember(
584: annotCmd.getPackageName() + "."
585: + annotFmd.className,
586: annotFmd.name);
587: }
588: if (baseFmd != null) {
589: // Make a copy of the base field definition and merge the Annotations
590: if (baseFmd instanceof FieldMetaData) {
591: // Copy the JDO definition of the superclass since no JDO definition in this class
592: fmd = primaryCmd
593: .getMetaDataManager()
594: .getMetaDataFactory()
595: .newFieldObject(primaryCmd, baseFmd);
596: } else {
597: // Copy the JDO definition of the superclass since no JDO definition in this class
598: fmd = primaryCmd.getMetaDataManager()
599: .getMetaDataFactory()
600: .newPropertyObject(primaryCmd,
601: (PropertyMetaData) baseFmd);
602: }
603: fmd.className = annotFmd.className;
604: MetaDataMerger.mergeFieldAnnotationsData(fmd,
605: annotFmd);
606: } else {
607: // No base field definition so just copy the Annotations
608: if (annotFmd instanceof FieldMetaData) {
609: // Create default field since no available definition
610: fmd = primaryCmd.getMetaDataManager()
611: .getMetaDataFactory()
612: .newFieldObject(primaryCmd,
613: annotFmd);
614: } else {
615: // Create default property since no available definition
616: fmd = primaryCmd
617: .getMetaDataManager()
618: .getMetaDataFactory()
619: .newPropertyObject(primaryCmd,
620: (PropertyMetaData) annotFmd);
621: }
622: fmd.className = annotFmd.className;
623: }
624: } else {
625: // Create a copy of the Annotations "MetaData" and add
626: if (annotFmd instanceof FieldMetaData) {
627: // Annotation definition of the field
628: // creates a new fmd with this as parent and add to fields
629: fmd = primaryCmd.getMetaDataManager()
630: .getMetaDataFactory().newFieldObject(
631: primaryCmd, annotFmd);
632: } else {
633: // Annotation definition of the property
634: // creates a new fmd with this as parent and add to fields
635: fmd = primaryCmd.getMetaDataManager()
636: .getMetaDataFactory()
637: .newPropertyObject(primaryCmd,
638: (PropertyMetaData) annotFmd);
639: }
640: }
641: primaryCmd.addMember(fmd);
642: } else {
643: // Field specified in JDO MetaData so merge in Annotations
644: MetaDataMerger.mergeFieldAnnotationsData(primaryFmd,
645: annotFmd);
646: }
647: }
648:
649: // Add any extensions supplied in the annotations
650: ExtensionMetaData[] ormExtensions = annotCmd.getExtensions();
651: if (ormExtensions != null) {
652: for (int i = 0; i < ormExtensions.length; i++) {
653: primaryCmd.addExtension(ormExtensions[i].vendorName,
654: ormExtensions[i].key, ormExtensions[i].value);
655: }
656: }
657: }
658:
659: /**
660: * Method to take a field MetaData definition and merge in the Annotations "MetaData" definition.
661: * This is tied pretty intrinsically to the AbstractMemberMetaData class and so could have been included there.
662: * @param primaryFmd The MetaData Field definition (to be updated)
663: * @param annotFmd The Annotations "MetaData" Field definition (to be merged into the MetaData definition)
664: * @throws JPOXException if an error occurs while merging the annotation info
665: */
666: public static void mergeFieldAnnotationsData(
667: AbstractMemberMetaData primaryFmd,
668: AbstractMemberMetaData annotFmd) {
669: if (annotFmd == null || primaryFmd == null) {
670: return;
671: }
672:
673: if (primaryFmd.isInitialised() || primaryFmd.isPopulated()) {
674: throw new JPOXException(LOCALISER.msg("044107",
675: primaryFmd.name, annotFmd
676: .getAbstractClassMetaData()
677: .getFullClassName())).setFatal();
678: }
679:
680: if (primaryFmd.className == null && annotFmd.className != null) {
681: // If the Annotation is an overriding field, make sure we have the (real) class name
682: primaryFmd.className = annotFmd.className;
683: }
684: if (primaryFmd.container == null && annotFmd.container != null) {
685: primaryFmd.container = annotFmd.container;
686: primaryFmd.container.parent = primaryFmd;
687: }
688:
689: if (annotFmd.persistenceModifier != FieldPersistenceModifier.DEFAULT
690: && primaryFmd.persistenceModifier == FieldPersistenceModifier.DEFAULT) {
691: primaryFmd.persistenceModifier = annotFmd.persistenceModifier;
692: }
693: if (annotFmd.defaultFetchGroup != null
694: && primaryFmd.defaultFetchGroup == null) {
695: primaryFmd.defaultFetchGroup = annotFmd.defaultFetchGroup;
696: }
697: if (annotFmd.primaryKey != null) {
698: // "primary-key" will always have a value in XML so we just override if the annotation had it set
699: // This means that we don't allow overriding of the primary-key via XML
700: primaryFmd.primaryKey = annotFmd.primaryKey;
701: }
702: if (primaryFmd.table == null && annotFmd.table != null) {
703: primaryFmd.table = annotFmd.table;
704: }
705: if (primaryFmd.catalog == null && annotFmd.catalog != null) {
706: primaryFmd.catalog = annotFmd.catalog;
707: }
708: if (primaryFmd.schema == null && annotFmd.schema != null) {
709: primaryFmd.schema = annotFmd.schema;
710: }
711: if (primaryFmd.column == null && annotFmd.column != null) {
712: primaryFmd.column = annotFmd.column;
713: }
714: if (primaryFmd.dependent == null && annotFmd.dependent != null) {
715: primaryFmd.dependent = annotFmd.dependent;
716: }
717: if (primaryFmd.mappedBy == null && annotFmd.mappedBy != null) {
718: primaryFmd.mappedBy = annotFmd.mappedBy;
719: }
720: if (primaryFmd.valueStrategy == null
721: && annotFmd.valueStrategy != null) {
722: primaryFmd.valueStrategy = annotFmd.valueStrategy;
723: }
724: if (primaryFmd.sequence == null && annotFmd.sequence != null) {
725: primaryFmd.sequence = annotFmd.sequence;
726: }
727: if (primaryFmd.indexed == null && annotFmd.indexed != null) {
728: primaryFmd.indexed = annotFmd.indexed;
729: }
730: if (annotFmd.nullValue != NullValue.NONE) {
731: primaryFmd.nullValue = annotFmd.nullValue;
732: }
733:
734: if (primaryFmd.joinMetaData == null
735: && annotFmd.joinMetaData != null) {
736: primaryFmd.setJoinMetaData(annotFmd.joinMetaData);
737: }
738: if (primaryFmd.embeddedMetaData == null
739: && annotFmd.embeddedMetaData != null) {
740: primaryFmd.setEmbeddedMetaData(annotFmd.embeddedMetaData);
741: }
742: if (primaryFmd.elementMetaData == null
743: && annotFmd.elementMetaData != null) {
744: primaryFmd.setElementMetaData(annotFmd.elementMetaData);
745: }
746: if (primaryFmd.keyMetaData == null
747: && annotFmd.keyMetaData != null) {
748: primaryFmd.setKeyMetaData(annotFmd.keyMetaData);
749: }
750: if (primaryFmd.valueMetaData == null
751: && annotFmd.valueMetaData != null) {
752: primaryFmd.setValueMetaData(annotFmd.valueMetaData);
753: }
754: if (primaryFmd.orderMetaData == null
755: && annotFmd.orderMetaData != null) {
756: primaryFmd.setOrderMetaData(annotFmd.orderMetaData);
757: }
758: if (primaryFmd.foreignKeyMetaData == null
759: && annotFmd.foreignKeyMetaData != null) {
760: primaryFmd.foreignKeyMetaData = annotFmd.foreignKeyMetaData;
761: if (primaryFmd.foreignKeyMetaData != null) {
762: primaryFmd.foreignKeyMetaData.parent = primaryFmd;
763: }
764: }
765: if (primaryFmd.indexMetaData == null
766: && annotFmd.indexMetaData != null) {
767: primaryFmd.indexMetaData = annotFmd.indexMetaData;
768: if (primaryFmd.indexMetaData != null) {
769: primaryFmd.indexMetaData.parent = primaryFmd;
770: }
771: }
772: if (primaryFmd.uniqueMetaData == null
773: && annotFmd.uniqueMetaData != null) {
774: primaryFmd.uniqueMetaData = annotFmd.uniqueMetaData;
775: if (primaryFmd.uniqueMetaData != null) {
776: primaryFmd.uniqueMetaData.parent = primaryFmd;
777: }
778: }
779:
780: if (primaryFmd.columns.size() == 0
781: && annotFmd.columns.size() > 0) {
782: // Columns specified in annotations but not in MetaData
783: ColumnMetaData[] annotColumns = annotFmd
784: .getColumnMetaData();
785: if (annotColumns != null) {
786: for (int i = 0; i < annotColumns.length; i++) {
787: primaryFmd.columns.add(annotColumns[i]);
788: }
789: }
790: }
791:
792: // Add any extensions supplied in the annotations
793: ExtensionMetaData[] annotExtensions = annotFmd.getExtensions();
794: if (annotExtensions != null) {
795: for (int i = 0; i < annotExtensions.length; i++) {
796: primaryFmd.addExtension(annotExtensions[i].vendorName,
797: annotExtensions[i].key,
798: annotExtensions[i].value);
799: }
800: }
801: }
802: }
|