Source Code Cross Referenced for AbstractClassMetaData.java in  » Database-ORM » JPOX » org » jpox » metadata » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » JPOX » org.jpox.metadata 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.