0001: /**********************************************************************
0002: Copyright (c) 2005 Andy Jefferson and others. All rights reserved.
0003: Licensed under the Apache License, Version 2.0 (the "License");
0004: you may not use this file except in compliance with the License.
0005: You may obtain a copy of the License at
0006:
0007: http://www.apache.org/licenses/LICENSE-2.0
0008:
0009: Unless required by applicable law or agreed to in writing, software
0010: distributed under the License is distributed on an "AS IS" BASIS,
0011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012: See the License for the specific language governing permissions and
0013: limitations under the License.
0014:
0015:
0016: Contributors:
0017: ...
0018: **********************************************************************/package org.jpox.metadata;
0019:
0020: import java.util.ArrayList;
0021: import java.util.Collection;
0022: import java.util.HashMap;
0023: import java.util.HashSet;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028:
0029: import org.jpox.ClassLoaderResolver;
0030: import org.jpox.api.ApiAdapter;
0031: import org.jpox.exceptions.ClassNotResolvedException;
0032: import org.jpox.exceptions.JPOXException;
0033: import org.jpox.exceptions.JPOXUserException;
0034: import org.jpox.util.ClassUtils;
0035: import org.jpox.util.JPOXLogger;
0036: import org.jpox.util.Localiser;
0037: import org.jpox.util.MacroString;
0038: import org.jpox.util.StringUtils;
0039: import org.jpox.util.ViewUtils;
0040:
0041: /**
0042: * Abstract representation of the MetaData of a class/interface.
0043: * Has a parent PackageMetaData that can contain the metadata for several classes/interfaces.
0044: * Is extended by ClassMetaData and InterfaceMetaData.
0045: * Of the things that it contains the main one are the "members" which are the MetaData for
0046: * all fields and properties that are persistable.
0047: * @since 1.1
0048: * @version $Revision: 1.98 $
0049: */
0050: public abstract class AbstractClassMetaData extends MetaData {
0051: protected static Localiser LOCALISER_API = Localiser
0052: .getInstance("org.jpox.Localisation");
0053:
0054: /** Class name */
0055: protected final String name;
0056:
0057: /** Entity name. Required by JPA1 §4.3.1 for accessing this class in queries. */
0058: protected String entityName;
0059:
0060: /** Identity-type tag value. */
0061: protected IdentityType identityType = IdentityType.DATASTORE;
0062:
0063: /** persistence-modifier tag value. */
0064: protected ClassPersistenceModifier persistenceModifier = null;
0065:
0066: /** persistence-capable-superclass tag value (deprecated). */
0067: protected String persistenceCapableSuperclass;
0068:
0069: /** objectid-class tag value. */
0070: protected String objectidClass;
0071:
0072: /** requires-extent tag value. */
0073: protected boolean requiresExtent = true;
0074:
0075: /** detachable tag value. */
0076: protected boolean detachable = false;
0077:
0078: /** embedded-only tag value. */
0079: protected boolean embeddedOnly = false;
0080:
0081: /** Catalog name (O/R mapping). */
0082: protected String catalog;
0083:
0084: /** Schema name (O/R mapping). */
0085: protected String schema;
0086:
0087: /** Table name (O/R mapping). This may be of the form "[database].[catalog].[schema].table" */
0088: protected String table;
0089:
0090: /** Full name (e.g org.jpox.MyClass) */
0091: protected final String fullName;
0092:
0093: /** Version MetaData */
0094: protected VersionMetaData versionMetaData;
0095:
0096: /** Identity MetaData */
0097: protected IdentityMetaData identityMetaData;
0098:
0099: /** Flag whether the identity was specified by the user. */
0100: protected boolean identitySpecified = false;
0101:
0102: /** Inheritance MetaData */
0103: protected InheritanceMetaData inheritanceMetaData;
0104:
0105: /** PrimaryKey MetaData */
0106: protected PrimaryKeyMetaData primaryKeyMetaData;
0107:
0108: /** EventListeners. Use a list to preserve ordering. */
0109: protected List listeners = null;
0110:
0111: /** Flag to exclude superclass listeners. */
0112: protected Boolean excludeSuperClassListeners = null;
0113:
0114: /** Flag to exclude default listeners. */
0115: protected Boolean excludeDefaultListeners = null;
0116:
0117: /** Fetch Groups for this class. Available to be used in queries and when detaching. */
0118: protected FetchGroupMetaData[] fetchGroupMetaData;
0119:
0120: /** Convenience lookup map of fetch group by the name. */
0121: protected Map fetchGroupMetaDataByName;
0122:
0123: /** Class MetaData for the Persistence-Capable superclass (if any) */
0124: protected AbstractClassMetaData pcSuperclassMetaData = null;
0125:
0126: /** Flag for whether the MetaData here is complete without annotations. Used by JPA. */
0127: protected boolean metaDataComplete = false;
0128:
0129: /** Named queries */
0130: protected Collection queries = null;
0131:
0132: /** List of query result MetaData defined for this file. */
0133: protected Collection queryResultMetaData = null;
0134:
0135: /** JoinMetaData */
0136: protected JoinMetaData[] joinMetaData;
0137:
0138: /** IndexMetaData */
0139: protected IndexMetaData[] indexMetaData;
0140:
0141: /** ForeignKeyMetaData */
0142: protected ForeignKeyMetaData[] foreignKeyMetaData;
0143:
0144: /** UniqueMetaData */
0145: protected UniqueMetaData[] uniqueMetaData;
0146:
0147: /** List of members (fields/properties). */
0148: protected List members = new ArrayList();
0149:
0150: /** The columns that are present in the datastore yet not mapped to fields in this class. */
0151: protected List unmappedColumns = null;
0152:
0153: // These fields are only used when the MetaData is read by the parser and elements are dynamically added to
0154: // the other elements. At initialise() they are cleared and nulled so shouldn't be used internally.
0155:
0156: /** List of joins */
0157: protected List joins = new ArrayList();
0158:
0159: /** List of foreign-key */
0160: protected List foreignKeys = new ArrayList();
0161:
0162: /** List of indexes */
0163: protected List indexes = new ArrayList();
0164:
0165: /** List of uniqueConstraints */
0166: protected List uniqueConstraints = new ArrayList();
0167:
0168: /** List of fetch-group */
0169: protected List fetchGroups = new ArrayList();
0170:
0171: // Fields below here are not represented in the output MetaData. They are for use internally in the operation of the system.
0172: // The majority are for convenience to save iterating through the fields since the fields are fixed once initialised.
0173:
0174: /**
0175: * Managed fields/properties of this class. Contains the same AbstractMemberMetaData objects as are in "members".
0176: * Doesnt include any overridden members which are stored separately. All fields will return true to
0177: * "fmd.isJdoField()".
0178: */
0179: protected AbstractMemberMetaData[] managedMembers;
0180:
0181: /** Fields/properties for superclasses that are overridden in this class. */
0182: protected AbstractMemberMetaData[] overriddenMembers;
0183:
0184: /** Position numbers of members mapped by the name of the field/property. */
0185: protected Map memberPositionsByName;
0186:
0187: /** Positions of all fields/properties (inc superclasses). */
0188: protected int[] allMemberPositions;
0189:
0190: /** Positions of the primary-key fields/properties (inc superclasses). */
0191: protected int[] pkMemberPositions;
0192:
0193: /** Positions of the non-primary-key fields/properties (inc superclasses). */
0194: protected int[] nonPkMemberPositions;
0195:
0196: /** Flags of the non-primary key fields/properties (inc superclasses). */
0197: protected boolean[] nonPkMemberFlags;
0198:
0199: /** Positions of the default-fetch-group fields/properties (inc superclasses). */
0200: protected int[] dfgMemberPositions;
0201:
0202: /** Flags of the default-fetch-group state for all fields/properties. */
0203: protected boolean[] dfgMemberFlags;
0204:
0205: /** Positions of the SCO mutable fields/properties (inc superclasses). */
0206: protected int[] scoMutableMemberPositions;
0207:
0208: /** Flags of the SCO mutable state for all fields/properties. */
0209: protected boolean[] scoMutableMemberFlags;
0210:
0211: /** Postions of the PersistenceCapable fields/properties (inc superclasses). */
0212: protected int[] persistenceCapableMemberPositions;
0213:
0214: /** No of managed fields/properties in superclasses, that are inherited by this class. */
0215: protected int noOfInheritedManagedMembers = 0;
0216:
0217: /** if this PersistenceCapable class uses SingleFieldIdentity */
0218: protected boolean usesSingleFieldIdentityClass;
0219:
0220: /** number of managed fields/properties from this class plus inherited classes. */
0221: protected int memberCount;
0222:
0223: protected boolean implementationOfPersistentDefinition = false;
0224:
0225: // ----------------------------- Constructors ------------------------------
0226:
0227: /**
0228: * Constructor.
0229: * Takes the basic string information found in an XML MetaData file.
0230: * @param parent The package to which this class/interface belongs
0231: * @param name Name of class
0232: * @param identityType identity-type flag
0233: * @param objectidClass Primary key class name
0234: * @param requiresExtent Whether the class requires an extent
0235: * @param detachable Whether the class can be detached
0236: * @param embeddedOnly embedded-only tag
0237: * @param modifier persistence-modifier tag
0238: * @param catalog The catalog name default for this class
0239: * @param schema The schema name default for this class
0240: * @param table table to store the class in
0241: * @param entityName the entity name required by JPA §4.3.1
0242: */
0243: protected AbstractClassMetaData(final PackageMetaData parent,
0244: final String name, final String identityType,
0245: final String objectidClass, final String requiresExtent,
0246: final String detachable, final String embeddedOnly,
0247: final String modifier,
0248: final String persistenceCapableSuperclass,
0249: final String catalog, final String schema,
0250: final String table, final String entityName) {
0251: super (parent);
0252:
0253: if (name == null) {
0254: throw new JPOXUserException(LOCALISER.msg("044041", "name",
0255: getPackageName(), "class"));
0256: }
0257: if (StringUtils.isWhitespace(name)) {
0258: throw new InvalidMetaDataException(LOCALISER, "044061",
0259: parent.name);
0260: }
0261:
0262: this .name = name;
0263: this .fullName = ClassUtils.createFullClassName(parent.name,
0264: name);
0265: this .objectidClass = (StringUtils.isWhitespace(objectidClass) ? null
0266: : ClassUtils.createFullClassName(parent.name,
0267: objectidClass));
0268: this .identityType = IdentityType.getIdentityType(identityType);
0269: this .requiresExtent = (requiresExtent != null && requiresExtent
0270: .equalsIgnoreCase("false")) ? false : true;
0271: this .detachable = (detachable != null && detachable
0272: .equalsIgnoreCase("true")) ? true : false;
0273: this .embeddedOnly = (embeddedOnly != null && embeddedOnly
0274: .equalsIgnoreCase("true")) ? true : false;
0275: this .catalog = (StringUtils.isWhitespace(catalog) ? null
0276: : catalog);
0277: this .schema = (StringUtils.isWhitespace(schema) ? null : schema);
0278: this .table = (StringUtils.isWhitespace(table) ? null : table);
0279: this .persistenceModifier = ClassPersistenceModifier
0280: .getClassPersistenceModifier(modifier);
0281: this .entityName = (entityName != null ? entityName : null);
0282: this .persistenceCapableSuperclass = (StringUtils
0283: .isWhitespace(persistenceCapableSuperclass) ? null
0284: : ClassUtils.createFullClassName(parent.name,
0285: persistenceCapableSuperclass));
0286: }
0287:
0288: /** Implementation of "persistent-interface" needing table setting from superclass. */
0289: protected transient boolean persistentInterfaceImplNeedingTableFromSuperclass = false;
0290:
0291: /** Implementation of "persistent-interface" needing table setting from subclass. */
0292: protected transient boolean persistentInterfaceImplNeedingTableFromSubclass = false;
0293:
0294: /**
0295: * Constructor for creating the ClassMetaData for an implementation of a "persistent-interface".
0296: * @param imd MetaData for the "persistent-interface"
0297: * @param implClassName Name of the implementation class
0298: * @param copyMembers Whether to copy the fields/properties of the interface too
0299: */
0300: public AbstractClassMetaData(InterfaceMetaData imd,
0301: String implClassName, boolean copyMembers) {
0302: this (
0303: (PackageMetaData) imd.parent,
0304: implClassName,
0305: imd.identityType.toString(),
0306: imd.objectidClass,
0307: imd.requiresExtent ? "true" : "false",
0308: imd.detachable ? "true" : "false",
0309: imd.embeddedOnly ? "true" : "false",
0310: ClassPersistenceModifier.PERSISTENCE_CAPABLE.toString(),
0311: null, // Ignore class inheritance since we are just implementing this interface
0312: imd.catalog, imd.schema, imd.table, imd.entityName);
0313: implementationOfPersistentDefinition = true;
0314:
0315: if (copyMembers) {
0316: copyMembersFromInterface(imd);
0317: }
0318:
0319: setVersionMetaData(imd.versionMetaData);
0320: setIdentityMetaData(imd.identityMetaData);
0321: setPrimaryKeyMetaData(imd.primaryKeyMetaData);
0322:
0323: if (imd.inheritanceMetaData != null) {
0324: if (imd.inheritanceMetaData.getStrategyValue() == InheritanceStrategy.SUPERCLASS_TABLE) {
0325: // Flag the table as requiring setting based on the next superclass
0326: persistentInterfaceImplNeedingTableFromSuperclass = true;
0327: } else if (imd.getInheritanceMetaData().getStrategyValue() == InheritanceStrategy.SUBCLASS_TABLE) {
0328: // Flag the table as requiring setting based on the next subclass
0329: persistentInterfaceImplNeedingTableFromSubclass = true;
0330: }
0331:
0332: InheritanceMetaData inhmd = new InheritanceMetaData(this ,
0333: InheritanceStrategy.NEW_TABLE.toString());
0334: if (imd.inheritanceMetaData.getStrategyValue() == InheritanceStrategy.SUPERCLASS_TABLE) {
0335: AbstractClassMetaData acmd = imd
0336: .getSuperAbstractClassMetaData();
0337: while (acmd != null) {
0338: if (acmd.getInheritanceMetaData() != null) {
0339: if (acmd.getInheritanceMetaData()
0340: .getStrategyValue() == InheritanceStrategy.NEW_TABLE) {
0341: if (acmd.getInheritanceMetaData()
0342: .getDiscriminatorMetaData() != null) {
0343: inhmd
0344: .setDiscriminatorMetaData(new DiscriminatorMetaData(
0345: inhmd,
0346: acmd
0347: .getInheritanceMetaData()
0348: .getDiscriminatorMetaData()));
0349: }
0350: inhmd.setJoinMetaData(acmd
0351: .getInheritanceMetaData()
0352: .getJoinMetaData());
0353: break;
0354: }
0355: }
0356: acmd = acmd.getSuperAbstractClassMetaData();
0357: }
0358: } else if (imd.inheritanceMetaData.getStrategyValue() == InheritanceStrategy.NEW_TABLE) {
0359: if (imd.getInheritanceMetaData()
0360: .getDiscriminatorMetaData() != null) {
0361: inhmd
0362: .setDiscriminatorMetaData(new DiscriminatorMetaData(
0363: inhmd, imd.getInheritanceMetaData()
0364: .getDiscriminatorMetaData()));
0365: }
0366: inhmd.setJoinMetaData(imd.getInheritanceMetaData()
0367: .getJoinMetaData());
0368: }
0369: setInheritanceMetaData(inhmd);
0370: }
0371:
0372: if (imd.joinMetaData != null) {
0373: for (int i = 0; i < imd.joinMetaData.length; i++) {
0374: addJoin(imd.joinMetaData[i]);
0375: }
0376: }
0377: if (imd.foreignKeyMetaData != null) {
0378: for (int i = 0; i < imd.foreignKeyMetaData.length; i++) {
0379: addForeignKey(imd.foreignKeyMetaData[i]);
0380: }
0381: }
0382: if (imd.indexMetaData != null) {
0383: for (int i = 0; i < imd.indexMetaData.length; i++) {
0384: addIndex(imd.indexMetaData[i]);
0385: }
0386: }
0387: if (imd.uniqueMetaData != null) {
0388: for (int i = 0; i < imd.uniqueMetaData.length; i++) {
0389: addUniqueConstraint(imd.uniqueMetaData[i]);
0390: }
0391: }
0392: if (imd.fetchGroupMetaData != null) {
0393: for (int i = 0; i < imd.fetchGroupMetaData.length; i++) {
0394: addFetchGroup(imd.fetchGroupMetaData[i]);
0395: }
0396: }
0397: if (queries != null) {
0398: Iterator iter = queries.iterator();
0399: {
0400: addQuery((QueryMetaData) iter.next());
0401: }
0402: }
0403:
0404: if (imd.listeners != null) {
0405: if (listeners == null) {
0406: listeners = new ArrayList();
0407: }
0408: listeners.addAll(imd.listeners);
0409: }
0410: }
0411:
0412: /**
0413: * Constructor for creating the ClassMetaData for an implementation of a "persistent-abstract-class".
0414: * @param cmd MetaData for the implementation of the "persistent-abstract-class"
0415: * @param implClassName Name of the implementation class
0416: */
0417: public AbstractClassMetaData(ClassMetaData cmd, String implClassName) {
0418: this (
0419: (PackageMetaData) cmd.parent,
0420: implClassName,
0421: null,
0422: null,
0423: cmd.requiresExtent ? "true" : "false",
0424: cmd.detachable ? "true" : "false",
0425: cmd.embeddedOnly ? "true" : "false",
0426: ClassPersistenceModifier.PERSISTENCE_CAPABLE.toString(),
0427: cmd.getFullClassName(), cmd.catalog, cmd.schema,
0428: cmd.table, cmd.entityName);
0429: implementationOfPersistentDefinition = true;
0430:
0431: // Mark all artificial fields (added in implementing the abstract class) as non-persistent
0432: for (int i = 0; i < cmd.getMemberCount(); i++) {
0433: FieldMetaData fmd = new FieldMetaData(this , cmd
0434: .getMetaDataForManagedMemberAtAbsolutePosition(i));
0435: fmd.persistenceModifier = FieldPersistenceModifier.NONE;
0436: fmd.primaryKey = Boolean.FALSE;
0437: fmd.defaultFetchGroup = Boolean.FALSE;
0438: addMember(fmd);
0439: }
0440: }
0441:
0442: /**
0443: * Return whether this MetaData is for an implementation of a persistent definition.
0444: * This could be an implementation of a persistent interface or a persistent abstract-class.
0445: * @return Whether this is an implementation
0446: */
0447: public boolean isImplementationOfPersistentDefinition() {
0448: return implementationOfPersistentDefinition;
0449: }
0450:
0451: /**
0452: * Convenience method to copy the properties from an existing interface.
0453: * Adds FieldMetaData for each PropertyMetaData on the persistent-interface.
0454: * @param imd The interface that we copy from
0455: */
0456: protected void copyMembersFromInterface(InterfaceMetaData imd) {
0457: for (int i = 0; i < imd.getMemberCount(); i++) {
0458: // generate FieldMetaData out of PropertyMetaData
0459: FieldMetaData fmd = new FieldMetaData(this , imd
0460: .getMetaDataForManagedMemberAtAbsolutePosition(i));
0461: addMember(fmd);
0462: }
0463: }
0464:
0465: /**
0466: * Method to check whether the Meta-Data has been initialised.
0467: * @throws JDOFatalInternalException Thrown if the Meta-Data hasn't been initialised.
0468: **/
0469: protected void checkInitialised() {
0470: if (!isInitialised()) {
0471: throw new JPOXException(LOCALISER.msg("044069", fullName))
0472: .setFatal();
0473: }
0474: }
0475:
0476: /**
0477: * Method to check whether the Meta-Data has been populated.
0478: * @throws JPOXException Thrown if the Meta-Data hasn't been populated.
0479: **/
0480: protected void checkPopulated() {
0481: if (!isPopulated() && !isInitialised()) {
0482: throw new JPOXException(LOCALISER.msg("044070", fullName))
0483: .setFatal();
0484: }
0485: }
0486:
0487: /**
0488: * Load the persistent interface/class
0489: * @param clr the ClassLoader
0490: * @param primary the primary ClassLoader to use (or null)
0491: * @return the loaded class
0492: */
0493: protected Class loadClass(ClassLoaderResolver clr,
0494: ClassLoader primary) {
0495: // No class loader, so use default
0496: if (clr == null) {
0497: JPOXLogger.METADATA.warn(LOCALISER.msg("044067", fullName));
0498: clr = getMetaDataManager().getOMFContext()
0499: .getClassLoaderResolver(null);
0500: }
0501:
0502: // Load the class we are modelling
0503: Class cls;
0504: try {
0505: cls = clr.classForName(fullName, primary, false);
0506: } catch (ClassNotResolvedException cnre) {
0507: JPOXLogger.METADATA
0508: .error(LOCALISER.msg("044080", fullName));
0509: throw new InvalidMetaDataException(LOCALISER, "044080",
0510: fullName);
0511: }
0512: if (cls == null) {
0513: JPOXLogger.METADATA
0514: .error(LOCALISER.msg("044080", fullName));
0515: throw new InvalidMetaDataException(LOCALISER, "044080",
0516: fullName);
0517: }
0518: return cls;
0519: }
0520:
0521: /**
0522: * Determines the identity based on MetaData defaults or user defined MetaData
0523: */
0524: protected void determineIdentity() {
0525: // Provide a default identity type if not supplied
0526: if (this .identityType == null) {
0527: if (objectidClass != null) {
0528: // PK provided so we use application-identity
0529: identityType = IdentityType.APPLICATION;
0530: } else {
0531: int noOfPkKeys = 0;
0532: Iterator memberIter = members.iterator();
0533: while (memberIter.hasNext()) {
0534: AbstractMemberMetaData mmd = (AbstractMemberMetaData) memberIter
0535: .next();
0536: if (mmd.isPrimaryKey()) {
0537: noOfPkKeys++;
0538: }
0539: }
0540: if (noOfPkKeys == 1) {
0541: // 1 PK so we use application-identity (SingleFieldIdentity)
0542: identityType = IdentityType.APPLICATION; // SingleFieldIdentity
0543: } else {
0544: // Use datastore-identity
0545: identityType = IdentityType.DATASTORE;
0546: }
0547: }
0548: }
0549: }
0550:
0551: /**
0552: * Determine the super PersistenceCapable class.
0553: * The persistence-capable-superclass attribute is deprecated for JDO2.0.
0554: * The attribute will be ignored so metadata files from previous releases can be used.
0555: * The persistenceCapableSuperclass we use will be retrieved from the class itself.
0556: * @param clr The ClassLoaderResolver
0557: * @param cls This class
0558: * @throws InvalidMetaDataException if the declared <code>persistence-capable-superclass</code> super class
0559: * cannot be loaded by the <code>clr</code>.
0560: * @throws InvalidMetaDataException if the declared <code>persistence-capable-superclass</code> has
0561: * no reachable MetaData
0562: */
0563: protected void determineSuperClassName(ClassLoaderResolver clr,
0564: Class cls) {
0565: String realPcSuperclassName = null;
0566:
0567: Collection super classes = null;
0568: if (cls.isInterface()) {
0569: super classes = ClassUtils.getSuperinterfaces(cls);
0570: } else {
0571: super classes = ClassUtils.getSuperclasses(cls);
0572: }
0573:
0574: if (!super classes.isEmpty()) {
0575: Iterator super classesIter = super classes.iterator();
0576: while (super classesIter.hasNext()) {
0577: Class super class = (Class) super classesIter.next();
0578: AbstractClassMetaData super Cmd = getMetaDataManager()
0579: .getMetaDataForClassInternal(super class, clr);
0580: if (super Cmd != null
0581: && super Cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
0582: realPcSuperclassName = super class.getName();
0583: break;
0584: }
0585: }
0586: }
0587:
0588: if (persistenceCapableSuperclass != null
0589: && !persistenceCapableSuperclass
0590: .equals(realPcSuperclassName)) {
0591: // Valifies the defined persistenceCapableSuperclass
0592: try {
0593: AbstractClassMetaData super Cmd = getMetaDataManager()
0594: .getMetaDataForClassInternal(
0595: clr
0596: .classForName(persistenceCapableSuperclass),
0597: clr);
0598: if (super Cmd == null
0599: || super Cmd.getPersistenceModifier() != ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
0600: throw new InvalidMetaDataException(LOCALISER,
0601: "044083", name,
0602: persistenceCapableSuperclass);
0603: }
0604: } catch (ClassNotResolvedException cnre) {
0605: throw new InvalidMetaDataException(LOCALISER, "044088",
0606: name, persistenceCapableSuperclass);
0607: }
0608: if (realPcSuperclassName != null) {
0609: throw new InvalidMetaDataException(LOCALISER, "044087",
0610: name, realPcSuperclassName,
0611: persistenceCapableSuperclass);
0612: } else {
0613: // The defined persistenceCapableSuperclass could NOT have been a superclass
0614: // of this class, otherwise it would have been equal to the realPcSuperclassName.
0615: throw new InvalidMetaDataException(LOCALISER, "044082",
0616: name, persistenceCapableSuperclass);
0617: }
0618: }
0619: if (persistenceCapableSuperclass == null
0620: && realPcSuperclassName != null) {
0621: persistenceCapableSuperclass = realPcSuperclassName;
0622: if (JPOXLogger.METADATA.isDebugEnabled()) {
0623: JPOXLogger.METADATA.debug(LOCALISER.msg("044089", name,
0624: persistenceCapableSuperclass));
0625: }
0626: }
0627: validateSuperClass(clr, cls, super classes);
0628: }
0629:
0630: /**
0631: * Check if the previously determined super class implements PersistenceCapable and has
0632: * reachable MetaData file. The super class MetaData is populated if not yet populated or initilised.
0633: * @param clr the ClassLoaderResolver
0634: * @param cls This class
0635: * @param superclasses A List of super classes of this class, starting from the least derived super class up to the root class
0636: * @throws InvalidMetaDataException if the super class cannot be loaded by the <code>clr</code>.
0637: * @throws InvalidMetaDataException if the declared <code>persistence-capable-superclass</code> is not
0638: * actually assignable from <code>cls</code>
0639: * @throws InvalidMetaDataException if any of the super classes implements <code>PersistenceCapable</code> interface,
0640: * but the MetaData says that class is not persistent.
0641: */
0642: private void validateSuperClass(ClassLoaderResolver clr, Class cls,
0643: Collection super classes) {
0644: // "persistence-capable-superclass"
0645: // Check that the class can be loaded, and is a true superclass
0646: if (persistenceCapableSuperclass != null) {
0647: Class pcsc = null;
0648: try {
0649: // Load using same class loader resolver as this class
0650: pcsc = clr.classForName(persistenceCapableSuperclass);
0651: } catch (ClassNotResolvedException cnre) {
0652: throw new InvalidMetaDataException(LOCALISER, "044081",
0653: name, persistenceCapableSuperclass);
0654: }
0655:
0656: if (persistenceCapableSuperclass.equals(fullName)
0657: || !(pcsc.isAssignableFrom(cls))) {
0658: throw new InvalidMetaDataException(LOCALISER, "044082",
0659: name, persistenceCapableSuperclass);
0660: }
0661:
0662: // Retrieve the Meta-Data for the superclass
0663: if (getMetaDataManager() != null) {
0664: // JPOX normal operation will have a MetaDataManager and so we
0665: // can ask that for the MetaData of the superclass.
0666: pcSuperclassMetaData = getMetaDataManager()
0667: .getMetaDataForClassInternal(pcsc, clr);
0668: if (pcSuperclassMetaData == null) {
0669: // Superclass isn't persistence capable since no MetaData
0670: // could be found.
0671: throw new InvalidMetaDataException(LOCALISER,
0672: "044083", name,
0673: persistenceCapableSuperclass);
0674: }
0675: } else {
0676: // The enhancer doesn't need MetaDataManager so we just
0677: // navigate up to the FileMetaData and find it.
0678: // NOTE : assumes that the class is specified in the same file
0679: String super class_pkg_name = persistenceCapableSuperclass
0680: .substring(0, persistenceCapableSuperclass
0681: .lastIndexOf('.'));
0682: PackageMetaData pmd = getPackageMetaData()
0683: .getFileMetaData().getPackage(
0684: super class_pkg_name);
0685: if (pmd != null) {
0686: String super class_class_name = persistenceCapableSuperclass
0687: .substring(persistenceCapableSuperclass
0688: .lastIndexOf('.') + 1);
0689: pcSuperclassMetaData = pmd
0690: .getClass(super class_class_name);
0691: }
0692: }
0693: if (pcSuperclassMetaData == null) {
0694: throw new InvalidMetaDataException(LOCALISER, "044084",
0695: name, persistenceCapableSuperclass);
0696: }
0697: if (!pcSuperclassMetaData.isPopulated()
0698: && !pcSuperclassMetaData.isInitialised()) {
0699: // Populate the superclass since we will be needing it
0700: pcSuperclassMetaData
0701: .populate(clr, cls.getClassLoader());
0702: }
0703: } else {
0704: // Check that none of our real superclasses is PersistenceCapable since this
0705: // class hasn't declared a PC superclass
0706: if (!super classes.isEmpty()) {
0707: Iterator super classesIter = super classes.iterator();
0708: while (super classesIter.hasNext()) {
0709: Class super class = (Class) super classesIter.next();
0710: AbstractClassMetaData super Cmd = getMetaDataManager()
0711: .getMetaDataForClassInternal(super class,
0712: clr);
0713: if (super Cmd != null
0714: && super Cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
0715: throw new InvalidMetaDataException(LOCALISER,
0716: "044091", fullName, super class
0717: .getName());
0718: }
0719: }
0720: }
0721: }
0722: }
0723:
0724: /**
0725: * Check for conflicts on super class and this class MetaData identity
0726: * @throws InvalidMetaDataException if the user tries to overwrite a super class identity / strategy
0727: */
0728: protected void validateUserInputForIdentity() {
0729: // Check that the user isn't trying to override the datastore-identity strategy!
0730: if (pcSuperclassMetaData != null) {
0731: AbstractClassMetaData baseCmd = getBaseAbstractClassMetaData();
0732: IdentityMetaData imd = baseCmd.getIdentityMetaData();
0733: if (baseCmd.identitySpecified
0734: && identitySpecified
0735: && imd != null
0736: && imd.getValueStrategy() != null
0737: && identityMetaData != null
0738: && identityMetaData.getValueStrategy() != null
0739: && identityMetaData.getValueStrategy() != imd
0740: .getValueStrategy()) {
0741: throw new InvalidMetaDataException(LOCALISER, "044094",
0742: fullName, identityMetaData.getValueStrategy(),
0743: imd.getValueStrategy());
0744: }
0745: }
0746: }
0747:
0748: /**
0749: * Convenience accessor for the AbstractClassMetaData of the base object in this hierarchy.
0750: * @return The AbstractClassMetaData for the base object.
0751: */
0752: public AbstractClassMetaData getBaseAbstractClassMetaData() {
0753: if (pcSuperclassMetaData != null) {
0754: return pcSuperclassMetaData.getBaseAbstractClassMetaData();
0755: } else {
0756: return this ;
0757: }
0758: }
0759:
0760: /**
0761: * Inherit detach settings from super classes. This class is forced to be detachable if the super classes is.
0762: */
0763: protected void inheritDetachableSettings() {
0764: // "persistence-capable-superclass"
0765: // Check that the class can be loaded, and is a true superclass
0766: if (persistenceCapableSuperclass != null) {
0767: if (!isDetachable() && pcSuperclassMetaData.isDetachable()) {
0768: // If the superclass is detachable then we are by definition since we extend
0769: detachable = true;
0770: }
0771: }
0772: }
0773:
0774: /**
0775: * Inherit the identity definition from super classes.
0776: * @throws InvalidMetaDataException if the MetaData of this class conflicts with super classes definition
0777: */
0778: protected void inheritIdentity() {
0779: // "persistence-capable-superclass"
0780: // Check that the class can be loaded, and is a true superclass
0781: if (persistenceCapableSuperclass != null) {
0782: // Class has superclass, yet has objectid-class defined! ops, this might result in user errors
0783: if (objectidClass != null) {
0784: String super ObjectIdClass = pcSuperclassMetaData
0785: .getObjectidClass();
0786: if (super ObjectIdClass == null
0787: || !objectidClass.equals(super ObjectIdClass)) {
0788: throw new InvalidMetaDataException(LOCALISER,
0789: "044085", name,
0790: persistenceCapableSuperclass);
0791: }
0792: // by default users should only specify the object-id class in the root persistent class
0793: JPOXLogger.METADATA.warn(LOCALISER.msg("044086", name,
0794: persistenceCapableSuperclass));
0795: } else {
0796: // get the objectid class from superclass
0797: this .objectidClass = pcSuperclassMetaData
0798: .getObjectidClass();
0799: }
0800:
0801: if (this .identityType == null) {
0802: this .identityType = pcSuperclassMetaData
0803: .getIdentityType();
0804: }
0805:
0806: // Superclass identityType must be the same as this classes identityType
0807: if (!this .identityType.equals(pcSuperclassMetaData
0808: .getIdentityType())) {
0809: // We can't change the identity type from what was specified in the base class
0810: throw new InvalidMetaDataException(LOCALISER, "044093",
0811: fullName);
0812: }
0813: }
0814: }
0815:
0816: /**
0817: * Utility to add a defaulted PropertyMetaData to the class.
0818: * Provided as a method since then any derived classes can override it.
0819: * @param name name of property
0820: * @return the new PropertyMetaData
0821: */
0822: protected AbstractMemberMetaData newDefaultedProperty(String name) {
0823: return new PropertyMetaData(this , name);
0824: }
0825:
0826: /**
0827: * Check if the inheritance MetaData is credible.
0828: * @throws InvalidMetaDataException if the strategy is superclass-table, yet there are no super class
0829: * @throws InvalidMetaDataException if the strategy is superclass-table, yet the super class has not
0830: * specified a discriminator
0831: * @throws InvalidMetaDataException if the strategy is superclass-table and discriminator is "value-map",
0832: * yet no value for the discriminator has been specified
0833: */
0834: protected void validateUserInputForInheritanceMetaData() {
0835: // Check that the inheritance strategy is credible
0836: if (inheritanceMetaData != null) {
0837: // Check validity of inheritance strategy and discriminator
0838: if (inheritanceMetaData.getStrategyValue() == InheritanceStrategy.SUPERCLASS_TABLE) {
0839: AbstractClassMetaData super Cmd = getClassManagingTableForClass(this );
0840: if (super Cmd == null) {
0841: // We need a superclass table yet there is no superclass with its own table!
0842: throw new InvalidMetaDataException(LOCALISER,
0843: "044099", fullName);
0844: }
0845:
0846: DiscriminatorMetaData super Dismd = super Cmd
0847: .getInheritanceMetaData()
0848: .getDiscriminatorMetaData();
0849: if (super Dismd == null) {
0850: // If we are using "superclass-table" then the superclass should have specified the discriminator.
0851: throw new InvalidMetaDataException(LOCALISER,
0852: "044100", fullName, super Cmd.fullName);
0853: }
0854:
0855: DiscriminatorMetaData dismd = inheritanceMetaData
0856: .getDiscriminatorMetaData();
0857: if (super Dismd.getStrategy() == DiscriminatorStrategy.VALUE_MAP
0858: && (dismd == null || dismd.getValue() == null)) {
0859: // If we are using "superclass-table" and the discriminator uses "value-map" then we must specify a value
0860: throw new InvalidMetaDataException(LOCALISER,
0861: "044102", fullName, super Cmd.fullName,
0862: super Dismd.getColumnName());
0863: }
0864: }
0865: }
0866: }
0867:
0868: /**
0869: * Convenience method to validate the specified "unmapped" columns.
0870: * @throws InvalidMetaDataException if a column is specified without its name.
0871: */
0872: protected void validateUnmappedColumns() {
0873: // Validate any unmapped columns
0874: if (unmappedColumns != null && unmappedColumns.size() > 0) {
0875: Iterator unmappedIter = unmappedColumns.iterator();
0876: while (unmappedIter.hasNext()) {
0877: ColumnMetaData colmd = (ColumnMetaData) unmappedIter
0878: .next();
0879: if (colmd.getName() == null) {
0880: throw new InvalidMetaDataException(LOCALISER,
0881: "044119", getFullClassName());
0882: }
0883: if (colmd.getJdbcType() == null) {
0884: throw new InvalidMetaDataException(LOCALISER,
0885: "044120", colmd.getName(),
0886: getFullClassName());
0887: }
0888: }
0889: }
0890: }
0891:
0892: /**
0893: * Utility to navigate up to superclasses to find the next class with its own table.
0894: * @param cmd AbstractClassMetaData of the class
0895: * @return The AbstractClassMetaData of the class managing its own table
0896: */
0897: private static AbstractClassMetaData getClassManagingTableForClass(
0898: AbstractClassMetaData cmd) {
0899: if (cmd == null) {
0900: return null;
0901: }
0902:
0903: InheritanceMetaData imd = cmd.getInheritanceMetaData();
0904: if (imd == null) {
0905: return cmd;
0906: } else if (imd.getStrategyValue() == InheritanceStrategy.NEW_TABLE) {
0907: return cmd;
0908: } else if (imd.getStrategyValue() == InheritanceStrategy.SUPERCLASS_TABLE) {
0909: return getClassManagingTableForClass(cmd
0910: .getSuperAbstractClassMetaData());
0911: }
0912: return null;
0913: }
0914:
0915: /**
0916: * Accessor for the Meta-Data for the superclass of this class.
0917: * @return MetaData of the superclass
0918: */
0919: public AbstractClassMetaData getSuperAbstractClassMetaData() {
0920: // checkInitialised();
0921:
0922: return pcSuperclassMetaData;
0923: }
0924:
0925: /**
0926: * Convenience accessor for the discriminator strategy applying to this class.
0927: * This is specified on the class managing the table if at all.
0928: * @return The discriminator strategy
0929: */
0930: public final DiscriminatorStrategy getDiscriminatorStrategy() {
0931: if (inheritanceMetaData == null) {
0932: return null;
0933: } else if (inheritanceMetaData.getStrategyValue() == InheritanceStrategy.NEW_TABLE) {
0934: if (inheritanceMetaData.getDiscriminatorMetaData() != null) {
0935: return inheritanceMetaData.getDiscriminatorMetaData()
0936: .getStrategy();
0937: } else {
0938: // Not specified.
0939: return null;
0940: }
0941: } else if (getSuperAbstractClassMetaData() != null) {
0942: return getSuperAbstractClassMetaData()
0943: .getDiscriminatorStrategy();
0944: } else {
0945: // Unknown!
0946: return null;
0947: }
0948: }
0949:
0950: /**
0951: * Determine the object id class
0952: * @param clr the ClassLoader
0953: * @throws InvalidMetaDataException if the class 0 or more that one primary key field and no <code>objectid-class</code>
0954: * has been declared in the MetaData
0955: * @throws InvalidMetaDataException if the <code>objectid-class</code> has not been set and the primary key field does
0956: * not match a supported SingleFieldIdentity
0957: * @throws InvalidMetaDataException if the identity type is APPLICATION but not primary key fields have been set
0958: * @throws InvalidMetaDataException if the <code>objectid-class</code> cannot be loaded by the <code>clr</code>
0959: */
0960: protected void determineObjectIdClass(ClassLoaderResolver clr) {
0961: ApiAdapter api = getMetaDataManager().getApiAdapter();
0962:
0963: // Update "objectid-class" if required yet not specified
0964: if (objectidClass == null
0965: && persistenceCapableSuperclass == null
0966: && identityType == IdentityType.APPLICATION) {
0967: int no_of_pk_fields = 0;
0968: AbstractMemberMetaData fmd_pk = null;
0969: Iterator fields_pk_iter = members.iterator();
0970: while (fields_pk_iter.hasNext()) {
0971: AbstractMemberMetaData fmd = (AbstractMemberMetaData) fields_pk_iter
0972: .next();
0973: if (fmd.isPrimaryKey()) {
0974: fmd_pk = fmd;
0975: no_of_pk_fields++;
0976: }
0977: }
0978:
0979: // Check for more than 1 field
0980: if (no_of_pk_fields > 1 || no_of_pk_fields == 0) {
0981: JPOXLogger.METADATA.error(LOCALISER.msg("044065",
0982: fullName, "" + no_of_pk_fields));
0983: throw new InvalidMetaDataException(LOCALISER, "044065",
0984: fullName, "" + no_of_pk_fields);
0985: }
0986:
0987: // Assign associated SingleField identity class
0988: Class pk_type = fmd_pk.getType();
0989: if (Byte.class.isAssignableFrom(pk_type)
0990: || byte.class.isAssignableFrom(pk_type)) {
0991: objectidClass = api
0992: .getSingleFieldIdentityClassNameForByte();
0993: } else if (Character.class.isAssignableFrom(pk_type)
0994: || char.class.isAssignableFrom(pk_type)) {
0995: objectidClass = api
0996: .getSingleFieldIdentityClassNameForChar();
0997: } else if (Integer.class.isAssignableFrom(pk_type)
0998: || int.class.isAssignableFrom(pk_type)) {
0999: objectidClass = api
1000: .getSingleFieldIdentityClassNameForInt();
1001: } else if (Long.class.isAssignableFrom(pk_type)
1002: || long.class.isAssignableFrom(pk_type)) {
1003: objectidClass = api
1004: .getSingleFieldIdentityClassNameForLong();
1005: } else if (Short.class.isAssignableFrom(pk_type)
1006: || short.class.isAssignableFrom(pk_type)) {
1007: objectidClass = api
1008: .getSingleFieldIdentityClassNameForShort();
1009: } else if (String.class.isAssignableFrom(pk_type)) {
1010: objectidClass = api
1011: .getSingleFieldIdentityClassNameForString();
1012: } else if (Object.class.isAssignableFrom(pk_type)) {
1013: objectidClass = api
1014: .getSingleFieldIdentityClassNameForObject();
1015: } else {
1016: JPOXLogger.METADATA.error(LOCALISER.msg("044066",
1017: fullName, pk_type.getName()));
1018: throw new InvalidMetaDataException(LOCALISER, "044066",
1019: fullName, pk_type.getName());
1020: }
1021: JPOXLogger.METADATA.info(LOCALISER.msg("044064", fullName,
1022: objectidClass));
1023: }
1024:
1025: // Check no of primary key fields (inc superclass)
1026: int no_of_pk_fields = getNoOfPopulatedPKMembers();
1027: if (no_of_pk_fields == 0
1028: && identityType == IdentityType.APPLICATION) {
1029: // No primary key fields found (even in superclasses)
1030: throw new InvalidMetaDataException(LOCALISER, "044077",
1031: fullName, objectidClass);
1032: }
1033:
1034: // Update "objectid-class" since has been specified.
1035: // Only check at the least derived pc class
1036: if (objectidClass != null
1037: && getPersistenceCapableSuperclass() == null) {
1038: Class obj_cls = null;
1039: try {
1040: // Load the class, using the same class loader resolver as this class
1041: obj_cls = clr.classForName(objectidClass);
1042: } catch (ClassNotResolvedException cnre) {
1043: // ObjectIdClass not found
1044: throw new InvalidMetaDataException(LOCALISER, "044079",
1045: fullName, objectidClass);
1046: }
1047:
1048: boolean validated = false;
1049: Set errors = new HashSet();
1050: try {
1051: // Check against the API Adapter in use for this MetaData
1052: if (api.isValidPrimaryKeyClass(obj_cls, this , clr,
1053: no_of_pk_fields)) {
1054: validated = true;
1055: }
1056: } catch (JPOXException ex) {
1057: errors.add(ex);
1058: }
1059: if (!validated) {
1060: // Why is this wrapping all exceptions into 1 single exception?
1061: // This needs coordinating with the test expectations in the enhancer unit tests.
1062: throw new JPOXUserException(LOCALISER_API.msg("019016",
1063: obj_cls.getName()), (Throwable[]) errors
1064: .toArray(new Throwable[errors.size()]));
1065: }
1066: }
1067: }
1068:
1069: /**
1070: * Method to provide the details of the class being represented by this
1071: * MetaData. This can be used to firstly provide defaults for attributes
1072: * that aren't specified in the MetaData, and secondly to report any errors
1073: * with attributes that have been specifed that are inconsistent with the
1074: * class being represented.
1075: * <P>
1076: * This method must be invoked by subclasses during populate operations
1077: * </P>
1078: * @param clr ClassLoaderResolver to use in loading any classes
1079: * @param primary the primary ClassLoader to use (or null)
1080: */
1081: abstract public void populate(ClassLoaderResolver clr,
1082: ClassLoader primary);
1083:
1084: /**
1085: * Method to initialise the sub-objects of this class metadata.
1086: * If populate() is going to be used it should be used BEFORE calling this method.
1087: * Subclasses must overwrite this method and invoke this
1088: */
1089: public abstract void initialise();
1090:
1091: /**
1092: * Impose a default inheritance strategy when one is not already specified.
1093: * Uses the PMF property for defaultInheritanceStrategy and works to the JDO2 spec etc.
1094: */
1095: protected void determineInheritanceMetaData() {
1096: if (inheritanceMetaData == null) {
1097: // User hasnt specified the <inheritance> for the class
1098: if (pcSuperclassMetaData != null) {
1099: AbstractClassMetaData baseCmd = getBaseAbstractClassMetaData();
1100: if (baseCmd.getInheritanceMetaData() != null
1101: && baseCmd.getInheritanceMetaData()
1102: .getStrategyValue() == InheritanceStrategy.COMPLETE_TABLE) {
1103: // Root class in tree is set to use COMPLETE_TABLE so all subclasses have own table
1104: inheritanceMetaData = new InheritanceMetaData(this ,
1105: InheritanceStrategy.COMPLETE_TABLE
1106: .toString());
1107: } else if (pcSuperclassMetaData
1108: .getInheritanceMetaData() != null
1109: && pcSuperclassMetaData
1110: .getInheritanceMetaData()
1111: .getStrategyValue() == InheritanceStrategy.SUBCLASS_TABLE) {
1112: // Superclass exists but needs our table so have own table
1113: inheritanceMetaData = new InheritanceMetaData(this ,
1114: InheritanceStrategy.NEW_TABLE.toString());
1115: } else {
1116: // Superclass exists and has a table or uses its superclass, so default based on that
1117: if (getMetaDataManager().getOMFContext()
1118: .getPersistenceConfiguration()
1119: .getDefaultInheritanceStrategy()
1120: .equalsIgnoreCase("JPOX")) {
1121: // JPOX 1.0 behaviour
1122: inheritanceMetaData = new InheritanceMetaData(
1123: this , InheritanceStrategy.NEW_TABLE
1124: .toString());
1125: } else {
1126: // JDO2 behaviour
1127: inheritanceMetaData = new InheritanceMetaData(
1128: this ,
1129: InheritanceStrategy.SUPERCLASS_TABLE
1130: .toString());
1131: }
1132: }
1133: } else {
1134: inheritanceMetaData = new InheritanceMetaData(this ,
1135: InheritanceStrategy.NEW_TABLE.toString());
1136: }
1137: return;
1138: }
1139:
1140: if (inheritanceMetaData.getStrategyValue() == null) {
1141: // User has included <inheritance> but not set the strategy, so populate it for them
1142: if (pcSuperclassMetaData != null) {
1143: AbstractClassMetaData baseCmd = getBaseAbstractClassMetaData();
1144: if (baseCmd.getInheritanceMetaData() != null
1145: && baseCmd.getInheritanceMetaData()
1146: .getStrategyValue() == InheritanceStrategy.COMPLETE_TABLE) {
1147: // Root class in tree is set to use COMPLETE_TABLE so all subclasses have own table
1148: inheritanceMetaData.strategy = InheritanceStrategy.COMPLETE_TABLE;
1149: }
1150: if (pcSuperclassMetaData.getInheritanceMetaData() != null
1151: && pcSuperclassMetaData
1152: .getInheritanceMetaData()
1153: .getStrategyValue() == InheritanceStrategy.SUBCLASS_TABLE) {
1154: // Superclass exists but needs our table so have own table
1155: inheritanceMetaData.strategy = InheritanceStrategy.NEW_TABLE;
1156: } else {
1157: // Superclass exists and has a table or uses its superclass, so default based on that
1158: if (getMetaDataManager().getOMFContext()
1159: .getPersistenceConfiguration()
1160: .getDefaultInheritanceStrategy()
1161: .equalsIgnoreCase("JPOX")) {
1162: // JPOX 1.0 behaviour
1163: inheritanceMetaData.strategy = InheritanceStrategy.NEW_TABLE;
1164: } else {
1165: // JDO2 behaviour
1166: inheritanceMetaData.strategy = InheritanceStrategy.SUPERCLASS_TABLE;
1167: }
1168: }
1169: } else {
1170: inheritanceMetaData.strategy = InheritanceStrategy.NEW_TABLE;
1171: }
1172: }
1173: }
1174:
1175: /**
1176: * Check usage of deprecated MetaData
1177: * @throws InvalidMetaDataException if deprecated MetaData is used
1178: */
1179: protected void validateDeprecatedMetaData() {
1180: // "use-poid-generator" was used in JPOX 1.0, and 1.1 until beta-2. Now replaced by "value-strategy".
1181: if (hasExtension("use-poid-generator")) {
1182: throw new InvalidMetaDataException(LOCALISER, "044092",
1183: fullName);
1184: }
1185: }
1186:
1187: /**
1188: * Method to return the ClassMetaData records for classes referenced
1189: * by this object. This adds the entries to orderedCMDs ordered by
1190: * dependency, and to referencedCMDs for fast lookups.
1191: * <p>
1192: * Uses recursion to add all referenced ClassMetaData for any fields,
1193: * objectid classes, superclasses, and JPOX extension RDBMS "views".
1194: * </p>
1195: * <p>
1196: * This is the entry point for this process, and provides the core of the
1197: * "persistence-by-reachability" concept.
1198: * </p>
1199: * @param orderedCMDs List of ordered ClassMetaData objects (added to).
1200: * @param referencedCMDs Set of all ClassMetaData objects (added to).
1201: * @param dba_vendor_id Vendor ID of the DBA. Used for view addition.
1202: * @param clr the ClassLoaderResolver
1203: */
1204: void getReferencedClassMetaData(final List orderedCMDs,
1205: final Set referencedCMDs, final String dba_vendor_id,
1206: final ClassLoaderResolver clr) {
1207: Map viewReferences = new HashMap();
1208: getReferencedClassMetaData(orderedCMDs, referencedCMDs,
1209: dba_vendor_id, viewReferences, clr);
1210: }
1211:
1212: /**
1213: * Method to return the ClassMetaData for classes referenced by this
1214: * object. This method does the actual work of addition.
1215: * @param orderedCMDs List of ordered ClassMetaData objects (added to).
1216: * @param referencedCMDs Set of all ClassMetaData objects (added to).
1217: * @param dba_vendor_id Vendor ID of the DBA. Used for view addition.
1218: * @param viewReferences Map, mapping class name to set of referenced class
1219: * for all views.
1220: * @param clr the ClassLoaderResolver
1221: */
1222: private void getReferencedClassMetaData(final List orderedCMDs,
1223: final Set referencedCMDs, final String dba_vendor_id,
1224: final Map viewReferences, final ClassLoaderResolver clr) {
1225: // Recursively call getReferencedClassMetaData(...) before adding them
1226: // to the orderedCmds and referenced. This will ensure that any
1227: // classes with dependencies on them are put in the orderedCmds List
1228: // in the correct order.
1229: if (!referencedCMDs.contains(this )) {
1230: // Go ahead and add this class to the referenced Set, it will
1231: // get added to the orderedCMDs List after all classes that this
1232: // depends on have been added.
1233: referencedCMDs.add(this );
1234:
1235: for (int i = 0; i < managedMembers.length; i++) {
1236: AbstractMemberMetaData fmd = managedMembers[i];
1237: fmd.getReferencedClassMetaData(orderedCMDs,
1238: referencedCMDs, dba_vendor_id, clr);
1239: }
1240:
1241: // Add on any superclass
1242: if (persistenceCapableSuperclass != null) {
1243: AbstractClassMetaData super _cmd = getSuperAbstractClassMetaData();
1244: super _cmd.getReferencedClassMetaData(orderedCMDs,
1245: referencedCMDs, dba_vendor_id, clr);
1246: }
1247:
1248: // Add on any objectid class
1249: if (objectidClass != null) {
1250: AbstractClassMetaData id_cmd = getMetaDataManager()
1251: .getMetaDataForClass(objectidClass, clr);
1252: if (id_cmd != null) {
1253: id_cmd.getReferencedClassMetaData(orderedCMDs,
1254: referencedCMDs, dba_vendor_id, clr);
1255: }
1256: }
1257:
1258: // Add on any views defined for this class
1259: String viewDefStr = getValueForExtension("view-definition-"
1260: + dba_vendor_id);
1261: if (viewDefStr == null) {
1262: viewDefStr = getValueForExtension("view-definition");
1263: }
1264: if (viewDefStr != null) {
1265: MacroString viewDef = new MacroString(fullName,
1266: getValueForExtension("view-imports"),
1267: viewDefStr);
1268: viewDef.substituteMacros(
1269: new MacroString.MacroHandler() {
1270: public void onIdentifierMacro(
1271: MacroString.IdentifierMacro im) {
1272: if (!getFullClassName().equals(
1273: im.className)) //ignore itself
1274: {
1275: addViewReference(viewReferences,
1276: im.className);
1277: AbstractClassMetaData view_cmd = getMetaDataManager()
1278: .getMetaDataForClass(
1279: im.className, clr);
1280: view_cmd
1281: .getReferencedClassMetaData(
1282: orderedCMDs,
1283: referencedCMDs,
1284: dba_vendor_id,
1285: viewReferences, clr);
1286: }
1287: }
1288:
1289: public void onParameterMacro(
1290: MacroString.ParameterMacro pm) {
1291: throw new JPOXUserException(
1292: "Parameter macros not allowed in view definitions: "
1293: + pm);
1294: }
1295: }, clr);
1296: }
1297:
1298: orderedCMDs.add(this );
1299: }
1300: }
1301:
1302: /**
1303: * Method to add a reference for views. Check the view references for circular
1304: * dependencies. If there are any circular dependencies, throw a JPOXUserException.
1305: * @param viewReferences The Map of classname to Set of referenced Classes to add the reference to.
1306: * @param referenced_name Class name of the referenced class
1307: * @throws JPOXUserException Thrown if a circular reference is found
1308: */
1309: private void addViewReference(Map viewReferences,
1310: String referenced_name) {
1311: if (fullName.equals(referenced_name)) {
1312: // Add this reference to the Map.
1313: Set referencedSet = (Set) viewReferences
1314: .get(referenced_name);
1315: if (referencedSet == null) {
1316: referencedSet = new HashSet();
1317: viewReferences.put(fullName, referencedSet);
1318: }
1319: referencedSet.add(referenced_name);
1320:
1321: // Check to see if there is a circular dependency. This will
1322: // be true if the referenced class references this class.
1323: ViewUtils.checkForCircularViewReferences(viewReferences,
1324: fullName, referenced_name, null);
1325: }
1326: }
1327:
1328: // ------------------------------ Accessors --------------------------------
1329:
1330: /**
1331: * Accessor for the number of named queries.
1332: * @return no of named queries
1333: */
1334: public int getNoOfQueries() {
1335: return queries.size();
1336: }
1337:
1338: /**
1339: * Accessor for the metadata of the named queries.
1340: * @return Meta-Data for the named queries.
1341: */
1342: public QueryMetaData[] getQueries() {
1343: return (queries == null ? null : ((QueryMetaData[]) queries
1344: .toArray(new QueryMetaData[queries.size()])));
1345: }
1346:
1347: /**
1348: * Get the query result MetaData registered for this class.
1349: * @return Query Result MetaData defined for this class
1350: */
1351: public QueryResultMetaData[] getQueryResultMetaData() {
1352: if (queryResultMetaData == null) {
1353: return null;
1354: }
1355: return (QueryResultMetaData[]) queryResultMetaData
1356: .toArray(new QueryResultMetaData[queryResultMetaData
1357: .size()]);
1358: }
1359:
1360: /**
1361: * Accessor for Version MetaData for objects stored in this table
1362: * @return Returns the versionMetaData.
1363: */
1364: public final VersionMetaData getVersionMetaData() {
1365: return versionMetaData;
1366: }
1367:
1368: /**
1369: * Convenience method to find the version MetaData defining versioning for the same table
1370: * as this class is using. Traverses up the inheritance tree to find the highest class that uses
1371: * "subclass-table" that has version metadata defined, and returns the MetaData.
1372: * @return Version MetaData for the highest class in this tree using subclass-table
1373: */
1374: public final VersionMetaData getVersionMetaDataForTable() {
1375: if (pcSuperclassMetaData != null
1376: && pcSuperclassMetaData.getInheritanceMetaData()
1377: .getStrategyValue() == InheritanceStrategy.SUBCLASS_TABLE) {
1378: VersionMetaData vermd = pcSuperclassMetaData
1379: .getVersionMetaDataForTable();
1380: if (vermd != null) {
1381: // Superclass has versioning info so return that
1382: return vermd;
1383: }
1384: }
1385:
1386: // Nothing in superclasses sharing our table so return ours
1387: return versionMetaData;
1388: }
1389:
1390: /**
1391: * Convenience method to find the discriminator MetaData defining the discrim for the same table
1392: * as this class is using. Traverses up the inheritance tree to find the highest class that uses
1393: * "subclass-table" that has discriminator metadata defined, and returns the MetaData.
1394: * @return DiscriminatorMetaData for the highest class in this tree using subclass-table
1395: */
1396: public final DiscriminatorMetaData getDiscriminatorMetaDataForTable() {
1397: if (pcSuperclassMetaData != null
1398: && pcSuperclassMetaData.getInheritanceMetaData()
1399: .getStrategyValue() == InheritanceStrategy.SUBCLASS_TABLE) {
1400: if (pcSuperclassMetaData.getInheritanceMetaData() != null) {
1401: DiscriminatorMetaData dismd = pcSuperclassMetaData
1402: .getInheritanceMetaData()
1403: .getDiscriminatorMetaData();
1404: if (dismd != null) {
1405: // Superclass has discriminator info so return that
1406: return dismd;
1407: }
1408: }
1409: }
1410:
1411: // Nothing in superclasses sharing our table so return ours
1412: return (inheritanceMetaData != null ? inheritanceMetaData
1413: .getDiscriminatorMetaData() : null);
1414: }
1415:
1416: /**
1417: * Accessor for joinMetaData
1418: * @return Returns the joinMetaData.
1419: */
1420: public final JoinMetaData[] getJoinMetaData() {
1421: return joinMetaData;
1422: }
1423:
1424: /**
1425: * Accessor for all MetaData defined for fetch groups for this class.
1426: * This doesn't include superclasses.
1427: * @return Returns the fetchGroupMetaData.
1428: */
1429: public final FetchGroupMetaData[] getFetchGroupMetaData() {
1430: return fetchGroupMetaData;
1431: }
1432:
1433: /**
1434: * Accessor for fetch group metadata for the specified groups (if present).
1435: * The returned metadata is what is defined for this class that matches any of the names in the input set.
1436: * @param groupNames Names of the fetch groups
1437: * @return MetaData for the groups
1438: */
1439: public FetchGroupMetaData[] getFetchGroupMetaData(
1440: Collection groupNames) {
1441: Collection results = new HashSet();
1442: for (Iterator iter = groupNames.iterator(); iter.hasNext();) {
1443: String groupname = (String) iter.next();
1444: FetchGroupMetaData fgmd = getFetchGroupMetaData(groupname);
1445: if (fgmd != null) {
1446: results.add(fgmd);
1447: }
1448: }
1449: FetchGroupMetaData[] result = new FetchGroupMetaData[results
1450: .size()];
1451: results.toArray(result);
1452: return result;
1453: }
1454:
1455: /**
1456: * Accessor for the fetch group metadata for the group specified.
1457: * @param groupname Name of the fetch group
1458: * @return MetaData for this group
1459: */
1460: public FetchGroupMetaData getFetchGroupMetaData(String groupname) {
1461: FetchGroupMetaData fgmd = (FetchGroupMetaData) fetchGroupMetaDataByName
1462: .get(groupname);
1463: if (fgmd == null && pcSuperclassMetaData != null) {
1464: return pcSuperclassMetaData
1465: .getFetchGroupMetaData(groupname);
1466: }
1467: return fgmd;
1468: }
1469:
1470: /**
1471: * Accessor for the identity-type.
1472: * @return identity-type tag value
1473: */
1474: public IdentityType getIdentityType() {
1475: return identityType;
1476: }
1477:
1478: /**
1479: * Accessor for indexMetaData
1480: * @return Returns the indexMetaData.
1481: */
1482: public final IndexMetaData[] getIndexMetaData() {
1483: return indexMetaData;
1484: }
1485:
1486: /**
1487: * Accessor for foreignKeyMetaData
1488: * @return Returns the foreignKeyMetaData.
1489: */
1490: public final ForeignKeyMetaData[] getForeignKeyMetaData() {
1491: return foreignKeyMetaData;
1492: }
1493:
1494: /**
1495: * Accessor for UniqueMetaData
1496: * @return Returns the UniqueMetaData.
1497: */
1498: public final UniqueMetaData[] getUniqueMetaData() {
1499: return uniqueMetaData;
1500: }
1501:
1502: /**
1503: * Accessor for the unmapped columns require for the datastore table.
1504: * @return The list of unmapped columns
1505: */
1506: public final List getUnmappedColumns() {
1507: return unmappedColumns;
1508: }
1509:
1510: /**
1511: * Accessor for the class name.
1512: * @return class name
1513: */
1514: public String getName() {
1515: return name;
1516: }
1517:
1518: /**
1519: * Accessor for the full class name.
1520: * @return full class name.
1521: */
1522: public String getFullClassName() {
1523: return fullName;
1524: }
1525:
1526: /**
1527: * Accessor for the class name.
1528: * @return class name
1529: */
1530: public String getEntityName() {
1531: return entityName;
1532: }
1533:
1534: /**
1535: * Accessor for the objectid-class tag value.
1536: * @return the fully qualified objectid class name
1537: */
1538: public String getObjectidClass() {
1539: return objectidClass;
1540: }
1541:
1542: /**
1543: * Accessor for the catalog name.
1544: * @return catalog name
1545: */
1546: public String getCatalog() {
1547: if (this .catalog == null) {
1548: // Nothing defined here for catalog, so get from package
1549: return ((PackageMetaData) parent).getCatalog();
1550: }
1551:
1552: return catalog;
1553: }
1554:
1555: /**
1556: * Accessor for the schema name.
1557: * @return schema name
1558: */
1559: public String getSchema() {
1560: if (this .schema == null) {
1561: // Nothing defined here for schema, so get from package
1562: return ((PackageMetaData) parent).getSchema();
1563: }
1564:
1565: return schema;
1566: }
1567:
1568: /**
1569: * Accessor for the table name.
1570: * @return table name
1571: */
1572: public String getTable() {
1573: return table;
1574: }
1575:
1576: /**
1577: * Accessor for the requires-extent tag value.
1578: * @return requires-extent tag value
1579: */
1580: public boolean isRequiresExtent() {
1581: return requiresExtent;
1582: }
1583:
1584: /**
1585: * Accessor for the detachable tag value.
1586: * @return detachable tag value
1587: */
1588: public boolean isDetachable() {
1589: return detachable;
1590: }
1591:
1592: /**
1593: * Accessor for the embedded-only tag value.
1594: * @return embedded-only tag value
1595: */
1596: public boolean isEmbeddedOnly() {
1597: return embeddedOnly;
1598: }
1599:
1600: /**
1601: * Convenience method to make this class available for storing only when embedded in another object.
1602: */
1603: public void setEmbeddedOnly() {
1604: embeddedOnly = true;
1605: }
1606:
1607: /**
1608: * Accessor for identityMetaData
1609: * @return Returns the identityMetaData.
1610: */
1611: public final IdentityMetaData getIdentityMetaData() {
1612: return identityMetaData;
1613: }
1614:
1615: /**
1616: * Accessor for inheritanceMetaData
1617: * @return Returns the inheritanceMetaData.
1618: */
1619: public final InheritanceMetaData getInheritanceMetaData() {
1620: return inheritanceMetaData;
1621: }
1622:
1623: /**
1624: * Accessor for primaryKeyMetaData
1625: * @return Returns the primaryKey MetaData.
1626: */
1627: public final PrimaryKeyMetaData getPrimaryKeyMetaData() {
1628: return primaryKeyMetaData;
1629: }
1630:
1631: /**
1632: * Convenience accessor for the MetaData Manager in use.
1633: * @return MetaDataManager.
1634: */
1635: public MetaDataManager getMetaDataManager() {
1636: if (parent != null && parent.getParent() != null) {
1637: return getPackageMetaData().getFileMetaData()
1638: .getMetaDataManager();
1639: }
1640: return null;
1641: }
1642:
1643: /**
1644: * Convenience accessor for the parent Package MetaData.
1645: * @return MetaData for parent package.
1646: */
1647: public PackageMetaData getPackageMetaData() {
1648: if (parent != null) {
1649: return (PackageMetaData) parent;
1650: }
1651: return null;
1652: }
1653:
1654: /**
1655: * Convenience accessor for the package name.
1656: * @return package name.
1657: */
1658: public String getPackageName() {
1659: return getPackageMetaData().getName();
1660: }
1661:
1662: /**
1663: * Accessor for the number of fields/properties.
1664: * This is the total number of fields/properties (inc static, final etc) in this class
1665: * @return no of fields/properties.
1666: */
1667: public int getNoOfMembers() {
1668: return members.size();
1669: }
1670:
1671: /**
1672: * Accessor for the metadata of a field/property. Does not include superclasses
1673: * @param index field index relative to this class only starting from 0
1674: * @return Meta-Data for the field/property
1675: */
1676: public AbstractMemberMetaData getMetaDataForMemberAtRelativePosition(
1677: int index) {
1678: if (index < 0 || index >= members.size()) {
1679: return null;
1680: }
1681: return (AbstractMemberMetaData) members.get(index);
1682: }
1683:
1684: /**
1685: * Accessor for the persistence-modifier of the class.
1686: * @return persistence-modifier tag value
1687: */
1688: public ClassPersistenceModifier getPersistenceModifier() {
1689: return persistenceModifier;
1690: }
1691:
1692: /**
1693: * Accessor for the persistence-capable-superclass tag value.
1694: * @return persistence-capable-superclass tag value
1695: */
1696: public String getPersistenceCapableSuperclass() {
1697: return persistenceCapableSuperclass;
1698: }
1699:
1700: /**
1701: * Check if the argument cmd is the same as this or a descedent.
1702: * @param cmd the AbstractClassMetaData to be verify if this is an ancestor
1703: * @return true if the argument is a child or same as this
1704: */
1705: public boolean isSameOrAncestorOf(AbstractClassMetaData cmd) {
1706: checkInitialised();
1707:
1708: if (cmd == null) {
1709: return false;
1710: }
1711:
1712: if (fullName.equals(cmd.fullName)) {
1713: return true;
1714: }
1715:
1716: AbstractClassMetaData parent = cmd
1717: .getSuperAbstractClassMetaData();
1718: while (parent != null) {
1719: if (fullName.equals(parent.fullName)) {
1720: return true;
1721: }
1722: parent = parent.getSuperAbstractClassMetaData();
1723: }
1724: return false;
1725: }
1726:
1727: /**
1728: * Accessor for the names of the primary key fields/properties. Only valid after being populated.
1729: * Provided as a convenience where we need to get the names of the PK members but cant wait til initialisation.
1730: * @return names of the PK fields/properties
1731: */
1732: public String[] getPrimaryKeyMemberNames() {
1733: if (identityType != IdentityType.APPLICATION) {
1734: return null;
1735: }
1736:
1737: HashSet memberNames = new HashSet();
1738: Iterator iter = members.iterator();
1739: while (iter.hasNext()) {
1740: AbstractMemberMetaData mmd = (AbstractMemberMetaData) iter
1741: .next();
1742: if (mmd.primaryKey == Boolean.TRUE) {
1743: memberNames.add(mmd.name);
1744: }
1745: }
1746:
1747: if (memberNames.size() > 0) {
1748: return (String[]) memberNames
1749: .toArray(new String[memberNames.size()]);
1750: }
1751: memberNames = null;
1752: return pcSuperclassMetaData.getPrimaryKeyMemberNames();
1753: }
1754:
1755: /**
1756: * Method to check if a field/property exists in this classes definition.
1757: * @param memberName Name of field/property
1758: * @return return true if exists.
1759: */
1760: public boolean hasMember(String memberName) {
1761: Iterator iter = members.iterator();
1762: while (iter.hasNext()) {
1763: AbstractMemberMetaData mmd = (AbstractMemberMetaData) iter
1764: .next();
1765: if (mmd.getName().equals(memberName)) {
1766: return true;
1767: }
1768: }
1769: return false;
1770: }
1771:
1772: /**
1773: * Accessor for the Meta-Data for a field/property. Include superclasses.
1774: * @param name the name of the field/property
1775: * @return Meta-Data for the field.
1776: */
1777: public AbstractMemberMetaData getMetaDataForMember(String name) {
1778: if (name == null) {
1779: return null;
1780: }
1781:
1782: Iterator iter = members.iterator();
1783: while (iter.hasNext()) {
1784: AbstractMemberMetaData mmd = (AbstractMemberMetaData) iter
1785: .next();
1786: if (mmd.getName().equals(name)) {
1787: return mmd;
1788: }
1789: }
1790:
1791: // Check superclass for the field/property with this name
1792: if (pcSuperclassMetaData != null) {
1793: return pcSuperclassMetaData.getMetaDataForMember(name);
1794: }
1795: return null;
1796: }
1797:
1798: /**
1799: * Accessor for the number of managed fields/properties (this class only).
1800: * @return no of managed fields/properties in this class
1801: */
1802: public int getNoOfManagedMembers() {
1803: // checkInitialised();
1804:
1805: if (managedMembers == null) {
1806: return 0;
1807: }
1808: return managedMembers.length;
1809: }
1810:
1811: /**
1812: * Accessor for the managed fields/properties in this class (not including superclass, but including overridden).
1813: * @return MetaData for the managed fields/properties in this class
1814: */
1815: public AbstractMemberMetaData[] getManagedMembers() {
1816: checkInitialised();
1817:
1818: return managedMembers;
1819: }
1820:
1821: /**
1822: * Accessor for MetaData for a managed field/property in this class. The position is relative to
1823: * the first field in this class (ignores superclasses).
1824: * @param position The position of the managed field. 0 = first in the class
1825: * @return The JDO managed field at that position
1826: */
1827: public AbstractMemberMetaData getMetaDataForManagedMemberAtPosition(
1828: int position) {
1829: checkInitialised();
1830:
1831: if (managedMembers == null) {
1832: return null;
1833: }
1834: if (position < 0 || position >= managedMembers.length) {
1835: return null;
1836: }
1837:
1838: return managedMembers[position];
1839: }
1840:
1841: /**
1842: * Accessor for the number of overridden fields/properties (this class only).
1843: * @return no of overridden fields/properties in this class
1844: */
1845: public int getNoOfOverriddenMembers() {
1846: if (overriddenMembers == null) {
1847: return 0;
1848: }
1849: return overriddenMembers.length;
1850: }
1851:
1852: /**
1853: * Accessor for the overridden fields/properties in this class.
1854: * @return The overridden fields/properties in this class
1855: */
1856: public AbstractMemberMetaData[] getOverriddenMembers() {
1857: checkInitialised();
1858:
1859: return overriddenMembers;
1860: }
1861:
1862: /**
1863: * Accessor for MetaData for an overridden field/property in this class.
1864: * @param position The position of the overridden field/property.
1865: * @return MetaData for the field/property at that position
1866: */
1867: public AbstractMemberMetaData getOverriddenMember(int position) {
1868: checkInitialised();
1869:
1870: if (overriddenMembers == null) {
1871: return null;
1872: }
1873: if (position < 0 || position >= overriddenMembers.length) {
1874: return null;
1875: }
1876:
1877: return overriddenMembers[position];
1878: }
1879:
1880: /**
1881: * Accessor for an overridden field/property with the specified name.
1882: * @param name Name of the field/property
1883: * @return The MetaData for the field/property
1884: */
1885: public AbstractMemberMetaData getOverriddenMember(String name) {
1886: checkInitialised();
1887:
1888: if (overriddenMembers == null) {
1889: return null;
1890: }
1891: for (int i = 0; i < overriddenMembers.length; i++) {
1892: if (overriddenMembers[i].getName().equals(name)) {
1893: return overriddenMembers[i];
1894: }
1895: }
1896: return null;
1897: }
1898:
1899: /**
1900: * Convenience method that navigates up a MetaData inheritance tree until it finds the base field/property definition.
1901: * @param name Name of the field/property we require
1902: * @return The AbstractMemberMetaData
1903: */
1904: protected AbstractMemberMetaData getMemberBeingOverridden(
1905: String name) {
1906: Iterator iter = members.iterator();
1907: while (iter.hasNext()) {
1908: AbstractMemberMetaData apmd = (AbstractMemberMetaData) iter
1909: .next();
1910: if (apmd.name.equals(name) && apmd.fieldBelongsToClass()) {
1911: return apmd;
1912: }
1913: }
1914: if (pcSuperclassMetaData != null) {
1915: return pcSuperclassMetaData.getMemberBeingOverridden(name);
1916: }
1917: return null;
1918: }
1919:
1920: /**
1921: * Accessor for the number of inherited managed fields/properties in superclasses.
1922: * @return No of inherited managed fields/properties in superclasses.
1923: */
1924: public int getNoOfInheritedManagedMembers() {
1925: checkInitialised();
1926:
1927: return noOfInheritedManagedMembers;
1928: }
1929:
1930: /**
1931: * Accessor for the number of managed fields/properties from this class plus inherited classes.
1932: * @return The number of managed fields/properties from this class plus inherited classes.
1933: */
1934: public int getMemberCount() {
1935: // we assume this
1936: // checkInitialised();
1937:
1938: return memberCount;
1939: }
1940:
1941: /**
1942: * Accessor for a managed field/property including superclass fields.
1943: * @param abs_position The position of the managed member including the
1944: * superclass. Fields are numbered from 0 in the root superclass.
1945: * @return The managed field/property at this "absolute" position.
1946: */
1947: public AbstractMemberMetaData getMetaDataForManagedMemberAtAbsolutePosition(
1948: int abs_position) {
1949: checkInitialised();
1950:
1951: return getMetaDataForManagedMemberAtAbsolutePositionInternal(abs_position);
1952: }
1953:
1954: /**
1955: * Internal method to get the field/property for an absolute field number.
1956: * If the field for that absolute field position is overridden by a field in this class
1957: * then this field/property will be returned.
1958: * @param abs_position The position of the managed field including the
1959: * superclass. Fields are numbered from 0 in the root superclass.
1960: * @return The managed field at this "absolute" position.
1961: */
1962: protected AbstractMemberMetaData getMetaDataForManagedMemberAtAbsolutePositionInternal(
1963: int abs_position) {
1964: // If the field is in a superclass, go there
1965: if (abs_position < noOfInheritedManagedMembers) {
1966: if (pcSuperclassMetaData == null) {
1967: return null;
1968: } else {
1969: AbstractMemberMetaData fmd = pcSuperclassMetaData
1970: .getMetaDataForManagedMemberAtAbsolutePositionInternal(abs_position);
1971: if (fmd != null) {
1972: for (int i = 0; i < overriddenMembers.length; i++) {
1973: if (overriddenMembers[i].getName().equals(
1974: fmd.getName())
1975: && overriddenMembers[i].getClassName()
1976: .equals(fmd.getClassName())) {
1977: // Return the overriding field if we have one (class and field name is the safest comparison)
1978: return overriddenMembers[i];
1979: }
1980: }
1981:
1982: return fmd;
1983: }
1984: return null;
1985: }
1986: }
1987: // If the field is in this class, return it
1988: else if (abs_position - noOfInheritedManagedMembers >= managedMembers.length) {
1989: return null;
1990: } else {
1991: return managedMembers[abs_position
1992: - noOfInheritedManagedMembers];
1993: }
1994: }
1995:
1996: /**
1997: * Accessor for the absolute position for a relative position.
1998: * @param relativePosition The relative field number
1999: * @return The absolute position
2000: */
2001: public int getAbsoluteMemberPositionForRelativePosition(
2002: int relativePosition) {
2003: return noOfInheritedManagedMembers + relativePosition;
2004: }
2005:
2006: /**
2007: * Accessor for the position of the field/property with the specified name.
2008: * The returned position is relative to this class only.
2009: * @param memberName Name of the field/property
2010: * @return Position of the field/property in this class.
2011: */
2012: public int getRelativePositionOfMember(String memberName) {
2013: checkInitialised();
2014:
2015: if (memberName == null) {
2016: return -1;
2017: }
2018:
2019: Integer i = (Integer) memberPositionsByName.get(memberName);
2020:
2021: return i == null ? -1 : i.intValue();
2022: }
2023:
2024: /**
2025: * Accessor for the absolute position of the field/property with the specified name.
2026: * The absolute position has origin of the root superclass, starting at 0.
2027: * @param memberName Name of the field/property
2028: * @return Absolute position of the field/property.
2029: */
2030: public int getAbsolutePositionOfMember(String memberName) {
2031: checkInitialised();
2032:
2033: if (memberName == null) {
2034: return -1;
2035: }
2036:
2037: int i = getRelativePositionOfMember(memberName);
2038: if (i < 0) {
2039: if (pcSuperclassMetaData != null) {
2040: i = pcSuperclassMetaData
2041: .getAbsolutePositionOfMember(memberName);
2042: }
2043: } else {
2044: i += noOfInheritedManagedMembers;
2045: }
2046:
2047: return i;
2048: }
2049:
2050: /**
2051: * Accessor for the absolute position of the field/property with the specified name.
2052: * The absolute position has origin of the root superclass, starting at 0.
2053: * Will only retrieve the absolute field number if the <code>field_name</code>
2054: * is of type given by <code>class_name</code>.
2055: * @param className Name of the class
2056: * @param memberName Name of the field/property
2057: * @return Absolute position of the field/property.
2058: */
2059: public int getAbsolutePositionOfMember(String className,
2060: String memberName) {
2061: checkInitialised();
2062:
2063: if (memberName == null) {
2064: return -1;
2065: }
2066:
2067: int i = -1;
2068: if (className.equals(getFullClassName())) {
2069: i = getRelativePositionOfMember(memberName);
2070: }
2071: if (i < 0) {
2072: if (pcSuperclassMetaData != null) {
2073: i = pcSuperclassMetaData.getAbsolutePositionOfMember(
2074: className, memberName);
2075: }
2076: } else {
2077: i += noOfInheritedManagedMembers;
2078: }
2079:
2080: return i;
2081: }
2082:
2083: /**
2084: * Convenience method to check the number of fields/properties in this class that have been populated and
2085: * that are primary key members. This is only ever called during populate() since the accessor
2086: * for PK members cant be used yet due to lack of initialisation.
2087: * Recurses to its superclass if it has a superclass.
2088: * @return The number of PK members
2089: */
2090: private int getNoOfPopulatedPKMembers() {
2091: if (pcSuperclassMetaData != null) {
2092: return pcSuperclassMetaData.getNoOfPopulatedPKMembers();
2093: }
2094:
2095: Iterator fields_iter = members.iterator();
2096: int noOfPks = 0;
2097: while (fields_iter.hasNext()) {
2098: AbstractMemberMetaData fmd = (AbstractMemberMetaData) fields_iter
2099: .next();
2100: if (fmd.isPrimaryKey()) {
2101: noOfPks++;
2102: }
2103: }
2104: return noOfPks;
2105: }
2106:
2107: /**
2108: * Accessor for the number of primary key fields/properties.
2109: * @return no of primary key fields/properties
2110: */
2111: public int getNoOfPrimaryKeyMembers() {
2112: if (pkMemberPositions == null) {
2113: return 0;
2114: } else {
2115: return pkMemberPositions.length;
2116: }
2117: }
2118:
2119: /**
2120: * Accessor for all field/property positions.
2121: * These are absolute numbers and include superclasses and are really just 0, 1, 2, ... n.
2122: * @return The positions of all (managed) fields/properties.
2123: */
2124: public int[] getAllMemberPositions() {
2125: checkInitialised();
2126: return allMemberPositions;
2127: }
2128:
2129: /**
2130: * Accessor for the field numbers of the primary key fields/properties.
2131: * These are absolute numbers (including superclasses).
2132: * @return The positions of the primary key fields/properties.
2133: */
2134: public int[] getPKMemberPositions() {
2135: checkInitialised();
2136: return pkMemberPositions;
2137: }
2138:
2139: /**
2140: * Accessor for the positions of the non primary key fields/properties (inc superclass fields).
2141: * @return The member positions
2142: */
2143: public int[] getNonPKMemberPositions() {
2144: checkInitialised();
2145: return nonPkMemberPositions;
2146: }
2147:
2148: /**
2149: * Accessor for the flags of the non primary key fields/properties (inc superclass members).
2150: * @return The flags whether the field/property is non primary key
2151: */
2152: public boolean[] getNonPKMemberFlags() {
2153: checkInitialised();
2154: return nonPkMemberFlags;
2155: }
2156:
2157: /**
2158: * Accessor for the absolute positions of the default fetch group fields/properties (inc superclasses).
2159: * @return The positions of the DFG fields/properties (inc superclasses).
2160: */
2161: public int[] getDFGMemberPositions() {
2162: checkInitialised();
2163: return dfgMemberPositions;
2164: }
2165:
2166: /**
2167: * Accessor for the flags of the DFG fields/properties (inc superclass).
2168: * @return The flags whether the field/property is in the DFG
2169: **/
2170: public boolean[] getDFGMemberFlags() {
2171: checkInitialised();
2172: return dfgMemberFlags;
2173: }
2174:
2175: /**
2176: * Accessor for the absolute positions of the second class mutable fields/properties.
2177: * @return The field numbers of the second class mutable fields (inc superclasses).
2178: */
2179: public int[] getSCOMutableMemberPositions() {
2180: checkInitialised();
2181: return scoMutableMemberPositions;
2182: }
2183:
2184: /** Field numbers of all SCO fields/properties that arent containers. */
2185: protected int[] scoNonContainerMemberPositions = null;
2186:
2187: /**
2188: * Accessor for the absolute positions of all SCO fields/properties that are NOT containers (e.g Dates, Points, etc)
2189: * @return Field numbers of all SCO non-container fields/properties
2190: */
2191: public int[] getSCONonContainerMemberPositions() {
2192: checkInitialised();
2193: if (scoNonContainerMemberPositions == null) {
2194: int[] noncontainerMemberPositions;
2195: int numberNonContainerSCOFields = 0;
2196: for (int i = 0; i < scoMutableMemberPositions.length; i++) {
2197: AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePosition(scoMutableMemberPositions[i]);
2198: if (!(java.util.Collection.class.isAssignableFrom(fmd
2199: .getType()))
2200: && !(java.util.Map.class.isAssignableFrom(fmd
2201: .getType()))) {
2202: numberNonContainerSCOFields++;
2203: }
2204: }
2205:
2206: noncontainerMemberPositions = new int[numberNonContainerSCOFields];
2207: int nonContNum = 0;
2208: for (int i = 0; i < scoMutableMemberPositions.length; i++) {
2209: AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePosition(scoMutableMemberPositions[i]);
2210: if (!(java.util.Collection.class.isAssignableFrom(fmd
2211: .getType()))
2212: && !(java.util.Map.class.isAssignableFrom(fmd
2213: .getType()))) {
2214: noncontainerMemberPositions[nonContNum++] = scoMutableMemberPositions[i];
2215: }
2216: }
2217:
2218: scoNonContainerMemberPositions = noncontainerMemberPositions;
2219: }
2220: return scoNonContainerMemberPositions;
2221: }
2222:
2223: /** Positions of all SCO fields/properties that are containers. */
2224: protected int[] secondClassContainerMemberPositions = null;
2225:
2226: /**
2227: * Accessor for the absolute positions of all SCO fields/properties that are containers.
2228: * @return Positions of all SCO container fields/properties.
2229: */
2230: public int[] getSCOContainerMemberPositions() {
2231: checkInitialised();
2232: if (secondClassContainerMemberPositions == null) {
2233: int[] containerMemberPositions;
2234: int numberContainerSCOFields = 0;
2235: for (int i = 0; i < scoMutableMemberPositions.length; i++) {
2236: AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePosition(scoMutableMemberPositions[i]);
2237: if (java.util.Collection.class.isAssignableFrom(fmd
2238: .getType())
2239: || java.util.Map.class.isAssignableFrom(fmd
2240: .getType())) {
2241: numberContainerSCOFields++;
2242: }
2243: }
2244:
2245: containerMemberPositions = new int[numberContainerSCOFields];
2246: int contNum = 0;
2247: for (int i = 0; i < scoMutableMemberPositions.length; i++) {
2248: AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePosition(scoMutableMemberPositions[i]);
2249: if (java.util.Collection.class.isAssignableFrom(fmd
2250: .getType())
2251: || java.util.Map.class.isAssignableFrom(fmd
2252: .getType())) {
2253: containerMemberPositions[contNum++] = scoMutableMemberPositions[i];
2254: }
2255: }
2256:
2257: secondClassContainerMemberPositions = containerMemberPositions;
2258: }
2259: return secondClassContainerMemberPositions;
2260: }
2261:
2262: /**
2263: * Accessor for the absolute positions of the PersistenceCapable fields/properties.
2264: * @return The positions of the PersistenceCapable fields/properties (inc superclasses).
2265: */
2266: public int[] getPersistenceCapableMemberPositions() {
2267: checkInitialised();
2268: return persistenceCapableMemberPositions;
2269: }
2270:
2271: /**
2272: * Accessor for the flags of the SCO mutable fields (inc superclass fields).
2273: * @return The flags whether the field is second class mutable
2274: */
2275: public boolean[] getSCOMutableMemberFlags() {
2276: checkInitialised();
2277: return scoMutableMemberFlags;
2278: }
2279:
2280: /**
2281: * Whether this PersistenceCapable class uses SingleFieldIdentity
2282: * @return true if using SingleFieldIdentity as objectid class
2283: */
2284: public boolean usesSingleFieldIdentityClass() {
2285: return usesSingleFieldIdentityClass;
2286: }
2287:
2288: /**
2289: * Accessor for whether this class is fully specified by this metadata and that any
2290: * annotations should be ignored.
2291: * @return Whether we should ignore any annotations
2292: */
2293: public boolean isMetaDataComplete() {
2294: return metaDataComplete;
2295: }
2296:
2297: /** Absolute positions of the fields/properties that have relations. */
2298: int[] relationPositions = null;
2299:
2300: /**
2301: * Convenience method to return if the class has relations to other objects. Includes superclasses.
2302: * @return Whether the class has any relations (that it knows about)
2303: */
2304: public boolean hasRelations(ClassLoaderResolver clr) {
2305: if (relationPositions == null) {
2306: // Relations not yet calculated so do it now
2307: getRelationMemberPositions(clr);
2308: }
2309: return (relationPositions.length > 0);
2310: }
2311:
2312: /**
2313: * Convenience method to return the absolute positions of all fields/properties that have relations.
2314: * @param clr ClassLoader resolver
2315: * @return The absolute positions of all fields/properties that have relations
2316: */
2317: public int[] getRelationMemberPositions(ClassLoaderResolver clr) {
2318: if (relationPositions == null) {
2319: int[] super classRelationPositions = null;
2320: if (pcSuperclassMetaData != null) {
2321: super classRelationPositions = pcSuperclassMetaData
2322: .getRelationMemberPositions(clr);
2323: }
2324:
2325: int numRelationsSuperclass = (super classRelationPositions != null ? super classRelationPositions.length
2326: : 0);
2327: int numRelations = numRelationsSuperclass;
2328: for (int i = 0; i < managedMembers.length; i++) {
2329: if (managedMembers[i].getRelationType(clr) != Relation.NONE) {
2330: numRelations++;
2331: }
2332: }
2333:
2334: relationPositions = new int[numRelations];
2335: int num = 0;
2336: if (numRelationsSuperclass > 0) {
2337: for (int i = 0; i < super classRelationPositions.length; i++) {
2338: relationPositions[num++] = super classRelationPositions[i];
2339: }
2340: }
2341: if (numRelations > numRelationsSuperclass) {
2342: for (int i = 0; i < managedMembers.length; i++) {
2343: if (managedMembers[i].getRelationType(clr) != Relation.NONE) {
2344: relationPositions[num++] = managedMembers[i]
2345: .getAbsoluteFieldNumber();
2346: }
2347: }
2348: }
2349: }
2350: return relationPositions;
2351: }
2352:
2353: /**
2354: * Convenience method to return the absolute positions of fields/properties that have bidirectional
2355: * relations.
2356: * @param clr ClassLoader resolver
2357: * @return Absolute positions of bidirectional relation fields/properties
2358: */
2359: public int[] getBidirectionalRelationMemberPositions(
2360: ClassLoaderResolver clr) {
2361: if (relationPositions == null) {
2362: getRelationMemberPositions(clr);
2363: }
2364:
2365: int numBidirs = 0;
2366: for (int i = 0; i < relationPositions.length; i++) {
2367: AbstractMemberMetaData mmd = getMetaDataForManagedMemberAtAbsolutePosition(relationPositions[i]);
2368: int relationType = mmd.getRelationType(clr);
2369: if (relationType == Relation.ONE_TO_ONE_BI
2370: || relationType == Relation.ONE_TO_MANY_BI
2371: || relationType == Relation.MANY_TO_ONE_BI
2372: || relationType == Relation.MANY_TO_MANY_BI) {
2373: numBidirs++;
2374: }
2375: }
2376:
2377: int[] bidirRelations = new int[numBidirs];
2378: numBidirs = 0;
2379: for (int i = 0; i < relationPositions.length; i++) {
2380: AbstractMemberMetaData mmd = getMetaDataForManagedMemberAtAbsolutePosition(relationPositions[i]);
2381: int relationType = mmd.getRelationType(clr);
2382: if (relationType == Relation.ONE_TO_ONE_BI
2383: || relationType == Relation.ONE_TO_MANY_BI
2384: || relationType == Relation.MANY_TO_ONE_BI
2385: || relationType == Relation.MANY_TO_MANY_BI) {
2386: bidirRelations[numBidirs] = mmd
2387: .getAbsoluteFieldNumber();
2388: }
2389: }
2390: return bidirRelations;
2391: }
2392:
2393: // ------------------------------- Mutators --------------------------------
2394:
2395: /**
2396: * Cinvenience method for updating the identity type when not set correctly during construction.
2397: * This is needed where we have annotations and the user hasnt defined "APPLICATION", and we find a field
2398: * defined as @PrimaryKey so we set it to APPLICATION at that point.
2399: * @param type The Identity type to use
2400: */
2401: public void setIdentityType(IdentityType type) {
2402: if (isPopulated() || isInitialised()) {
2403: throw new JPOXUserException("Already populated/initialised");
2404: }
2405:
2406: this .identityType = type;
2407: }
2408:
2409: /**
2410: * Method to set that this class is "metadata complete" (see JPA spec).
2411: * Means that any annotations will be ignored.
2412: */
2413: public void setMetaDataComplete() {
2414: metaDataComplete = true;
2415: }
2416:
2417: /**
2418: * Method to add a named query to this class. Rejects the addition of
2419: * duplicate named queries.
2420: * @param qmd Meta-Data for the query.
2421: */
2422: public void addQuery(QueryMetaData qmd) {
2423: if (qmd == null) {
2424: return;
2425: }
2426: if (queries == null) {
2427: queries = new HashSet();
2428: }
2429:
2430: queries.add(qmd);
2431: qmd.parent = this ;
2432: }
2433:
2434: /**
2435: * Method to register a query-result MetaData.
2436: * @param resultMetaData Query-Result MetaData to register
2437: */
2438: public void addQueryResultMetaData(
2439: QueryResultMetaData resultMetaData) {
2440: if (queryResultMetaData == null) {
2441: queryResultMetaData = new HashSet();
2442: }
2443: if (!queryResultMetaData.contains(resultMetaData)) {
2444: queryResultMetaData.add(resultMetaData);
2445: }
2446: }
2447:
2448: /**
2449: * Method to add an index to this class.
2450: * @param idxmd Meta-Data for the index.
2451: */
2452: public void addIndex(IndexMetaData idxmd) {
2453: if (idxmd == null) {
2454: return;
2455: }
2456:
2457: if (isInitialised()) {
2458: throw new JPOXUserException("Already initialised");
2459: }
2460: indexes.add(idxmd);
2461: }
2462:
2463: /**
2464: * Method to add an foreign-key to this class.
2465: * @param fkmd Meta-Data for the foreign-key.
2466: */
2467: public void addForeignKey(ForeignKeyMetaData fkmd) {
2468: if (fkmd == null) {
2469: return;
2470: }
2471:
2472: if (isInitialised()) {
2473: throw new JPOXUserException("Already initialised");
2474: }
2475: foreignKeys.add(fkmd);
2476: }
2477:
2478: /**
2479: * Method to add a unique constraint to this class.
2480: * @param unimd Meta-Data for the unique constraint.
2481: */
2482: public void addUniqueConstraint(UniqueMetaData unimd) {
2483: if (unimd == null) {
2484: return;
2485: }
2486:
2487: if (isInitialised()) {
2488: throw new JPOXUserException("Already initialised");
2489: }
2490: uniqueConstraints.add(unimd);
2491: }
2492:
2493: /**
2494: * Method to add an unmapped column.
2495: * @param colmd The metadata for the unmapped column
2496: */
2497: public final void addUnmappedColumn(ColumnMetaData colmd) {
2498: if (unmappedColumns == null) {
2499: unmappedColumns = new ArrayList();
2500: }
2501: unmappedColumns.add(colmd);
2502: }
2503:
2504: /**
2505: * Method to add a field/property to this interface.
2506: * Rejects the addition of duplicate named fields/properties.
2507: * @param mmd Field/Property MetaData
2508: */
2509: public void addMember(AbstractMemberMetaData mmd) {
2510: if (mmd == null) {
2511: return;
2512: }
2513: if (isInitialised()) {
2514: // TODO Localise this message
2515: throw new JPOXUserException("adding field/property "
2516: + mmd.getName() + " when already initialised!");
2517: }
2518:
2519: // Check for conflicting fields/properties
2520: Iterator iter = members.iterator();
2521: while (iter.hasNext()) {
2522: AbstractMemberMetaData md = (AbstractMemberMetaData) iter
2523: .next();
2524: if (mmd.getName().equals(md.getName())) {
2525: if ((mmd instanceof PropertyMetaData && md instanceof PropertyMetaData)
2526: || (mmd instanceof FieldMetaData && md instanceof FieldMetaData)) {
2527: // Duplicate entry for the same field or property
2528: throw new JPOXUserException(LOCALISER.msg("044090",
2529: fullName, mmd.getName()));
2530: }
2531: }
2532:
2533: String existingName = md.getName();
2534: boolean existingIsProperty = (md instanceof PropertyMetaData);
2535: if (existingIsProperty) {
2536: existingName = ((PropertyMetaData) md).getFieldName();
2537: if (existingName == null) {
2538: // "fieldName" not specified so default to the property name
2539: existingName = md.getName();
2540: }
2541: }
2542: String newName = mmd.getName();
2543: boolean newIsProperty = (mmd instanceof PropertyMetaData);
2544: if (newIsProperty) {
2545: newName = ((PropertyMetaData) mmd).getFieldName();
2546: if (newName == null) {
2547: // "fieldName" not specified so default to the property name
2548: newName = mmd.getName();
2549: }
2550: }
2551:
2552: if (existingName.equals(newName)) {
2553: if (existingIsProperty && newIsProperty) {
2554: // Duplicate entry for the same field or property
2555: throw new JPOXUserException(LOCALISER.msg("044090",
2556: fullName, mmd.getName()));
2557: } else if (existingIsProperty && !newIsProperty) {
2558: // We have the property and this is a field so ignore it
2559: // TODO Check if one is not persistent before discarding
2560: JPOXLogger.JDO
2561: .info("Ignoring metadata for field "
2562: + mmd.getFullFieldName()
2563: + " since we already have MetaData for the property "
2564: + md.getFullFieldName());
2565: return;
2566: } else if (!existingIsProperty && newIsProperty) {
2567: // We have the field and this is property so replace the field with it
2568: // TODO Check if one is not persistent before discarding
2569: JPOXLogger.JDO
2570: .info("Ignoring existing metadata for field "
2571: + md.getFullFieldName()
2572: + " since now we have MetaData for the property "
2573: + mmd.getFullFieldName());
2574: iter.remove();
2575: }
2576: }
2577: }
2578:
2579: mmd.parent = this ;
2580: members.add(mmd);
2581: }
2582:
2583: /**
2584: * Method to add a fetch-group to this class.
2585: * @param fgmd Meta-Data for the fetch-group.
2586: */
2587: public void addFetchGroup(FetchGroupMetaData fgmd) {
2588: if (fgmd == null) {
2589: return;
2590: }
2591:
2592: if (isInitialised()) {
2593: throw new JPOXUserException("Already initialised");
2594: }
2595: fetchGroups.add(fgmd);
2596: fgmd.parent = this ;
2597: }
2598:
2599: /**
2600: * Method to add a join to this class.
2601: * Rejects the addition of duplicate named fields.
2602: * @param jnmd Meta-Data for the join.
2603: */
2604: public void addJoin(JoinMetaData jnmd) {
2605: if (jnmd == null) {
2606: return;
2607: }
2608:
2609: if (isInitialised()) {
2610: throw new JPOXUserException("Already initialised");
2611: }
2612: joins.add(jnmd);
2613: }
2614:
2615: /**
2616: * Add a listener class name
2617: * @param listener the listener metadata. Duplicated classes are ignored
2618: */
2619: public void addListener(EventListenerMetaData listener) {
2620: if (listeners == null) {
2621: listeners = new ArrayList();
2622: }
2623: if (!listeners.contains(listener)) {
2624: listeners.add(listener);
2625: }
2626: }
2627:
2628: /**
2629: * Accessor for the EventListener info for an EventListener class name
2630: * @param className Name of the event listener class
2631: * @return EventListener info for this class (or null if the class isnt an EventListener)
2632: */
2633: public EventListenerMetaData getListenerForClass(String className) {
2634: if (listeners == null) {
2635: return null;
2636: }
2637:
2638: for (int i = 0; i < listeners.size(); i++) {
2639: EventListenerMetaData elmd = (EventListenerMetaData) listeners
2640: .get(i);
2641: if (elmd.getClassName().equals(className)) {
2642: return elmd;
2643: }
2644: }
2645:
2646: return null;
2647: }
2648:
2649: /**
2650: * Get the event listeners
2651: * @return the event listeners
2652: */
2653: public List getListeners() {
2654: return listeners;
2655: }
2656:
2657: /**
2658: * Toogle exclude super class listeners
2659: */
2660: public void excludeSuperClassListeners() {
2661: this .excludeSuperClassListeners = Boolean.TRUE;
2662: }
2663:
2664: /**
2665: * Whether super classes listeners are not going to be invoked
2666: * @return true if super class listeners are not invoked
2667: */
2668: public boolean isExcludeSuperClassListeners() {
2669: if (excludeSuperClassListeners != null
2670: && excludeSuperClassListeners == Boolean.TRUE) {
2671: return true;
2672: } else {
2673: return false;
2674: }
2675: }
2676:
2677: /**
2678: * Method to exclude default listeners.
2679: */
2680: public void excludeDefaultListeners() {
2681: this .excludeDefaultListeners = Boolean.TRUE;
2682: }
2683:
2684: /**
2685: * Whether default listeners are not going to be invoked
2686: * @return true if default listeners are not invoked
2687: */
2688: public boolean isExcludeDefaultListeners() {
2689: if (excludeDefaultListeners != null
2690: && excludeDefaultListeners == Boolean.TRUE) {
2691: return true;
2692: } else {
2693: return false;
2694: }
2695: }
2696:
2697: /**
2698: * Mutator for the Version MetaData.
2699: * @param versionMetaData The versionMetaData to set.
2700: */
2701: public final void setVersionMetaData(VersionMetaData versionMetaData) {
2702: this .versionMetaData = versionMetaData;
2703: if (this .versionMetaData != null) {
2704: this .versionMetaData.parent = this ;
2705: }
2706: }
2707:
2708: /**
2709: * Mutator for the identity MetaData.
2710: * @param identityMetaData The identityMetaData to set.
2711: */
2712: public final void setIdentityMetaData(
2713: IdentityMetaData identityMetaData) {
2714: this .identityMetaData = identityMetaData;
2715: if (this .identityMetaData != null) {
2716: this .identityMetaData.parent = this ;
2717: }
2718: identitySpecified = true;
2719: }
2720:
2721: /**
2722: * Mutator for the inheritance MetaData.
2723: * @param inheritanceMetaData The inheritanceMetaData to set.
2724: */
2725: public final void setInheritanceMetaData(
2726: InheritanceMetaData inheritanceMetaData) {
2727: this .inheritanceMetaData = inheritanceMetaData;
2728: if (this .inheritanceMetaData != null) {
2729: this .inheritanceMetaData.parent = this ;
2730: }
2731: }
2732:
2733: /**
2734: * Mutator for the PrimaryKey MetaData.
2735: * @param primaryKeyMetaData The PrimaryKey MetaData to set.
2736: */
2737: public final void setPrimaryKeyMetaData(
2738: PrimaryKeyMetaData primaryKeyMetaData) {
2739: this .primaryKeyMetaData = primaryKeyMetaData;
2740: if (this .primaryKeyMetaData != null) {
2741: this .primaryKeyMetaData.parent = this ;
2742: }
2743: }
2744:
2745: /**
2746: * Mutator for the table name.
2747: * @param table Name of the table
2748: */
2749: public final void setTable(String table) {
2750: this .table = (StringUtils.isWhitespace(table) ? this .table
2751: : table);
2752: }
2753:
2754: /**
2755: * Mutator for the catalog name.
2756: * @param catalog Name of the catalog
2757: */
2758: public final void setCatalog(String catalog) {
2759: this .catalog = (StringUtils.isWhitespace(catalog) ? this .catalog
2760: : catalog);
2761: }
2762:
2763: /**
2764: * Mutator for the schema name.
2765: * @param schema Name of the schema
2766: */
2767: public final void setSchema(String schema) {
2768: this .schema = (StringUtils.isWhitespace(schema) ? this .schema
2769: : schema);
2770: }
2771:
2772: /**
2773: * Mutator for the object id class name.
2774: * @param objectidClass Name of the id class
2775: */
2776: public final void setObjectIdClass(String objectidClass) {
2777: this.objectidClass = (StringUtils.isWhitespace(objectidClass) ? this.objectidClass
2778: : objectidClass);
2779: }
2780: }
|