Source Code Cross Referenced for ClassMetaData.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) 2004 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:        Contributors:
0016:        2004 Kikuchi Kousuke - org.jpox.enhancer.conf.JDOConfigClass
0017:        2004 Marco Schulze (NightLabs) - changed the behaviour to warn only if
0018:                an inherited class declares an own objectid and it equals the
0019:                one of the superclass.
0020:        2004 Andy Jefferson - Added discriminator/inheritance checks
0021:        2004 Erik Bengtson - changes for application identity
0022:        2004 Andy Jefferson - moved PK class checks out into JDOUtils
0023:        2007 Xuan Baldauf - little reduction in code duplication to anticipate changes regarding issue http://www.jpox.org/servlet/jira/browse/CORE-3272
0024:            ...
0025:         **********************************************************************/package org.jpox.metadata;
0026:
0027:        import java.lang.reflect.Field;
0028:        import java.lang.reflect.Method;
0029:        import java.lang.reflect.Modifier;
0030:        import java.util.ArrayList;
0031:        import java.util.Collection;
0032:        import java.util.Collections;
0033:        import java.util.HashMap;
0034:        import java.util.Iterator;
0035:        import java.util.List;
0036:
0037:        import org.jpox.ClassLoaderResolver;
0038:        import org.jpox.exceptions.ClassNotResolvedException;
0039:        import org.jpox.exceptions.JPOXException;
0040:        import org.jpox.util.ClassUtils;
0041:        import org.jpox.util.JPOXLogger;
0042:
0043:        /**
0044:         * Representation of the MetaData of a class. Extends the abstract definition to include
0045:         * implementations, fields, embedded-only tags. Has a parent PackageMetaData that
0046:         * can contain the metadata for several classes.
0047:         *
0048:         * <H3>Lifecycle state</H3>
0049:         * This object supports 3 lifecycle states. The first is the raw
0050:         * constructed object which represents pure MetaData (maybe from a MetaData
0051:         * file). The second is a "populated" object which represents MetaData for a
0052:         * Class with the metadata aligned to be appropriate for that Class.
0053:         * The third is "initialised" once the internal arrays are created.
0054:         * This object, once populated, will represent ALL fields in the class
0055:         * (including static, final and transient fields).
0056:         *
0057:         * <H3>Fields/Properties</H3>
0058:         * This object keeps a list of FieldMetaData/PropertyMetaData objects for the fields of this class. 
0059:         * In addition it has an array of FieldMetaData
0060:         * objects representing those that are actually managed by JDO
0061:         * ("managedFields"). This second set does not contain things like static, final
0062:         * or transient fields since JDO doesn't support those yet.
0063:         * <P>Fields are of 2 types. The first are normal fields of this class.
0064:         * These have their own "relative" field number, relative to this class.
0065:         * The second type are "overriding" fields which override the baseline field
0066:         * in a superclass. These fields have no "relative" field number since they are
0067:         * relative to this class (and such a relative field number would make no sense).
0068:         * Fields are all added through addField() during the parse process, and
0069:         * are updated during the populate/initialise process to define their relative field
0070:         * numbers. Please refer to FieldMetaData for more details of fields.
0071:         *
0072:         * <H3>Numbering of fields</H3>
0073:         * Fields of the class are numbered in 2 ways. The first way is the numbering
0074:         * within a class. In a class, the field 'id's will start at 0. If a class is
0075:         * inherited, it will also have a second numbering for its fields - the
0076:         * "absolute" numbering. With "absolute" numbering, the fields start at the
0077:         * first field in the root superclass which has absolute number 0, and they are
0078:         * numbered from there, navigating down the hierarchy. In terms of what is
0079:         * stored in the records, the FieldMetaData stores fieldId as the first
0080:         * method (relative to the class it is in). The "absolute" numbering is 
0081:         * always derived from this and the inheritance hierarchy.
0082:         *
0083:         * <H3>MetaData Element</H3>
0084:         * The MetaData Element represented here is as follows
0085:         * <PRE>
0086:         * &lt;!ELEMENT class (datastore-identity?, implements*, inheritance?, version?, join*,
0087:         *      foreign-key*, index*, unique*, field*, column*, query*, fetch-group*, extension*)&gt;
0088:         * &lt;!ATTLIST class name CDATA #REQUIRED&gt;
0089:         * &lt;!ATTLIST class identity-type (application|datastore|nondurable) #IMPLIED&gt;
0090:         * &lt;!ATTLIST class catalog CDATA #IMPLIED&gt;
0091:         * &lt;!ATTLIST class schema CDATA #IMPLIED&gt;
0092:         * &lt;!ATTLIST class table CDATA #IMPLIED&gt;
0093:         * &lt;!ATTLIST class persistence-capable-superclass CDATA #IMPLIED&gt;
0094:         * &lt;!ATTLIST class objectid-class CDATA #IMPLIED&gt;
0095:         * &lt;!ATTLIST class requires-extent (true|false) 'true'&gt;
0096:         * &lt;!ATTLIST class detachable (true|false) 'true'&gt;
0097:         * &lt;!ATTLIST class embedded-only (true|false) #IMPLIED&gt;
0098:         * &lt;!ATTLIST class persistence-modifier 
0099:         *      (persistence-capable|persistence-aware|non-persistent) #IMPLIED&gt;
0100:         * </PRE>
0101:         *
0102:         * @since 1.1
0103:         * @version $Revision: 1.136 $
0104:         */
0105:        public class ClassMetaData extends AbstractClassMetaData {
0106:            /** List of implements. */
0107:            protected List implementations = new ArrayList();
0108:
0109:            // -------------------------------------------------------------------------
0110:            // Fields below here are not represented in the output MetaData. They are
0111:            // for use internally in the operation of the JDO system. The majority are
0112:            // for convenience to save iterating through the fields since the fields
0113:            // are fixed once initialised.
0114:
0115:            /*** ImplementsMetaData */
0116:            protected ImplementsMetaData[] implements MetaData;
0117:
0118:            /** is the persistable class abstract. */
0119:            protected boolean isAbstractPersistenceCapable;
0120:
0121:            /** whether the populate method is running **/
0122:            private boolean populating = false;
0123:
0124:            // ----------------------------- Constructors ------------------------------
0125:
0126:            /**
0127:             * Constructor.
0128:             * Takes the basic string information found in the MetaData file.
0129:             * @param parent The package to which this class belongs
0130:             * @param name Name of class
0131:             * @param identityType identity-type flag
0132:             * @param objectidClass Primary key class name
0133:             * @param requiresExtent Whether the class requires an extent
0134:             * @param detachable Whether the class can be detached
0135:             * @param modifier persistence-modifier tag
0136:             * @param embeddedOnly embedded-only tag
0137:             * @param persistenceCapableSuperclass Name of PC superclass
0138:             * @param catalog Name for catalog
0139:             * @param schema Name for schema
0140:             * @param table RDBMS table to store the class in
0141:             * @param entityName the entity name required by JPA §4.3.1
0142:             */
0143:            public ClassMetaData(final PackageMetaData parent,
0144:                    final String name, final String identityType,
0145:                    final String objectidClass, final String requiresExtent,
0146:                    final String detachable, final String embeddedOnly,
0147:                    final String modifier,
0148:                    final String persistenceCapableSuperclass,
0149:                    final String catalog, final String schema,
0150:                    final String table, final String entityName) {
0151:                super (parent, name, identityType, objectidClass,
0152:                        requiresExtent, detachable, embeddedOnly, modifier,
0153:                        persistenceCapableSuperclass, catalog, schema, table,
0154:                        entityName);
0155:            }
0156:
0157:            /**
0158:             * Constructor for creating the ClassMetaData for an implementation of a "persistent-interface".
0159:             * @param imd MetaData for the "persistent-interface"
0160:             * @param implClassName Name of the implementation class
0161:             * @param copyFields Whether to copy the fields of the interface too
0162:             */
0163:            public ClassMetaData(final InterfaceMetaData imd,
0164:                    String implClassName, boolean copyFields) {
0165:                super (imd, implClassName, copyFields);
0166:            }
0167:
0168:            /**
0169:             * Constructor for creating the ClassMetaData for an implementation of a "persistent-abstract-class".
0170:             * @param cmd MetaData for the implementation of the "persistent-abstract-class"
0171:             * @param implClassName Name of the implementation class
0172:             */
0173:            public ClassMetaData(final ClassMetaData cmd, String implClassName) {
0174:                super (cmd, implClassName);
0175:            }
0176:
0177:            /**
0178:             * Method to provide the details of the class being represented by this
0179:             * MetaData. This can be used to firstly provide defaults for attributes
0180:             * that aren't specified in the MetaData, and secondly to report any errors
0181:             * with attributes that have been specifed that are inconsistent with the
0182:             * class being represented.
0183:             * <P>
0184:             * One possible use of this method would be to take a basic ClassMetaData
0185:             * for a class and call this, passing in the users class. This would then
0186:             * add FieldMetaData for all fields in this class providing defaults for
0187:             * all of these.
0188:             *
0189:             * @param clr ClassLoaderResolver to use in loading any classes
0190:             * @param primary the primary ClassLoader to use (or null)
0191:             */
0192:            public synchronized void populate(ClassLoaderResolver clr,
0193:                    ClassLoader primary) {
0194:                if (isInitialised() || isPopulated()) {
0195:                    JPOXLogger.METADATA.error(LOCALISER.msg("044068", name));
0196:                    throw new JPOXException(LOCALISER.msg("044068", fullName))
0197:                            .setFatal();
0198:                }
0199:                if (populating) {
0200:                    return;
0201:                }
0202:
0203:                try {
0204:                    if (JPOXLogger.METADATA.isDebugEnabled()) {
0205:                        JPOXLogger.METADATA.debug(LOCALISER.msg("044075",
0206:                                fullName));
0207:                    }
0208:                    populating = true;
0209:
0210:                    Class cls = loadClass(clr, primary);
0211:
0212:                    isAbstractPersistenceCapable = Modifier.isAbstract(cls
0213:                            .getModifiers());
0214:
0215:                    // Load any Annotations definition for this class
0216:                    if (!isMetaDataComplete()) {
0217:                        getMetaDataManager().addAnnotationsDataToClass(cls,
0218:                                this , clr);
0219:                    }
0220:
0221:                    // Load any ORM definition for this class
0222:                    getMetaDataManager().addORMDataToClass(cls, clr);
0223:
0224:                    // If a class is an inner class and is non-static it is invalid
0225:                    if (ClassUtils.isInnerClass(fullName)
0226:                            && !Modifier.isStatic(cls.getModifiers())
0227:                            && persistenceModifier == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
0228:                        throw new InvalidMetaDataException(LOCALISER, "044063",
0229:                                fullName);
0230:                    }
0231:
0232:                    if (entityName == null) {
0233:                        // No entity name given so just default to the name of the class (without package)
0234:                        this .entityName = name;
0235:                    }
0236:
0237:                    determineSuperClassName(clr, cls);
0238:
0239:                    inheritDetachableSettings();
0240:
0241:                    inheritIdentity();
0242:
0243:                    determineIdentity();
0244:
0245:                    validateUserInputForIdentity();
0246:
0247:                    addMetaDataForMembersNotInMetaData(cls);
0248:
0249:                    if (objectidClass == null) {
0250:                        // No user-defined objectid-class but potentially have SingleFieldIdentity so make sure PK fields are set
0251:                        populateMemberMetaData(clr, cls, true, primary); // Make sure all PK fields (and superclasses) are set before objectid-class
0252:                        determineObjectIdClass(clr);
0253:                        populateMemberMetaData(clr, cls, false, primary); // Populate non-PK fields
0254:                    } else {
0255:                        populateMemberMetaData(clr, cls, true, primary);
0256:                        populateMemberMetaData(clr, cls, false, primary);
0257:                        determineObjectIdClass(clr);
0258:                    }
0259:
0260:                    validateUserInputForInheritanceMetaData();
0261:
0262:                    determineInheritanceMetaData();
0263:
0264:                    validateDeprecatedMetaData();
0265:
0266:                    validateUnmappedColumns();
0267:
0268:                    // populate the implements
0269:                    for (int i = 0; i < implementations.size(); i++) {
0270:                        ((ImplementsMetaData) implementations.get(i))
0271:                                .populate(clr);
0272:                    }
0273:
0274:                    if (persistentInterfaceImplNeedingTableFromSuperclass) {
0275:                        // Need to go up to next superinterface and make sure its metadata is populated
0276:                        // until we find the next interface with metadata with inheritance strategy of "new-table".
0277:                        AbstractClassMetaData acmd = getMetaDataForSuperinterfaceManagingTable(
0278:                                cls, clr);
0279:                        if (acmd != null) {
0280:                            table = acmd.table;
0281:                            schema = acmd.schema;
0282:                            catalog = acmd.catalog;
0283:                        }
0284:                        persistentInterfaceImplNeedingTableFromSuperclass = false;
0285:                    } else if (persistentInterfaceImplNeedingTableFromSubclass) {
0286:                        // TODO Cater for finding the subclass-table that manages our table
0287:                        persistentInterfaceImplNeedingTableFromSubclass = false;
0288:                    }
0289:
0290:                    setPopulated();
0291:                } catch (RuntimeException e) {
0292:                    JPOXLogger.METADATA.debug(e);
0293:                    throw e;
0294:                } finally {
0295:                    populating = false;
0296:                }
0297:            }
0298:
0299:            /**
0300:             * Method to find a superinterface with MetaData that specifies NEW_TABLE inheritance strategy
0301:             * @param cls The class
0302:             * @param clr ClassLoader resolver
0303:             * @return The AbstractClassMetaData for the class managing the table
0304:             */
0305:            private AbstractClassMetaData getMetaDataForSuperinterfaceManagingTable(
0306:                    Class cls, ClassLoaderResolver clr) {
0307:                Collection super interfaces = ClassUtils.getSuperinterfaces(cls);
0308:                Iterator iter = super interfaces.iterator();
0309:                while (iter.hasNext()) {
0310:                    Class super intf = (Class) iter.next();
0311:                    AbstractClassMetaData acmd = getMetaDataManager()
0312:                            .getMetaDataForInterface(super intf, clr);
0313:                    if (acmd != null && acmd.getInheritanceMetaData() != null) {
0314:                        if (acmd.getInheritanceMetaData().getStrategyValue() == InheritanceStrategy.NEW_TABLE) {
0315:                            // Found it
0316:                            return acmd;
0317:                        } else if (acmd.getInheritanceMetaData()
0318:                                .getStrategyValue() == InheritanceStrategy.SUPERCLASS_TABLE) {
0319:                            // Try further up the hierarchy
0320:                            return getMetaDataForSuperinterfaceManagingTable(
0321:                                    super intf, clr);
0322:                        }
0323:                    }
0324:                }
0325:                return null;
0326:            }
0327:
0328:            /**
0329:             * Add MetaData of fields/properties not declared in MetaData.
0330:             * @param cls Class represented by this metadata
0331:             */
0332:            protected void addMetaDataForMembersNotInMetaData(Class cls) {
0333:                // Access API since we treat things differently for JPA and JDO
0334:                String api = getMetaDataManager().getOMFContext().getApi();
0335:
0336:                // Add fields/properties for the class that don't have MetaData.
0337:                // We use Reflection here since JDOImplHelper would only give use info
0338:                // for enhanced files (and the enhancer needs unenhanced as well). 
0339:                // NOTE 1 : We ignore fields/properties in superclasses
0340:                // NOTE 2 : We ignore "enhanced" fields/properties (added by the JPOX enhancer)
0341:                // NOTE 3 : We ignore inner class fields/properties (containing "$")
0342:                // NOTE 4 : We sort the fields/properties into ascending alphabetical order
0343:                Collections.sort(members);
0344:                try {
0345:                    // check if we have any persistent properties (JPA)
0346:                    boolean hasProperties = false;
0347:                    for (int i = 0; i < members.size(); i++) {
0348:                        if (((AbstractMemberMetaData) members.get(i))
0349:                                .isProperty()) {
0350:                            hasProperties = true;
0351:                            break;
0352:                        }
0353:                    }
0354:
0355:                    if (hasProperties && api.equalsIgnoreCase("JPA")) {
0356:                        // JPA : when we are using properties go through and add properties for those not specified.
0357:                        // Process all (reflected) methods in the populating class
0358:                        Method[] clsMethods = cls.getDeclaredMethods();
0359:                        for (int i = 0; i < clsMethods.length; i++) {
0360:                            // Limit to getter methods in this class, that aren't enhancer-added methods
0361:                            // that aren't inner class methods, and that aren't static
0362:                            if (clsMethods[i].getDeclaringClass().getName()
0363:                                    .equals(fullName)
0364:                                    && !clsMethods[i].getName().startsWith(
0365:                                            "jdo")
0366:                                    && (clsMethods[i].getName().startsWith(
0367:                                            "get") || clsMethods[i].getName()
0368:                                            .startsWith("is"))
0369:                                    && !ClassUtils.isInnerClass(clsMethods[i]
0370:                                            .getName())
0371:                                    && !Modifier.isStatic(clsMethods[i]
0372:                                            .getModifiers())) {
0373:                                // Find if there is metadata for this property
0374:                                String propertyName = ClassUtils
0375:                                        .getFieldNameForJavaBeanGetter(clsMethods[i]
0376:                                                .getName());
0377:                                if (Collections.binarySearch(members,
0378:                                        propertyName) < 0) // AbstractMemberMetaData implements Comparable
0379:                                {
0380:                                    // No field/property of this name - add a default PropertyMetaData for this method
0381:                                    JPOXLogger.METADATA.debug(LOCALISER.msg(
0382:                                            "044060", propertyName, name));
0383:                                    AbstractMemberMetaData fmd = getMetaDataManager()
0384:                                            .getMetaDataFactory()
0385:                                            .newPropertyObject(this ,
0386:                                                    propertyName, null, null,
0387:                                                    null, null, null, null,
0388:                                                    null, null, null, null,
0389:                                                    null, null, null, null,
0390:                                                    null, null, null, null,
0391:                                                    null, null, null);
0392:                                    members.add(fmd);
0393:                                    Collections.sort(members);
0394:                                } else {
0395:                                    // Field/property exists
0396:                                }
0397:                            }
0398:                        }
0399:                    }
0400:
0401:                    // Process all (reflected) fields in the populating class
0402:                    Field[] clsFields = cls.getDeclaredFields();
0403:                    for (int i = 0; i < clsFields.length; i++) {
0404:                        // Limit to fields in this class, that aren't enhancer-added fields
0405:                        // that aren't inner class fields, and that aren't static
0406:                        if (clsFields[i].getDeclaringClass().getName().equals(
0407:                                fullName)
0408:                                && !clsFields[i].getName().startsWith("jdo")
0409:                                && !ClassUtils.isInnerClass(clsFields[i]
0410:                                        .getName())
0411:                                && !Modifier.isStatic(clsFields[i]
0412:                                        .getModifiers())) {
0413:                            // Find if there is metadata for this field.
0414:                            // This is possible as FieldMetaData implements Comparable
0415:                            if (Collections.binarySearch(members, clsFields[i]
0416:                                    .getName()) < 0) {
0417:                                // No field/property of this name
0418:                                if (hasProperties
0419:                                        && api.equalsIgnoreCase("JPA")) {
0420:                                    // JPA : Class has properties but field not present, so add as transient field (JPA)
0421:                                    AbstractMemberMetaData fmd = getMetaDataManager()
0422:                                            .getMetaDataFactory()
0423:                                            .newFieldObject(this ,
0424:                                                    clsFields[i].getName(),
0425:                                                    null, "none", null, null,
0426:                                                    null, null, null, null,
0427:                                                    null, null, null, null,
0428:                                                    null, null, null, null,
0429:                                                    null, null, null, null);
0430:                                    members.add(fmd);
0431:                                    Collections.sort(members);
0432:                                } else {
0433:                                    // Class has fields but field not present, so add as field
0434:                                    JPOXLogger.METADATA.debug(LOCALISER.msg(
0435:                                            "044060", clsFields[i].getName(),
0436:                                            name));
0437:                                    AbstractMemberMetaData fmd = getMetaDataManager()
0438:                                            .getMetaDataFactory()
0439:                                            .newFieldObject(this ,
0440:                                                    clsFields[i].getName(),
0441:                                                    null, null, null, null,
0442:                                                    null, null, null, null,
0443:                                                    null, null, null, null,
0444:                                                    null, null, null, null,
0445:                                                    null, null, null, null);
0446:                                    members.add(fmd);
0447:                                    Collections.sort(members);
0448:                                }
0449:                            }
0450:                        }
0451:                    }
0452:                } catch (Exception e) {
0453:                    JPOXLogger.METADATA.error(e.getMessage(), e);
0454:                    throw new RuntimeException(e.getMessage());
0455:                }
0456:            }
0457:
0458:            /**
0459:             * Populate MetaData for all members.
0460:             * @param clr The ClassLoaderResolver
0461:             * @param cls This class
0462:             * @param pkMembers Process pk fields/properties (or non-PK if false)
0463:             * @param primary the primary ClassLoader to use (or null)
0464:             * @throws InvalidMetaDataException if the Class for a declared type in a field cannot be loaded by the <code>clr</code>
0465:             * @throws InvalidMetaDataException if a field declared in the MetaData does not exist in the Class
0466:             */
0467:            protected void populateMemberMetaData(ClassLoaderResolver clr,
0468:                    Class cls, boolean pkMembers, ClassLoader primary) {
0469:                Collections.sort(members);
0470:
0471:                // Populate the FieldMetaData with their real field values
0472:                // This will populate any containers in these fields also
0473:                Iterator fields_iter = members.iterator();
0474:                while (fields_iter.hasNext()) {
0475:                    AbstractMemberMetaData fmd = (AbstractMemberMetaData) fields_iter
0476:                            .next();
0477:                    if (pkMembers == fmd.isPrimaryKey()) {
0478:                        Class fieldCls = cls;
0479:                        if (fmd.className != null
0480:                                && fmd.className.equals("#UNKNOWN")) {
0481:                            // Field is for a superclass but we didnt know which at creation so resolve it
0482:                            if (pcSuperclassMetaData != null) {
0483:                                AbstractMemberMetaData super Fmd = pcSuperclassMetaData
0484:                                        .getMetaDataForMember(fmd.getName());
0485:                                if (super Fmd != null) {
0486:                                    // Field is for a superclass so set its "className"
0487:                                    if (super Fmd.className != null) {
0488:                                        fmd.className = super Fmd.className;
0489:                                    } else {
0490:                                        fmd.className = super Fmd.getClassName();
0491:                                    }
0492:                                }
0493:                            } else {
0494:                                // No superclass so it doenst make sense so assume to be for this class
0495:                                fmd.className = null;
0496:                            }
0497:                        }
0498:                        if (!fmd.fieldBelongsToClass()) {
0499:                            // Field overrides a field in a superclass, so find the class
0500:                            try {
0501:                                fieldCls = clr.classForName(fmd.getClassName());
0502:                            } catch (ClassNotResolvedException cnre) {
0503:                                // Not found at specified location, so try the same package as this class
0504:                                String fieldClassName = getPackageName() + "."
0505:                                        + fmd.getClassName();
0506:                                try {
0507:                                    fieldCls = clr.classForName(fieldClassName);
0508:                                    fmd.setClassName(fieldClassName);
0509:                                } catch (ClassNotResolvedException cnre2) {
0510:                                    JPOXLogger.METADATA.error(LOCALISER.msg(
0511:                                            "044080", fieldClassName));
0512:                                    throw new InvalidMetaDataException(
0513:                                            LOCALISER, "044080", fieldClassName);
0514:                                }
0515:                            }
0516:                        }
0517:
0518:                        boolean populated = false;
0519:                        if (fmd.isProperty()) {
0520:                            // User class must have a getter and setter for this property as per Java Beans
0521:                            Method getMethod = null;
0522:                            try {
0523:                                // Find the getter
0524:                                // a). Try as a standard form of getter (getXXX)
0525:                                getMethod = fieldCls.getDeclaredMethod(
0526:                                        ClassUtils.getJavaBeanGetterName(fmd
0527:                                                .getName(), false), null);
0528:                            } catch (Exception e) {
0529:                                try {
0530:                                    // b). Try as a boolean form of getter (isXXX)
0531:                                    getMethod = fieldCls.getDeclaredMethod(
0532:                                            ClassUtils.getJavaBeanGetterName(
0533:                                                    fmd.getName(), true), null);
0534:                                } catch (Exception e2) {
0535:                                }
0536:                            }
0537:                            if (getMethod == null
0538:                                    && fmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
0539:                                // Property is persistent yet no getter!
0540:                                throw new InvalidMetaDataException(LOCALISER,
0541:                                        "044073", fullName, fmd.getName());
0542:                            }
0543:
0544:                            Method setMethod = null;
0545:                            try {
0546:                                // Find the setter
0547:                                String setterName = ClassUtils
0548:                                        .getJavaBeanSetterName(fmd.getName());
0549:                                Method[] methods = fieldCls
0550:                                        .getDeclaredMethods();
0551:                                for (int i = 0; i < methods.length; i++) {
0552:                                    if (methods[i].getName().equals(setterName)
0553:                                            && methods[i].getParameterTypes() != null
0554:                                            && methods[i].getParameterTypes().length == 1) {
0555:                                        setMethod = methods[i];
0556:                                    }
0557:                                }
0558:                            } catch (Exception e) {
0559:                            }
0560:                            if (setMethod == null
0561:                                    && fmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
0562:                                // Property is persistent yet no setter!
0563:                                throw new InvalidMetaDataException(LOCALISER,
0564:                                        "044074", fullName, fmd.getName());
0565:                            }
0566:
0567:                            // Populate the property using the getter
0568:                            if (getMethod != null) {
0569:                                fmd.populate(clr, null, getMethod, primary);
0570:                                populated = true;
0571:                            }
0572:                        }
0573:                        // TODO Why is this next block capable of processing things declared as property?
0574:                        if (!populated) {
0575:                            Field cls_field = null;
0576:                            try {
0577:                                cls_field = fieldCls.getDeclaredField(fmd
0578:                                        .getName());
0579:                            } catch (Exception e) {
0580:                            }
0581:                            if (cls_field != null) {
0582:                                fmd.populate(clr, cls_field, null, primary);
0583:                                populated = true;
0584:                            }
0585:                        }
0586:                        if (!populated) {
0587:                            // MetaData field doesn't exist in the class!
0588:                            throw new InvalidMetaDataException(LOCALISER,
0589:                                    "044071", fullName, fmd.getFullFieldName());
0590:                        }
0591:                    }
0592:                }
0593:            }
0594:
0595:            /**
0596:             * Method to initialise the object, creating internal convenience arrays.
0597:             * Initialises all sub-objects. populate() should be called BEFORE calling this.
0598:             */
0599:            public synchronized void initialise() {
0600:                if (populating) {
0601:                    return;
0602:                }
0603:                checkPopulated();
0604:                if (isInitialised()) {
0605:                    return;
0606:                }
0607:
0608:                if (pcSuperclassMetaData != null) {
0609:                    // We need our superclass to be initialised before us because we rely on information there
0610:                    if (!pcSuperclassMetaData.isInitialised()) {
0611:                        pcSuperclassMetaData.initialise();
0612:                    }
0613:                }
0614:
0615:                if (JPOXLogger.METADATA.isDebugEnabled()) {
0616:                    JPOXLogger.METADATA
0617:                            .debug(LOCALISER.msg("044076", fullName));
0618:                }
0619:
0620:                // Count the fields/properties of the relevant category
0621:                Iterator membersIter = members.iterator();
0622:                int numManaged = 0;
0623:                int numOverridden = 0;
0624:                while (membersIter.hasNext()) {
0625:                    AbstractMemberMetaData fmd = (AbstractMemberMetaData) membersIter
0626:                            .next();
0627:
0628:                    // Initialise the FieldMetaData (and its sub-objects)
0629:                    fmd.initialise();
0630:                    if (fmd.isJdoField()) {
0631:                        if (fmd.fieldBelongsToClass()) {
0632:                            numManaged++;
0633:                        } else {
0634:                            numOverridden++;
0635:                        }
0636:                    }
0637:                }
0638:
0639:                // Generate the "managed members" list
0640:                managedMembers = new AbstractMemberMetaData[numManaged];
0641:                overriddenMembers = new AbstractMemberMetaData[numOverridden];
0642:
0643:                membersIter = members.iterator();
0644:                int field_id = 0;
0645:                int overridden_field_id = 0;
0646:                memberPositionsByName = new HashMap();
0647:                while (membersIter.hasNext()) {
0648:                    AbstractMemberMetaData mmd = (AbstractMemberMetaData) membersIter
0649:                            .next();
0650:                    if (mmd.isJdoField()) {
0651:                        if (mmd.fieldBelongsToClass()) {
0652:                            mmd.setFieldId(field_id);
0653:                            managedMembers[field_id] = mmd;
0654:                            memberPositionsByName.put(mmd.getName(),
0655:                                    new Integer(field_id));
0656:                            field_id++;
0657:                        } else {
0658:                            overriddenMembers[overridden_field_id++] = mmd;
0659:                            AbstractMemberMetaData super Fmd = pcSuperclassMetaData
0660:                                    .getMemberBeingOverridden(mmd.getName());
0661:                            if (super Fmd != null) {
0662:                                // Merge in any additional info not specified in the overridden field
0663:                                if (super Fmd.isPrimaryKey()) {
0664:                                    mmd.setPrimaryKey();
0665:                                }
0666:                                // TODO Add on any more info not present
0667:                            }
0668:                        }
0669:                    }
0670:                }
0671:
0672:                if (pcSuperclassMetaData != null) {
0673:                    if (!pcSuperclassMetaData.isInitialised()) {
0674:                        pcSuperclassMetaData.initialise();
0675:                    }
0676:                    noOfInheritedManagedMembers = pcSuperclassMetaData
0677:                            .getNoOfInheritedManagedMembers()
0678:                            + pcSuperclassMetaData.getNoOfManagedMembers();
0679:                }
0680:
0681:                // Set up the various convenience arrays of field numbers
0682:                int total_field_count = noOfInheritedManagedMembers
0683:                        + managedMembers.length;
0684:                this .memberCount = total_field_count;
0685:                allMemberPositions = new int[total_field_count];
0686:                dfgMemberFlags = new boolean[total_field_count];
0687:                scoMutableMemberFlags = new boolean[total_field_count];
0688:                nonPkMemberFlags = new boolean[total_field_count];
0689:                int pk_field_count = 0;
0690:                int dfg_field_count = 0;
0691:                int scm_field_count = 0;
0692:                int pc_field_count = 0;
0693:                for (int i = 0; i < total_field_count; i++) {
0694:                    allMemberPositions[i] = i;
0695:
0696:                    AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePositionInternal(i);
0697:                    if (fmd.isPrimaryKey()) {
0698:                        pk_field_count++;
0699:                    } else {
0700:                        nonPkMemberFlags[i] = true;
0701:                    }
0702:                    if (fmd.isDefaultFetchGroup()) {
0703:                        dfgMemberFlags[i] = true;
0704:                        dfg_field_count++;
0705:                    }
0706:                    if (fmd.calcIsSecondClassMutable()) {
0707:                        scoMutableMemberFlags[i] = true;
0708:                        scm_field_count++;
0709:                    }
0710:                    if (fmd.isFieldTypePersistable()) {
0711:                        pc_field_count++;
0712:                    }
0713:                }
0714:
0715:                if (pk_field_count > 0
0716:                        && identityType != IdentityType.APPLICATION) {
0717:                    // primary key fields found, but not using application identity
0718:                    throw new InvalidMetaDataException(LOCALISER, "044078",
0719:                            fullName, new Integer(pk_field_count), identityType);
0720:                } else if (pk_field_count > 0) {
0721:                    pkMemberPositions = new int[pk_field_count];
0722:                    for (int i = 0, pk_num = 0; i < total_field_count; i++) {
0723:                        AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePositionInternal(i);
0724:                        if (fmd.isPrimaryKey()) {
0725:                            pkMemberPositions[pk_num++] = i;
0726:                        }
0727:                    }
0728:                } else if (pk_field_count == 0
0729:                        && identityType == IdentityType.APPLICATION) {
0730:                    // No primary key fields found
0731:                    throw new InvalidMetaDataException(LOCALISER, "044077",
0732:                            fullName, objectidClass);
0733:                }
0734:
0735:                nonPkMemberPositions = new int[total_field_count
0736:                        - pk_field_count];
0737:                persistenceCapableMemberPositions = new int[pc_field_count];
0738:                for (int i = 0, npkf = 0, npc = 0; i < total_field_count; i++) {
0739:                    AbstractMemberMetaData fmd = getMetaDataForManagedMemberAtAbsolutePositionInternal(i);
0740:                    if (!fmd.isPrimaryKey()) {
0741:                        nonPkMemberPositions[npkf++] = i;
0742:                    }
0743:                    if (fmd.isFieldTypePersistable()) {
0744:                        persistenceCapableMemberPositions[npc++] = i;
0745:                    }
0746:                }
0747:
0748:                dfgMemberPositions = new int[dfg_field_count];
0749:                scoMutableMemberPositions = new int[scm_field_count];
0750:                for (int i = 0, dfg_num = 0, scm_num = 0; i < total_field_count; i++) {
0751:                    if (dfgMemberFlags[i]) {
0752:                        dfgMemberPositions[dfg_num++] = i;
0753:                    }
0754:                    if (scoMutableMemberFlags[i]) {
0755:                        scoMutableMemberPositions[scm_num++] = i;
0756:                    }
0757:                }
0758:
0759:                // Initialise any sub-objects
0760:                implements MetaData = new ImplementsMetaData[implementations
0761:                        .size()];
0762:                for (int i = 0; i < implementations.size(); i++) {
0763:                    implements MetaData[i] = (ImplementsMetaData) implementations
0764:                            .get(i);
0765:                    implements MetaData[i].initialise();
0766:                }
0767:                joinMetaData = new JoinMetaData[joins.size()];
0768:                for (int i = 0; i < joinMetaData.length; i++) {
0769:                    joinMetaData[i] = (JoinMetaData) joins.get(i);
0770:                    joinMetaData[i].initialise();
0771:                }
0772:                indexMetaData = new IndexMetaData[indexes.size()];
0773:                for (int i = 0; i < indexMetaData.length; i++) {
0774:                    indexMetaData[i] = (IndexMetaData) indexes.get(i);
0775:                    indexMetaData[i].initialise();
0776:                }
0777:                foreignKeyMetaData = new ForeignKeyMetaData[foreignKeys.size()];
0778:                for (int i = 0; i < foreignKeyMetaData.length; i++) {
0779:                    foreignKeyMetaData[i] = (ForeignKeyMetaData) foreignKeys
0780:                            .get(i);
0781:                    foreignKeyMetaData[i].initialise();
0782:                }
0783:                uniqueMetaData = new UniqueMetaData[uniqueConstraints.size()];
0784:                for (int i = 0; i < uniqueMetaData.length; i++) {
0785:                    uniqueMetaData[i] = (UniqueMetaData) uniqueConstraints
0786:                            .get(i);
0787:                    uniqueMetaData[i].initialise();
0788:                }
0789:
0790:                fetchGroupMetaData = new FetchGroupMetaData[fetchGroups.size()];
0791:                fetchGroupMetaDataByName = new HashMap();
0792:                for (int i = 0; i < fetchGroupMetaData.length; i++) {
0793:                    fetchGroupMetaData[i] = (FetchGroupMetaData) fetchGroups
0794:                            .get(i);
0795:                    fetchGroupMetaData[i].initialise();
0796:                    fetchGroupMetaDataByName.put(fetchGroupMetaData[i]
0797:                            .getName(), fetchGroupMetaData[i]);
0798:                }
0799:
0800:                // If using datastore id and user hasn't provided the identity element,
0801:                // add a defaulted one (using the superclass if available)
0802:                if (identityType == IdentityType.DATASTORE
0803:                        && identityMetaData == null) {
0804:                    if (pcSuperclassMetaData != null) {
0805:                        IdentityMetaData super Imd = pcSuperclassMetaData
0806:                                .getIdentityMetaData();
0807:                        identityMetaData = new IdentityMetaData(this , super Imd
0808:                                .getColumnName(), super Imd.getValueStrategy()
0809:                                .toString(), super Imd.getSequence());
0810:                    } else {
0811:                        identityMetaData = new IdentityMetaData(this , null,
0812:                                null, null);
0813:                    }
0814:                }
0815:
0816:                if (primaryKeyMetaData != null) {
0817:                    primaryKeyMetaData.initialise();
0818:                }
0819:                if (versionMetaData != null) {
0820:                    versionMetaData.initialise();
0821:                }
0822:                if (identityMetaData != null) {
0823:                    identityMetaData.initialise();
0824:                }
0825:                if (inheritanceMetaData != null) {
0826:                    inheritanceMetaData.initialise();
0827:                }
0828:
0829:                if (identityType == IdentityType.APPLICATION) {
0830:                    usesSingleFieldIdentityClass = getMetaDataManager()
0831:                            .getApiAdapter().isSingleFieldIdentityClass(
0832:                                    getObjectidClass());
0833:                }
0834:
0835:                // Clear out the collections that we used when loading the MetaData
0836:                joins.clear();
0837:                joins = null;
0838:                fetchGroups.clear();
0839:                fetchGroups = null;
0840:                foreignKeys.clear();
0841:                foreignKeys = null;
0842:                indexes.clear();
0843:                indexes = null;
0844:                uniqueConstraints.clear();
0845:                uniqueConstraints = null;
0846:                implementations.clear();
0847:                implementations = null;
0848:                setInitialised();
0849:            }
0850:
0851:            /**
0852:             * Utility to add a defaulted FieldMetaData to the class. Provided as a
0853:             * method since then any derived classes can override it (e.g
0854:             * JDOConfigClass can create a JDOConfigField)
0855:             * @param name name of field
0856:             * @return the new FieldMetaData
0857:             */
0858:            protected AbstractMemberMetaData newDefaultedProperty(String name) {
0859:                return new FieldMetaData(this , name);
0860:            }
0861:
0862:            // ------------------------------ Accessors --------------------------------
0863:
0864:            /**
0865:             * Accessor for the implements MetaData
0866:             * @return Returns the implements MetaData.
0867:             */
0868:            public final ImplementsMetaData[] getImplementsMetaData() {
0869:                return implements MetaData;
0870:            }
0871:
0872:            /**
0873:             * Convenience accessor for whether this class implements a specified interface
0874:             * @param interfaceName The name of the interface
0875:             * @return Whether it implements the interface
0876:             */
0877:            public boolean implements Interface(String interfaceName) {
0878:                if (implements MetaData != null) {
0879:                    for (int i = 0; i < implements MetaData.length; i++) {
0880:                        if (implements MetaData[i].getName().equals(
0881:                                interfaceName)) {
0882:                            return true;
0883:                        }
0884:                    }
0885:                }
0886:                return false;
0887:            }
0888:
0889:            /**
0890:             * Whether the PersistenceCapable class is abstract
0891:             * @return true if the PersistenceCapable class is abstract
0892:             */
0893:            public boolean isAbstractPersistenceCapable() {
0894:                return isAbstractPersistenceCapable;
0895:            }
0896:
0897:            // ------------------------------- Mutators --------------------------------
0898:
0899:            /**
0900:             * Method to add an implements to this class.
0901:             * @param implmd Meta-Data for the implements
0902:             */
0903:            public void addImplements(ImplementsMetaData implmd) {
0904:                if (implmd == null) {
0905:                    return;
0906:                }
0907:
0908:                if (isInitialised()) {
0909:                    throw new RuntimeException("Already initialised");
0910:                }
0911:                implementations.add(implmd);
0912:            }
0913:
0914:            // ------------------------------ Utilities --------------------------------
0915:
0916:            /**
0917:             * Returns a string representation of the object.
0918:             * This can be used as part of a facility to output a MetaData file. 
0919:             * @param prefix prefix string
0920:             * @param indent indent string
0921:             * @return a string representation of the object.
0922:             */
0923:            public String toString(String prefix, String indent) {
0924:                StringBuffer sb = new StringBuffer();
0925:                sb.append(prefix).append("<class name=\"" + name + "\"\n");
0926:                if (identityType != null) {
0927:                    sb.append(prefix).append(
0928:                            "       identity-type=\"" + identityType + "\"\n");
0929:                }
0930:                if (objectidClass != null) {
0931:                    sb.append(prefix)
0932:                            .append(
0933:                                    "       objectid-class=\"" + objectidClass
0934:                                            + "\"\n");
0935:                }
0936:                if (!requiresExtent) {
0937:                    sb.append(prefix)
0938:                            .append(
0939:                                    "       requires-extent=\""
0940:                                            + requiresExtent + "\"");
0941:                }
0942:                if (embeddedOnly) {
0943:                    sb.append(prefix).append(
0944:                            "       embedded-only=\"" + embeddedOnly + "\"\n");
0945:                }
0946:                if (persistenceModifier != null) {
0947:                    sb.append(prefix).append(
0948:                            "       persistence-modifier=\""
0949:                                    + persistenceModifier + "\"\n");
0950:                }
0951:                if (catalog != null) {
0952:                    sb.append(prefix).append(
0953:                            "       catalog=\"" + catalog + "\"\n");
0954:                }
0955:                if (schema != null) {
0956:                    sb.append(prefix).append(
0957:                            "       schema=\"" + schema + "\"\n");
0958:                }
0959:                if (table != null) {
0960:                    sb.append(prefix)
0961:                            .append("       table=\"" + table + "\"\n");
0962:                }
0963:                if (detachable) {
0964:                    sb.append(prefix).append(
0965:                            "       detachable=\"" + detachable + "\">\n");
0966:                }
0967:
0968:                // Implements
0969:                if (implements MetaData != null) {
0970:                    for (int i = 0; i < implements MetaData.length; i++) {
0971:                        sb.append(implements MetaData[i].toString(prefix
0972:                                + indent, indent));
0973:                    }
0974:                }
0975:
0976:                // Identity
0977:                if (identityMetaData != null) {
0978:                    sb.append(identityMetaData
0979:                            .toString(prefix + indent, indent));
0980:                }
0981:
0982:                // PrimaryKey
0983:                if (primaryKeyMetaData != null) {
0984:                    sb.append(primaryKeyMetaData.toString(prefix + indent,
0985:                            indent));
0986:                }
0987:
0988:                // Inheritance
0989:                if (inheritanceMetaData != null) {
0990:                    sb.append(inheritanceMetaData.toString(prefix + indent,
0991:                            indent));
0992:                }
0993:
0994:                // Add Version
0995:                if (versionMetaData != null) {
0996:                    sb
0997:                            .append(versionMetaData.toString(prefix + indent,
0998:                                    indent));
0999:                }
1000:
1001:                // Add joins
1002:                if (joinMetaData != null) {
1003:                    for (int i = 0; i < joinMetaData.length; i++) {
1004:                        sb.append(joinMetaData[i].toString(prefix + indent,
1005:                                indent));
1006:                    }
1007:                }
1008:
1009:                // Add foreign-keys
1010:                if (foreignKeyMetaData != null) {
1011:                    for (int i = 0; i < foreignKeyMetaData.length; i++) {
1012:                        sb.append(foreignKeyMetaData[i].toString(prefix
1013:                                + indent, indent));
1014:                    }
1015:                }
1016:
1017:                // Add indexes
1018:                if (indexMetaData != null) {
1019:                    for (int i = 0; i < indexMetaData.length; i++) {
1020:                        sb.append(indexMetaData[i].toString(prefix + indent,
1021:                                indent));
1022:                    }
1023:                }
1024:
1025:                // Add unique constraints
1026:                if (uniqueMetaData != null) {
1027:                    for (int i = 0; i < uniqueMetaData.length; i++) {
1028:                        sb.append(uniqueMetaData[i].toString(prefix + indent,
1029:                                indent));
1030:                    }
1031:                }
1032:
1033:                // Add fields
1034:                if (managedMembers != null) {
1035:                    for (int i = 0; i < managedMembers.length; i++) {
1036:                        sb.append(managedMembers[i].toString(prefix + indent,
1037:                                indent));
1038:                    }
1039:                }
1040:
1041:                // Add unmapped columns
1042:                if (unmappedColumns != null) {
1043:                    for (int i = 0; i < unmappedColumns.size(); i++) {
1044:                        ColumnMetaData col = (ColumnMetaData) unmappedColumns
1045:                                .get(i);
1046:                        sb.append(col.toString(prefix + indent, indent));
1047:                    }
1048:                }
1049:
1050:                // Add queries
1051:                if (queries != null) {
1052:                    Iterator iter = queries.iterator();
1053:                    while (iter.hasNext()) {
1054:                        QueryMetaData q = (QueryMetaData) iter.next();
1055:                        sb.append(q.toString(prefix + indent, indent));
1056:                    }
1057:                }
1058:
1059:                // Add fetch-groups
1060:                if (fetchGroupMetaData != null) {
1061:                    for (int i = 0; i < fetchGroupMetaData.length; i++) {
1062:                        sb.append(fetchGroupMetaData[i].toString(prefix
1063:                                + indent, indent));
1064:                    }
1065:                }
1066:
1067:                // Add extensions
1068:                sb.append(super .toString(prefix + indent, indent));
1069:
1070:                sb.append(prefix + "</class>\n");
1071:                return sb.toString();
1072:            }
1073:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.