Source Code Cross Referenced for AbstractMemberMetaData.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:        2007 Xuan Baldauf - Implement solution for issue CORE-3272
0017:        2007 Xuan Baldauf - allow users to explictly state that an array whose component type is not PC may still have PC elements. See CORE-3274
0018:            ...
0019:         **********************************************************************/package org.jpox.metadata;
0020:
0021:        import java.io.Serializable;
0022:        import java.lang.reflect.Field;
0023:        import java.lang.reflect.Method;
0024:        import java.lang.reflect.Modifier;
0025:        import java.util.ArrayList;
0026:        import java.util.HashSet;
0027:        import java.util.List;
0028:        import java.util.Set;
0029:
0030:        import org.jpox.ClassLoaderResolver;
0031:        import org.jpox.ClassNameConstants;
0032:        import org.jpox.api.ApiAdapter;
0033:        import org.jpox.exceptions.ClassNotResolvedException;
0034:        import org.jpox.exceptions.JPOXUserException;
0035:        import org.jpox.sco.SCOUtils;
0036:        import org.jpox.store.DatastoreField;
0037:        import org.jpox.util.ClassUtils;
0038:        import org.jpox.util.JPOXLogger;
0039:        import org.jpox.util.JavaUtils;
0040:        import org.jpox.util.StringUtils;
0041:
0042:        /**
0043:         * Abstract representation of MetaData for a field/property of a class/interface.
0044:         * The term "member" is used to represent either a field or a method(property). The term
0045:         * property is used to represent the name after cutting off any Java-beans style "get" prefix.
0046:         * This class is extended for fields (FieldMetaData) and properties (PropertyMetaData) to provide
0047:         * the explicit support for those components.
0048:         * 
0049:         * @version $Revision: 1.20 $
0050:         */
0051:        public abstract class AbstractMemberMetaData extends MetaData implements 
0052:                Comparable, ColumnMetaDataContainer {
0053:            /** Contains the metadata for column(s). */
0054:            protected ColumnMetaData[] columnMetaData;
0055:
0056:            /** Meta-Data of any container. */
0057:            protected ContainerMetaData container;
0058:
0059:            /** EmbeddedMetaData. */
0060:            protected EmbeddedMetaData embeddedMetaData;
0061:
0062:            /** JoinMetaData. */
0063:            protected JoinMetaData joinMetaData;
0064:
0065:            /** ElementMetaData. */
0066:            protected ElementMetaData elementMetaData;
0067:
0068:            /** KeyMetaData. */
0069:            protected KeyMetaData keyMetaData;
0070:
0071:            /** ValueMetaData. */
0072:            protected ValueMetaData valueMetaData;
0073:
0074:            /** IndexMetaData. */
0075:            protected IndexMetaData indexMetaData;
0076:
0077:            /** The indexing value */
0078:            protected IndexedValue indexed = null;
0079:
0080:            /** UniqueMetaData. */
0081:            protected UniqueMetaData uniqueMetaData;
0082:
0083:            /** Whether to add a unique constraint. */
0084:            protected final boolean uniqueConstraint;
0085:
0086:            /** OrderMetaData. */
0087:            protected OrderMetaData orderMetaData;
0088:
0089:            /** ForeignKeyMetaData. */
0090:            protected ForeignKeyMetaData foreignKeyMetaData;
0091:
0092:            /** default-fetch-group tag value. */
0093:            protected Boolean defaultFetchGroup;
0094:
0095:            /** column tag value.  */
0096:            protected String column;
0097:
0098:            /** mapped-by tag value. */
0099:            protected String mappedBy;
0100:
0101:            /** embedded tag value. */
0102:            protected Boolean embedded;
0103:
0104:            /** Whether this field contains a reference that should be deleted when deleting this field.  */
0105:            protected Boolean dependent;
0106:
0107:            /** serialized tag value. */
0108:            protected Boolean serialized;
0109:
0110:            /** Whether to persist this relation when persisting the owning object. */
0111:            protected boolean cascadePersist;
0112:
0113:            /** Whether to update this relation when updating the owning object. */
0114:            protected boolean cascadeUpdate;
0115:
0116:            /** Whether to delete this relation when deleting the owning object (JPA). TODO Link this to dependent */
0117:            protected boolean cascadeDelete;
0118:
0119:            /** Whether to refresh this relation when refreshing the owning object (JPA). */
0120:            protected boolean cascadeRefresh;
0121:
0122:            /** load-fetch-group value. */
0123:            protected String loadFetchGroup;
0124:
0125:            /** Default recursion-depth according to proposed final draft spec, [12.7.2]. */
0126:            public static final int DEFAULT_RECURSION_DEPTH = 1;
0127:
0128:            /** Indicates the recursion-depth is not defined.  Use default value. */
0129:            public static final int UNDEFINED_RECURSION_DEPTH = 0;
0130:
0131:            /** recursion-depth value. */
0132:            protected int recursionDepth = UNDEFINED_RECURSION_DEPTH;
0133:
0134:            /** Field name. */
0135:            protected final String name;
0136:
0137:            /** null-value tag value (default is NONE). */
0138:            protected NullValue nullValue = NullValue.NONE;
0139:
0140:            /** persistence-modifier tag value. */
0141:            protected FieldPersistenceModifier persistenceModifier = FieldPersistenceModifier.DEFAULT;
0142:
0143:            /** primary key tag value. */
0144:            protected Boolean primaryKey;
0145:
0146:            /** Table name for this field. */
0147:            protected String table;
0148:
0149:            /** Catalog for the table specified for this field. */
0150:            protected String catalog;
0151:
0152:            /** Schema for the table specified for this field. */
0153:            protected String schema;
0154:
0155:            /**
0156:             * The value-strategy attribute specifies the strategy used to generate
0157:             * values for the field. This attribute has the same values and meaning as
0158:             * the strategy attribute in datastoreidentity.
0159:             */
0160:            protected IdentityStrategy valueStrategy;
0161:
0162:            /** Name of a value generator if the user wants to override the default JPOX generator. */
0163:            protected String valueGeneratorName;
0164:
0165:            /**
0166:             * If the value-strategy is sequence, the sequence attribute specifies the
0167:             * name of the sequence to use to automatically generate a value for the field.
0168:             */
0169:            protected String sequence;
0170:
0171:            /**
0172:             * Name of the class to which this field really belongs. Will be null if the field belongs
0173:             * to the parent ClassMetaData, and will have a value if it is an overriding field.
0174:             */
0175:            protected String className = null;
0176:
0177:            /**
0178:             * Specification of the possible type(s) that can be stored in this field. This is for the case where the
0179:             * field/property is declared as an interface, or Object and hence can contain derived types. This 
0180:             * provides the restriction to a particular type.
0181:             */
0182:            protected String[] fieldTypes;
0183:
0184:            /** Field type being represented by this MetaData. */
0185:            protected Class type;
0186:
0187:            /** Field modifiers */
0188:            protected int modifiers;
0189:
0190:            /**
0191:             * Id of the field in its class (only for fields managed by JDO).
0192:             * If the value is -1, the field is NOT managed by JDO or the object hasn't
0193:             * been populated.
0194:             */
0195:            protected int fieldId = -1;
0196:
0197:            /** The relation type of this field (1-1, 1-N, M-N, N-1). */
0198:            protected int relationType = -1;
0199:
0200:            /**
0201:             * MetaData for the other end of a relation when this member is a bidirectional relation. 
0202:             * This may be multiple fields if the FK is shared.
0203:             */
0204:            protected AbstractMemberMetaData[] relatedMemberMetaData = null;
0205:
0206:            /** Temporary flag to signify if the field is ordered. */
0207:            protected boolean ordered = false;
0208:
0209:            // -------------------------------------------------------------------------
0210:            // These fields are only used when the MetaData is read by the parser and
0211:            // elements are dynamically added to the other elements. At runtime, "columnMetaData"
0212:            // should be used.
0213:
0214:            /**
0215:             * Columns ColumnMetaData
0216:             */
0217:            protected List columns = new ArrayList();
0218:
0219:            /** Name of the target entity (when used with JPA MetaData on OneToOne, OneToMany etc) */
0220:            protected String targetClassName = null;
0221:
0222:            /** Wrapper for the ugly JPA "lob" so that when being populated we should make this serialised in some way. */
0223:            protected boolean storeInLob = false;
0224:
0225:            /** JDO Flags for use in enhancement process - see JDO spec 21.14. */
0226:            protected byte jdoFieldFlag;
0227:
0228:            /**
0229:             * Convenience constructor taking defaults
0230:             * @param parent Parent component
0231:             * @param name Name of the field
0232:             */
0233:            public AbstractMemberMetaData(MetaData parent, final String name) {
0234:                this (parent, name, null, null, null, null, null, null, null,
0235:                        null, null, null, null, null, null, null, null, null,
0236:                        null, null, null, null);
0237:            }
0238:
0239:            /**
0240:             * Convenience constructor to copy the specification from the passed field.
0241:             * This is used when we have an overriding field and we make a copy of the baseline
0242:             * field as a starting point.
0243:             * @param parent The parent
0244:             * @param fmd The field to copy
0245:             */
0246:            public AbstractMemberMetaData(MetaData parent,
0247:                    AbstractMemberMetaData fmd) {
0248:                super (parent);
0249:
0250:                // Copy the simple field values
0251:                this .name = fmd.name;
0252:                this .primaryKey = fmd.primaryKey;
0253:                this .defaultFetchGroup = fmd.defaultFetchGroup;
0254:                this .column = fmd.column;
0255:                this .mappedBy = fmd.mappedBy;
0256:                this .dependent = fmd.dependent;
0257:                this .embedded = fmd.embedded;
0258:                this .serialized = fmd.serialized;
0259:                this .cascadePersist = fmd.cascadePersist;
0260:                this .cascadeUpdate = fmd.cascadeUpdate;
0261:                this .cascadeDelete = fmd.cascadeDelete;
0262:                this .cascadeRefresh = fmd.cascadeRefresh;
0263:                this .nullValue = fmd.nullValue;
0264:                this .persistenceModifier = fmd.persistenceModifier;
0265:                this .table = fmd.table;
0266:                this .indexed = fmd.indexed;
0267:                this .valueStrategy = fmd.valueStrategy;
0268:                this .valueGeneratorName = fmd.valueGeneratorName;
0269:                this .sequence = fmd.sequence;
0270:                this .uniqueConstraint = fmd.uniqueConstraint;
0271:                this .loadFetchGroup = fmd.loadFetchGroup;
0272:                if (fmd.fieldTypes != null) {
0273:                    this .fieldTypes = new String[fmd.fieldTypes.length];
0274:                    for (int i = 0; i < fmd.fieldTypes.length; i++) {
0275:                        this .fieldTypes[i] = fmd.fieldTypes[i];
0276:                    }
0277:                }
0278:
0279:                // Create copies of the object fields
0280:                if (fmd.joinMetaData != null) {
0281:                    this .joinMetaData = new JoinMetaData(this , fmd.joinMetaData);
0282:                }
0283:                if (fmd.elementMetaData != null) {
0284:                    this .elementMetaData = new ElementMetaData(this ,
0285:                            fmd.elementMetaData);
0286:                }
0287:                if (fmd.keyMetaData != null) {
0288:                    this .keyMetaData = new KeyMetaData(this , fmd.keyMetaData);
0289:                }
0290:                if (fmd.valueMetaData != null) {
0291:                    this .valueMetaData = new ValueMetaData(this ,
0292:                            fmd.valueMetaData);
0293:                }
0294:                if (fmd.orderMetaData != null) {
0295:                    this .orderMetaData = new OrderMetaData(this ,
0296:                            fmd.orderMetaData);
0297:                }
0298:                if (fmd.indexMetaData != null) {
0299:                    this .indexMetaData = new IndexMetaData(fmd.indexMetaData);
0300:                }
0301:                if (fmd.uniqueMetaData != null) {
0302:                    this .uniqueMetaData = new UniqueMetaData(fmd.uniqueMetaData);
0303:                }
0304:                if (fmd.foreignKeyMetaData != null) {
0305:                    this .foreignKeyMetaData = new ForeignKeyMetaData(
0306:                            fmd.foreignKeyMetaData);
0307:                }
0308:                if (fmd.embeddedMetaData != null) {
0309:                    this .embeddedMetaData = new EmbeddedMetaData(this ,
0310:                            fmd.embeddedMetaData);
0311:                }
0312:                if (fmd.container != null) {
0313:                    if (fmd.container instanceof  CollectionMetaData) {
0314:                        container = new CollectionMetaData(this ,
0315:                                (CollectionMetaData) fmd.container);
0316:                    } else if (fmd.container instanceof  MapMetaData) {
0317:                        container = new MapMetaData(this ,
0318:                                (MapMetaData) fmd.container);
0319:                    } else if (fmd.container instanceof  ArrayMetaData) {
0320:                        container = new ArrayMetaData(this ,
0321:                                (ArrayMetaData) fmd.container);
0322:                    }
0323:                }
0324:                for (int i = 0; i < fmd.columns.size(); i++) {
0325:                    addColumn(new ColumnMetaData(this ,
0326:                            (ColumnMetaData) fmd.columns.get(i)));
0327:                }
0328:            }
0329:
0330:            /**
0331:             * Constructor. Saves the MetaData with the specified values. The object is
0332:             * then in an "unpopulated" state. It can become "populated" by calling the
0333:             * <B>populate()</B> method which compares it against the field it is to
0334:             * represent and updates any unset attributes and flags up any errors.
0335:             * @param parent parent MetaData instance
0336:             * @param name field name 
0337:             * @param pk attribute primary-key value
0338:             * @param modifier attribute persistence-modifier value
0339:             * @param defaultFetchGroup attribute default-fetch-group value
0340:             * @param nullValue attribute null-value value 
0341:             * @param embedded attribute embedded value
0342:             * @param serialized attribute serialized value
0343:             * @param dependent attribute dependent value
0344:             * @param mappedBy attribute mapped-by value
0345:             * @param column attribute column value
0346:             * @param table attribute table value
0347:             * @param catalog attribute catalog value
0348:             * @param schema attribute schema value
0349:             * @param deleteAction attribute delete-action value
0350:             * @param indexed Whether this is indexed
0351:             * @param unique Apply a unique constraint
0352:             * @param recursionDepth The depth of fetch to use when recursing
0353:             * @param loadFetchGroup Name of the additional fetch group to use when loading
0354:             * @param valueStrategy attribute value-strategy value
0355:             * @param sequence attribute sequence value
0356:             * @param fieldType Implementation type(s) for field.
0357:             */
0358:            public AbstractMemberMetaData(MetaData parent, final String name,
0359:                    final String pk, final String modifier,
0360:                    final String defaultFetchGroup, final String nullValue,
0361:                    final String embedded, final String serialized,
0362:                    final String dependent, final String mappedBy,
0363:                    final String column, final String table,
0364:                    final String catalog, final String schema,
0365:                    final String deleteAction, final String indexed,
0366:                    final String unique, final String recursionDepth,
0367:                    final String loadFetchGroup, final String valueStrategy,
0368:                    final String sequence, final String fieldType) {
0369:                super (parent);
0370:
0371:                if (name == null) {
0372:                    throw new JPOXUserException(LOCALISER.msg("044041", "name",
0373:                            getClassName(true), "field"));
0374:                }
0375:                if (name.indexOf('.') >= 0) {
0376:                    // TODO Check if this is a valid className
0377:                    this .className = name.substring(0, name.lastIndexOf('.'));
0378:                    this .name = name.substring(name.lastIndexOf('.') + 1);
0379:                } else {
0380:                    this .name = name;
0381:                }
0382:
0383:                // "primary-key"
0384:                if (!StringUtils.isWhitespace(pk)) {
0385:                    if (pk.equalsIgnoreCase("true")) {
0386:                        this .primaryKey = Boolean.TRUE;
0387:                        this .defaultFetchGroup = Boolean.TRUE;
0388:                    } else {
0389:                        this .primaryKey = Boolean.FALSE;
0390:                    }
0391:                }
0392:
0393:                this .column = (StringUtils.isWhitespace(column) ? null : column);
0394:                this .mappedBy = (StringUtils.isWhitespace(mappedBy) ? null
0395:                        : mappedBy);
0396:
0397:                // "dependent"
0398:                if (dependent != null) {
0399:                    if (dependent.equalsIgnoreCase("true")) {
0400:                        this .dependent = Boolean.TRUE;
0401:                    } else if (dependent.equalsIgnoreCase("false")) {
0402:                        this .dependent = Boolean.FALSE;
0403:                    }
0404:                }
0405:
0406:                // "embedded"
0407:                if (embedded != null) {
0408:                    if (embedded.equalsIgnoreCase("true")) {
0409:                        this .embedded = Boolean.TRUE;
0410:                    } else if (embedded.equalsIgnoreCase("false")) {
0411:                        this .embedded = Boolean.FALSE;
0412:                    }
0413:                }
0414:
0415:                // "serialized"
0416:                if (serialized != null) {
0417:                    if (serialized.equalsIgnoreCase("true")) {
0418:                        this .serialized = Boolean.TRUE;
0419:                    } else if (serialized.equalsIgnoreCase("false")) {
0420:                        this .serialized = Boolean.FALSE;
0421:                    }
0422:                }
0423:
0424:                // "null-value"
0425:                this .nullValue = NullValue.getNullValue(nullValue);
0426:
0427:                // "persistence-modifier"
0428:                if (!StringUtils.isWhitespace(modifier)) {
0429:                    persistenceModifier = FieldPersistenceModifier
0430:                            .getFieldPersistenceModifier(modifier);
0431:                }
0432:                if (persistenceModifier == null) {
0433:                    JPOXLogger.METADATA.error(LOCALISER.msg("044117", name,
0434:                            getClassName(false), modifier,
0435:                            "persistence-modifier"));
0436:                    throw new InvalidMetaDataException(LOCALISER, "044117",
0437:                            name, getClassName(false), modifier,
0438:                            "persistence-modifier");
0439:                }
0440:
0441:                // "default-fetch-group"
0442:                if (defaultFetchGroup != null) {
0443:                    if (defaultFetchGroup.equalsIgnoreCase("true")) {
0444:                        this .defaultFetchGroup = Boolean.TRUE;
0445:                    } else if (defaultFetchGroup.equalsIgnoreCase("false")) {
0446:                        this .defaultFetchGroup = Boolean.FALSE;
0447:                    }
0448:                }
0449:
0450:                // "table"
0451:                this .table = (StringUtils.isWhitespace(table) ? null : table);
0452:                this .catalog = (StringUtils.isWhitespace(catalog) ? null
0453:                        : catalog);
0454:                this .schema = (StringUtils.isWhitespace(schema) ? null : schema);
0455:
0456:                if (deleteAction != null) {
0457:                    foreignKeyMetaData = new ForeignKeyMetaData(null, null,
0458:                            null, null, deleteAction, null);
0459:                }
0460:
0461:                this .indexed = IndexedValue.getIndexedValue(indexed);
0462:
0463:                if (unique != null && unique.equalsIgnoreCase("true")) {
0464:                    uniqueConstraint = true;
0465:                } else {
0466:                    uniqueConstraint = false;
0467:                }
0468:
0469:                // Fetch Group
0470:                this .loadFetchGroup = (StringUtils.isWhitespace(loadFetchGroup) ? null
0471:                        : loadFetchGroup);
0472:                if (recursionDepth != null) {
0473:                    try {
0474:                        this .recursionDepth = (new Integer(recursionDepth))
0475:                                .intValue();
0476:                    } catch (Exception e) {
0477:                        // Not parseable so set as "undefined"
0478:                        this .recursionDepth = UNDEFINED_RECURSION_DEPTH;
0479:                    }
0480:                }
0481:
0482:                this .valueStrategy = valueStrategy == null ? null
0483:                        : IdentityStrategy.getIdentityStrategy(valueStrategy);
0484:                this .sequence = (StringUtils.isWhitespace(sequence) ? null
0485:                        : sequence);
0486:                if (!StringUtils.isWhitespace(fieldType)) {
0487:                    // Split the passed value assuming that it is comma-separated
0488:                    this .fieldTypes = MetaDataUtils.getInstance()
0489:                            .getValuesForCommaSeparatedAttribute(fieldType);
0490:                }
0491:
0492:                if (getMetaDataManager() != null) {
0493:                    // Set defaults for cascading
0494:                    // If we have no MetaDataManager here then we are likely a field for an Index/Unique etc so dont need this
0495:                    ApiAdapter apiAdapter = getMetaDataManager()
0496:                            .getOMFContext().getApiAdapter();
0497:                    this .cascadePersist = apiAdapter
0498:                            .getDefaultCascadePersistForField();
0499:                    this .cascadeUpdate = apiAdapter
0500:                            .getDefaultCascadeUpdateForField();
0501:                    this .cascadeDelete = apiAdapter
0502:                            .getDefaultCascadeDeleteForField();
0503:                    this .cascadeRefresh = apiAdapter
0504:                            .getDefaultCascadeRefreshForField();
0505:                }
0506:            }
0507:
0508:            /**
0509:             * Method to provide the details of the field being represented by this MetaData hence populating
0510:             * certain parts of the MetaData. This is used to firstly provide defaults for attributes that aren't 
0511:             * specified in the MetaData, and secondly to report any errors with attributes that have been specifed 
0512:             * that are inconsistent with the field being represented. 
0513:             * Either a field or a method should be passed in (one or the other) depending on what is being represented
0514:             * by this "member".
0515:             * @param clr ClassLoaderResolver to use for any class loading 
0516:             * @param field Field that we are representing (if it's a field)
0517:             * @param method Method(property) that we are representing (if it's a method).
0518:             * @param primary the primary ClassLoader to use (or null)
0519:             */
0520:            public synchronized void populate(ClassLoaderResolver clr,
0521:                    Field field, Method method, ClassLoader primary) {
0522:                if (isPopulated() || isInitialised()) {
0523:                    return;
0524:                    /*JPOXLogger.METADATA.error(LOCALISER.msg("044107",name,getClassName(false)));
0525:                    throw new InvalidMetaDataException(LOCALISER,
0526:                        "044107",
0527:                        name,getClassName(false));*/
0528:                }
0529:
0530:                if (field == null && method == null) {
0531:                    JPOXLogger.METADATA.error(LOCALISER.msg("044106", name,
0532:                            getClassName(false)));
0533:                    throw new InvalidMetaDataException(LOCALISER,
0534:                            "MetaData.Field.PopulateWithNullError", name,
0535:                            getClassName(false));
0536:                }
0537:
0538:                // No class loader, so use System
0539:                if (clr == null) {
0540:                    JPOXLogger.METADATA.warn(LOCALISER.msg("044067", name,
0541:                            getClassName(true)));
0542:                    clr = getAbstractClassMetaData().getMetaDataManager()
0543:                            .getOMFContext().getClassLoaderResolver(null);
0544:                }
0545:
0546:                if (field != null) {
0547:                    this .type = field.getType();
0548:                    this .modifiers = field.getModifiers();
0549:                } else if (method != null) {
0550:                    this .type = method.getReturnType();
0551:                    this .modifiers = method.getModifiers();
0552:                }
0553:
0554:                if (className != null) {
0555:                    // If the field is overriding a superclass field, check that it is valid
0556:                    Class this Class = null;
0557:                    try {
0558:                        this Class = clr.classForName(getAbstractClassMetaData()
0559:                                .getPackageName()
0560:                                + "." + getAbstractClassMetaData().getName());
0561:                    } catch (ClassNotResolvedException cnre) {
0562:                        // Do nothing
0563:                    }
0564:
0565:                    Class fieldClass = null;
0566:                    try {
0567:                        fieldClass = clr.classForName(className);
0568:                    } catch (ClassNotResolvedException cnre) {
0569:                        try {
0570:                            fieldClass = clr
0571:                                    .classForName(getAbstractClassMetaData()
0572:                                            .getPackageName()
0573:                                            + "." + className);
0574:                            className = getAbstractClassMetaData()
0575:                                    .getPackageName()
0576:                                    + "." + className;
0577:                        } catch (ClassNotResolvedException cnre2) {
0578:                            JPOXLogger.METADATA.error(LOCALISER.msg("044113",
0579:                                    getAbstractClassMetaData().getName(), name,
0580:                                    className));
0581:                            throw new InvalidMetaDataException(LOCALISER,
0582:                                    "044113", getAbstractClassMetaData()
0583:                                            .getName(), name, className);
0584:                        }
0585:                    }
0586:                    if (fieldClass != null
0587:                            && !fieldClass.isAssignableFrom(this Class)) {
0588:                        // TODO We could also check if PersistenceCapable, but won't work when enhancing
0589:                        JPOXLogger.METADATA.error(LOCALISER.msg("044114",
0590:                                getAbstractClassMetaData().getName(), name,
0591:                                className));
0592:                        throw new InvalidMetaDataException(LOCALISER, "044114",
0593:                                getAbstractClassMetaData().getName(), name,
0594:                                className);
0595:                    }
0596:                }
0597:
0598:                if (primaryKey == null) {
0599:                    // Primary key not set by user so initialise it to false
0600:                    primaryKey = Boolean.FALSE;
0601:                }
0602:
0603:                // Update "embedded" based on type
0604:                if (primaryKey == Boolean.FALSE && embedded == null) {
0605:                    Class element_type = getType();
0606:                    if (element_type.isArray()) {
0607:                        element_type = element_type.getComponentType();
0608:                        if (getMetaDataManager().getOMFContext()
0609:                                .getTypeManager().isDefaultEmbeddedType(
0610:                                        element_type)) {
0611:                            embedded = Boolean.TRUE;
0612:                        }
0613:                    } else if (getMetaDataManager().getOMFContext()
0614:                            .getTypeManager().isDefaultEmbeddedType(
0615:                                    element_type)) {
0616:                        embedded = Boolean.TRUE;
0617:                    }
0618:                }
0619:                if (embedded == null) {
0620:                    embedded = Boolean.FALSE;
0621:                }
0622:
0623:                // Update "persistence-modifier" according to type etc
0624:                if (FieldPersistenceModifier.DEFAULT
0625:                        .equals(persistenceModifier)) {
0626:                    boolean isPcClass = getType().isArray() ? isFieldArrayTypePersistable()
0627:                            : isFieldTypePersistable();
0628:                    if (!isPcClass) {
0629:                        if (getType().isArray()
0630:                                && getType().getComponentType().isInterface()) {
0631:                            isPcClass = (getAbstractClassMetaData()
0632:                                    .getMetaDataManager()
0633:                                    .getMetaDataForClassInternal(
0634:                                            getType().getComponentType(), clr) != null);
0635:                        } else if (getType().isInterface()) {
0636:                            isPcClass = (getAbstractClassMetaData()
0637:                                    .getMetaDataManager()
0638:                                    .getMetaDataForClassInternal(getType(), clr) != null);
0639:                        }
0640:                    }
0641:
0642:                    persistenceModifier = getMetaDataManager().getOMFContext()
0643:                            .getTypeManager()
0644:                            .getDefaultFieldPersistenceModifier(getType(),
0645:                                    modifiers, isPcClass);
0646:                }
0647:
0648:                // TODO If this field is NONE in superclass, make it NONE here too
0649:
0650:                // Check for array types supported by JPOX
0651:                if (!persistenceModifier.equals(FieldPersistenceModifier.NONE)
0652:                        && getType().isArray()
0653:                        && !getAbstractClassMetaData().getMetaDataManager()
0654:                                .isEnhancing()) {
0655:                    // JPOX supports simple arrays, arrays of PCs, and arrays of reference types, and anything serialised
0656:                    ApiAdapter api = getMetaDataManager().getOMFContext()
0657:                            .getApiAdapter();
0658:                    if (!getMetaDataManager().getOMFContext().getTypeManager()
0659:                            .isSupportedType(getType().getName())
0660:                            && !api.isPersistable(getType().getComponentType())
0661:                            && !getType().getComponentType().isInterface()
0662:                            && !getType().getComponentType().getName().equals(
0663:                                    "java.lang.Object")
0664:                            && serialized != Boolean.TRUE) {
0665:                        JPOXLogger.METADATA.warn(LOCALISER.msg("044111", name,
0666:                                getClassName(false)));
0667:                        throw new InvalidMetaDataException(LOCALISER, "044111",
0668:                                name, getClassName(false));
0669:                    }
0670:                }
0671:
0672:                // Update "default-fetch-group" according to type
0673:                if (defaultFetchGroup == null
0674:                        && persistenceModifier
0675:                                .equals(FieldPersistenceModifier.NONE)) {
0676:                    defaultFetchGroup = Boolean.FALSE;
0677:                } else if (defaultFetchGroup == null
0678:                        && persistenceModifier
0679:                                .equals(FieldPersistenceModifier.TRANSACTIONAL)) {
0680:                    defaultFetchGroup = Boolean.FALSE;
0681:                } else if (defaultFetchGroup == null) {
0682:                    defaultFetchGroup = Boolean.FALSE;
0683:                    if (!primaryKey.equals(Boolean.TRUE)
0684:                            && getMetaDataManager().getOMFContext()
0685:                                    .getTypeManager().isDefaultFetchGroup(
0686:                                            getType())) {
0687:                        defaultFetchGroup = Boolean.TRUE;
0688:                    }
0689:                }
0690:
0691:                // Field is not specified as "persistent" yet has DFG or primary-key !
0692:                if (persistenceModifier
0693:                        .equals(FieldPersistenceModifier.TRANSACTIONAL)
0694:                        || persistenceModifier
0695:                                .equals(FieldPersistenceModifier.NONE)) {
0696:                    if (defaultFetchGroup == Boolean.TRUE
0697:                            || primaryKey == Boolean.TRUE) {
0698:                        throw new InvalidMetaDataException(LOCALISER, "044109",
0699:                                name, getClassName(true), this .getType()
0700:                                        .getName(), persistenceModifier
0701:                                        .toString());
0702:                    }
0703:                }
0704:
0705:                if (storeInLob) {
0706:                    // Set up the serialized flag according to the field type in line with JPA1
0707:                    boolean useClob = false;
0708:                    if (type == String.class
0709:                            || (type.isArray() && type.getComponentType() == Character.class)
0710:                            || (type.isArray() && type.getComponentType() == char.class)) {
0711:                        useClob = true;
0712:                        if (columns == null || columns.size() == 0) {
0713:                            // Create a CLOB column. What if the RDBMS doesnt support CLOB ?
0714:                            addColumn(new ColumnMetaData(this , column, null,
0715:                                    null, "CLOB", null, null, null, null, null,
0716:                                    null, null, null, null));
0717:                        } else {
0718:                            ColumnMetaData colmd = (ColumnMetaData) columns
0719:                                    .get(0);
0720:                            colmd.setJdbcType("CLOB");
0721:                        }
0722:                    }
0723:                    if (!useClob) {
0724:                        serialized = Boolean.TRUE;
0725:                    }
0726:                }
0727:
0728:                if (container == null && type.isArray()) {
0729:                    // User hasnt specifed <array> but the field is an array so infer it
0730:                    Class arrayCls = type.getComponentType();
0731:                    ArrayMetaData arrmd = new ArrayMetaData(this , arrayCls
0732:                            .getName(), null, null, null);
0733:                    container = arrmd;
0734:                }
0735:
0736:                if (container == null && targetClassName != null) {
0737:                    // User has specified target class name (JPA) so generate the <collection> or <map> accordingly
0738:                    if (java.util.Collection.class.isAssignableFrom(type)) {
0739:                        CollectionMetaData colmd = new CollectionMetaData(this ,
0740:                                targetClassName, null, null, null);
0741:                        container = colmd;
0742:                    } else if (java.util.Map.class.isAssignableFrom(type)) {
0743:                        MapMetaData mapmd = new MapMetaData(this , null, null,
0744:                                null, null, targetClassName, null, null, null);
0745:                        container = mapmd;
0746:                    }
0747:                }
0748:
0749:                if (JavaUtils.isJRE1_5OrAbove()) {
0750:                    // User hasnt specified collection/map but using JDK1.5 so construct the <collection>, <map> if using generics
0751:                    if (java.util.Collection.class.isAssignableFrom(type)) {
0752:                        String elementType = null;
0753:                        if (field != null) {
0754:                            elementType = ClassUtils
0755:                                    .getCollectionElementType(field);
0756:                        } else {
0757:                            elementType = ClassUtils
0758:                                    .getCollectionElementType(method);
0759:                        }
0760:                        if (elementType != null) {
0761:                            // Use generics information to infer any missing parts
0762:                            if (container == null) {
0763:                                // Create <collection element-type="...">
0764:                                CollectionMetaData colmd = new CollectionMetaData(
0765:                                        this , elementType, null, null, null);
0766:                                container = colmd;
0767:                            } else if (getCollection().element.type == null
0768:                                    || getCollection().element.type
0769:                                            .equals(ClassNameConstants.Object)) {
0770:                                // element-type not set so update element-type
0771:                                getCollection().element.type = elementType;
0772:                            }
0773:                        }
0774:                    } else if (java.util.Map.class.isAssignableFrom(type)) {
0775:                        String keyType = null;
0776:                        String valueType = null;
0777:                        if (field != null) {
0778:                            keyType = ClassUtils.getMapKeyType(field);
0779:                        } else {
0780:                            keyType = ClassUtils.getMapKeyType(method);
0781:                        }
0782:                        if (field != null) {
0783:                            valueType = ClassUtils.getMapValueType(field);
0784:                        } else {
0785:                            valueType = ClassUtils.getMapValueType(method);
0786:                        }
0787:                        if (keyType != null && valueType != null) {
0788:                            // Use generics information to infer any missing parts
0789:                            if (container == null) {
0790:                                // Create <map key-type="..." value-type="...">
0791:                                MapMetaData mapmd = new MapMetaData(this ,
0792:                                        keyType, null, null, null, valueType,
0793:                                        null, null, null);
0794:                                container = mapmd;
0795:                            } else {
0796:                                if (getMap().key.type == null
0797:                                        || getMap().key.type
0798:                                                .equals(ClassNameConstants.Object)) {
0799:                                    // key-type not set so update key-type
0800:                                    getMap().key.type = keyType;
0801:                                }
0802:                                if (getMap().value.type == null
0803:                                        || getMap().value.type
0804:                                                .equals(ClassNameConstants.Object)) {
0805:                                    // value-type not set so update value-type
0806:                                    getMap().value.type = valueType;
0807:                                }
0808:                            }
0809:                        }
0810:                    }
0811:                }
0812:
0813:                if (hasCollection() && ordered && orderMetaData == null) {
0814:                    setOrderMetaData(new OrderMetaData("#PK")); // Special value recognised by OrderMetaData
0815:                }
0816:
0817:                if (elementMetaData == null && !isSerialized() && !isEmbedded()
0818:                        && columnMetaData != null) {
0819:                    if (hasCollection() || hasArray()) {
0820:                        // Collection/Array with column(s) specified on field but not serialising so move to element
0821:                        ElementMetaData elemmd = new ElementMetaData(this ,
0822:                                null, null, null, null, null, null);
0823:                        setElementMetaData(elemmd);
0824:                        for (int i = 0; i < columnMetaData.length; i++) {
0825:                            elemmd.addColumn(columnMetaData[i]);
0826:                        }
0827:                    }
0828:                }
0829:                if (valueMetaData == null && hasMap() && !isEmbedded()
0830:                        && !isSerialized() && columnMetaData != null) {
0831:                    // Column specified directly but no value and not serialising field so add a value and apply cols there
0832:                    ValueMetaData valmd = new ValueMetaData(this , null, null,
0833:                            null, null, null, null);
0834:                    setValueMetaData(valmd);
0835:                    for (int i = 0; i < columnMetaData.length; i++) {
0836:                        valmd.addColumn(columnMetaData[i]);
0837:                    }
0838:                }
0839:
0840:                if (this .container != null && this .dependent != null) {
0841:                    // Check for invalid dependent field specifications
0842:                    JPOXLogger.METADATA.error(LOCALISER.msg("044110", name,
0843:                            getClassName(false), ((ClassMetaData) this .parent)
0844:                                    .getName()));
0845:                    throw new InvalidMetaDataException(LOCALISER, "044110",
0846:                            name, getClassName(false),
0847:                            ((ClassMetaData) this .parent).getName());
0848:                }
0849:
0850:                if (elementMetaData != null) {
0851:                    // Populate any element object
0852:                    elementMetaData.populate(clr, primary);
0853:                }
0854:                if (keyMetaData != null) {
0855:                    // Populate any key object
0856:                    keyMetaData.populate(clr, primary);
0857:                }
0858:                if (valueMetaData != null) {
0859:                    // Populate any value object
0860:                    valueMetaData.populate(clr, primary);
0861:                }
0862:                if (embeddedMetaData != null) {
0863:                    // Populate any embedded object
0864:                    embeddedMetaData.populate(clr, primary);
0865:                    embedded = Boolean.TRUE;
0866:                }
0867:
0868:                if (elementMetaData != null && elementMetaData.mappedBy != null
0869:                        && mappedBy == null) {
0870:                    // User has specified "mapped-by" on element instead of field so pull it up to this level
0871:                    // <element mapped-by="..."> is the same as <field mapped-by="..."> for a collection field
0872:                    mappedBy = elementMetaData.mappedBy;
0873:                }
0874:
0875:                if (container != null
0876:                        && persistenceModifier == FieldPersistenceModifier.PERSISTENT) {
0877:                    // Populate any container
0878:                    if (container instanceof  CollectionMetaData) {
0879:                        if (cascadeDelete) {
0880:                            // User has set cascade-delete (JPA) so set the element as dependent
0881:                            getCollection().element.dependent = Boolean.TRUE;
0882:                        }
0883:                        getCollection().populate(clr, primary);
0884:                    } else if (container instanceof  MapMetaData) {
0885:                        if (cascadeDelete) {
0886:                            // User has set cascade-delete (JPA) so set the value as dependent
0887:                            getMap().key.dependent = Boolean.TRUE; // Not really necessary but JPA doesnt provide for PC key fields specification
0888:                            getMap().value.dependent = Boolean.TRUE;
0889:                        }
0890:                        getMap().populate(clr, primary);
0891:                    } else if (container instanceof  ArrayMetaData) {
0892:                        if (cascadeDelete) {
0893:                            // User has set cascade-delete (JPA) so set the element as dependent
0894:                            getArray().element.dependent = Boolean.TRUE;
0895:                        }
0896:                        getArray().populate(clr, primary);
0897:                    }
0898:                }
0899:                if (isFieldTypePersistable() && cascadeDelete) {
0900:                    setDependent(true);
0901:                }
0902:
0903:                if (hasExtension("implementation-classes")) {
0904:                    // Check the validity of the implementation-classes and qualify them where required.
0905:                    StringBuffer str = new StringBuffer();
0906:                    String[] implTypes = getValuesForExtension("implementation-classes");
0907:                    for (int i = 0; i < implTypes.length; i++) {
0908:                        String implTypeName = ClassUtils.createFullClassName(
0909:                                getAbstractClassMetaData().getPackageName(),
0910:                                implTypes[i]);
0911:                        if (i > 0) {
0912:                            str.append(",");
0913:                        }
0914:
0915:                        try {
0916:                            clr.classForName(implTypeName);
0917:                            str.append(implTypeName);
0918:                        } catch (ClassNotResolvedException cnre) {
0919:                            try {
0920:                                // Maybe the user specified a java.lang class without fully-qualifying it
0921:                                // This is beyond the scope of the JDO spec which expects java.lang cases to be fully-qualified
0922:                                String langClassName = ClassUtils
0923:                                        .getJavaLangClassForType(implTypeName);
0924:                                clr.classForName(langClassName);
0925:                                str.append(langClassName);
0926:                            } catch (ClassNotResolvedException cnre2) {
0927:                                // Implementation type not found
0928:                                throw new InvalidMetaDataException(LOCALISER,
0929:                                        "044116", name, getClassName(false),
0930:                                        implTypes[i]);
0931:                            }
0932:                        }
0933:                    }
0934:                    addExtension(JPOX_VENDOR_NAME, "implementation-classes",
0935:                            str.toString()); // Replace with this new value
0936:                }
0937:
0938:                // Set up JDO flags for enhancement process
0939:                byte serializable = 0;
0940:                if (Serializable.class.isAssignableFrom(getType())
0941:                        || getType().isPrimitive()) {
0942:                    serializable = PersistenceFlags.SERIALIZABLE;
0943:                }
0944:
0945:                if (FieldPersistenceModifier.NONE.equals(persistenceModifier)) {
0946:                    jdoFieldFlag = 0;
0947:                } else if (FieldPersistenceModifier.TRANSACTIONAL
0948:                        .equals(persistenceModifier)
0949:                        && Modifier.isTransient(modifiers)) {
0950:                    jdoFieldFlag = (byte) (PersistenceFlags.CHECK_WRITE | serializable);
0951:                } else if (primaryKey.booleanValue()) {
0952:                    jdoFieldFlag = (byte) (PersistenceFlags.MEDIATE_WRITE | serializable);
0953:                } else if (defaultFetchGroup.booleanValue()) {
0954:                    jdoFieldFlag = (byte) (PersistenceFlags.CHECK_READ
0955:                            | PersistenceFlags.CHECK_WRITE | serializable);
0956:                } else if (!defaultFetchGroup.booleanValue()) {
0957:                    jdoFieldFlag = (byte) (PersistenceFlags.MEDIATE_READ
0958:                            | PersistenceFlags.MEDIATE_WRITE | serializable);
0959:                } else {
0960:                    jdoFieldFlag = 0;
0961:                }
0962:
0963:                setPopulated();
0964:            }
0965:
0966:            /**
0967:             * Initialisation method. This should be called AFTER using the populate
0968:             * method if you are going to use populate. It creates the internal
0969:             * convenience arrays etc needed for normal operation.
0970:             */
0971:            public synchronized void initialise() {
0972:                if (persistenceModifier == FieldPersistenceModifier.NONE) {
0973:                    setInitialised();
0974:                    return;
0975:                }
0976:
0977:                // Cater for user specifying column name, or columns
0978:                if (columns.size() == 0 && column != null) {
0979:                    columnMetaData = new ColumnMetaData[1];
0980:                    columnMetaData[0] = new ColumnMetaData(this , column);
0981:                    columnMetaData[0].initialise();
0982:                } else if (columns.size() == 1 && column != null) {
0983:                    // Cater for user specifying <column> and <field column="...">
0984:                    columnMetaData = new ColumnMetaData[1];
0985:                    columnMetaData[0] = (ColumnMetaData) columns.get(0);
0986:                    if (columnMetaData[0].getName() == null) {
0987:                        columnMetaData[0].setName(column);
0988:                    }
0989:                    columnMetaData[0].initialise();
0990:                } else {
0991:                    columnMetaData = new ColumnMetaData[columns.size()];
0992:                    for (int i = 0; i < columnMetaData.length; i++) {
0993:                        columnMetaData[i] = (ColumnMetaData) columns.get(i);
0994:                        columnMetaData[i].initialise();
0995:                    }
0996:                }
0997:
0998:                // Initialise all sub-objects
0999:                if (container != null) {
1000:                    container.initialise();
1001:                }
1002:                if (embeddedMetaData != null) {
1003:                    embeddedMetaData.initialise();
1004:                }
1005:                if (joinMetaData != null) {
1006:                    joinMetaData.initialise();
1007:                }
1008:                if (elementMetaData != null) {
1009:                    elementMetaData.initialise();
1010:                }
1011:                if (keyMetaData != null) {
1012:                    keyMetaData.initialise();
1013:                }
1014:                if (valueMetaData != null) {
1015:                    valueMetaData.initialise();
1016:                }
1017:
1018:                // Interpret the "indexed" value to create our IndexMetaData where it wasn't specified that way
1019:                if (indexMetaData == null && columnMetaData != null
1020:                        && indexed != null && indexed != IndexedValue.FALSE) {
1021:                    indexMetaData = new IndexMetaData(null, null,
1022:                            (indexed == IndexedValue.UNIQUE) ? "true" : "false");
1023:                    for (int i = 0; i < columnMetaData.length; i++) {
1024:                        indexMetaData.addColumn(columnMetaData[i]);
1025:                    }
1026:                }
1027:                if (indexMetaData != null) {
1028:                    indexMetaData.initialise();
1029:                }
1030:                if (uniqueMetaData == null && uniqueConstraint) {
1031:                    uniqueMetaData = new UniqueMetaData(null, column, null);
1032:                    for (int i = 0; i < columnMetaData.length; i++) {
1033:                        uniqueMetaData.addColumn(columnMetaData[i]);
1034:                    }
1035:                }
1036:                if (uniqueMetaData != null) {
1037:                    uniqueMetaData.initialise();
1038:                }
1039:
1040:                if (foreignKeyMetaData != null) {
1041:                    foreignKeyMetaData.initialise();
1042:                }
1043:                if (orderMetaData != null) {
1044:                    orderMetaData.initialise();
1045:                }
1046:
1047:                if ((hasCollection() && SCOUtils
1048:                        .collectionHasSerialisedElements(this ))
1049:                        || (hasMap() && SCOUtils
1050:                                .mapHasSerialisedKeysAndValues(this ))
1051:                        || (hasArray() && SCOUtils
1052:                                .arrayIsStoredInSingleColumn(this ))) {
1053:                    boolean setSerialised = true;
1054:                    if (hasArray()
1055:                            && MetaDataUtils.getInstance()
1056:                                    .arrayStorableAsByteArrayInSingleColumn(
1057:                                            this )) {
1058:                        // These can be streamed as byte arrays
1059:                        setSerialised = false;
1060:                    }
1061:
1062:                    // Collection/Array with serialised elements or Map with serialised keys and values so set as serialised for later
1063:                    if (setSerialised) {
1064:                        serialized = Boolean.TRUE;
1065:                    }
1066:                }
1067:
1068:                if (hasExtension("cascade-persist")) {
1069:                    // JDO doesnt have a metadata attribute for this so we use an extension
1070:                    String cascadeValue = getValueForExtension("cascade-persist");
1071:                    if (cascadeValue.equalsIgnoreCase("true")) {
1072:                        cascadePersist = true;
1073:                    } else if (cascadeValue.equalsIgnoreCase("false")) {
1074:                        cascadePersist = false;
1075:                    }
1076:                }
1077:                if (hasExtension("cascade-update")) {
1078:                    // JDO doesnt have a metadata attribute for this so we use an extension
1079:                    String cascadeValue = getValueForExtension("cascade-update");
1080:                    if (cascadeValue.equalsIgnoreCase("true")) {
1081:                        cascadeUpdate = true;
1082:                    } else if (cascadeValue.equalsIgnoreCase("false")) {
1083:                        cascadeUpdate = false;
1084:                    }
1085:                }
1086:                if (hasExtension("cascade-refresh")) {
1087:                    // JDO doesnt have a metadata attribute for this so we use an extension
1088:                    String cascadeValue = getValueForExtension("cascade-refresh");
1089:                    if (cascadeValue.equalsIgnoreCase("true")) {
1090:                        cascadeRefresh = true;
1091:                    } else if (cascadeValue.equalsIgnoreCase("false")) {
1092:                        cascadeRefresh = false;
1093:                    }
1094:                }
1095:
1096:                setInitialised();
1097:            }
1098:
1099:            /**
1100:             * Utility to return if this field is persistable.
1101:             * Not valid for use by the enhancer. Must be overridden for that mode.
1102:             * @return Whether the field type is persistable.
1103:             */
1104:            public boolean isFieldTypePersistable() {
1105:                if (getAbstractClassMetaData().getMetaDataManager()
1106:                        .isEnhancing()) {
1107:                    // Enhancing so return if we have MetaData that is persistable
1108:                    AbstractClassMetaData cmd = getAbstractClassMetaData()
1109:                            .getMetaDataManager().readMetaDataForClass(
1110:                                    type.getName());
1111:                    if (cmd != null
1112:                            && cmd instanceof  ClassMetaData
1113:                            && cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
1114:                        return true;
1115:                    }
1116:                }
1117:                return getMetaDataManager().getOMFContext().getApiAdapter()
1118:                        .isPersistable(type);
1119:            }
1120:
1121:            /**
1122:             * Utility to return if this array field has elements that are Persistable.
1123:             * Not valid for use by the enhancer. Must be overridden for that mode.
1124:             * If the field is not an array will return false.
1125:             * @return Whether the field type is persistable.
1126:             */
1127:            public boolean isFieldArrayTypePersistable() {
1128:                if (!type.isArray()) {
1129:                    return false;
1130:                }
1131:                if (getAbstractClassMetaData().getMetaDataManager()
1132:                        .isEnhancing()) {
1133:                    // Enhancing so return if we have MetaData that is PersistenceCapable
1134:                    AbstractClassMetaData cmd = getAbstractClassMetaData()
1135:                            .getMetaDataManager().readMetaDataForClass(
1136:                                    type.getComponentType().getName());
1137:                    if (cmd != null
1138:                            && cmd instanceof  ClassMetaData
1139:                            && cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
1140:                        return true;
1141:                    }
1142:                }
1143:                return getMetaDataManager().getOMFContext().getApiAdapter()
1144:                        .isPersistable(type.getComponentType());
1145:            }
1146:
1147:            /**
1148:             * Convenience method to return if this field/property is static.
1149:             * When the object is not "populated" always returns false; 
1150:             * @return Whether the field/property is static
1151:             */
1152:            public boolean isStatic() {
1153:                if (!isPopulated()) {
1154:                    return false;
1155:                }
1156:                return Modifier.isStatic(modifiers);
1157:            }
1158:
1159:            /**
1160:             * Convenience method to return if this field/property is final.
1161:             * When the object is not "populated" always returns false; 
1162:             * @return Whether the field is field/property
1163:             */
1164:            public boolean isFinal() {
1165:                if (!isPopulated()) {
1166:                    return false;
1167:                }
1168:                return Modifier.isFinal(modifiers);
1169:            }
1170:
1171:            /**
1172:             * Convenience method to return if this field/property is transient.
1173:             * When the object is not "populated" always returns false; 
1174:             * @return Whether the field/property is transient
1175:             */
1176:            public boolean isTransient() {
1177:                if (!isPopulated()) {
1178:                    return false;
1179:                }
1180:                return Modifier.isTransient(modifiers);
1181:            }
1182:
1183:            /**
1184:             * Convenience method to return if this field/property is public.
1185:             * When the object is not "populated" always returns false; 
1186:             * @return Whether the field/property is public
1187:             */
1188:            public boolean isPublic() {
1189:                if (!isPopulated()) {
1190:                    return false;
1191:                }
1192:                return Modifier.isPublic(modifiers);
1193:            }
1194:
1195:            /**
1196:             * Convenience method to return if this field/property is protected.
1197:             * When the object is not "populated" always returns false; 
1198:             * @return Whether the field/property is protected
1199:             */
1200:            public boolean isProtected() {
1201:                if (!isPopulated()) {
1202:                    return false;
1203:                }
1204:                return Modifier.isProtected(modifiers);
1205:            }
1206:
1207:            /**
1208:             * Convenience method to return if this field/property is private.
1209:             * When the object is not "populated" always returns false; 
1210:             * @return Whether the field/property is private
1211:             */
1212:            public boolean isPrivate() {
1213:                if (!isPopulated()) {
1214:                    return false;
1215:                }
1216:                return Modifier.isPrivate(modifiers);
1217:            }
1218:
1219:            /**
1220:             * Convenience method to return if this field represents an abstract property.
1221:             * @return Whether the property is abstract
1222:             */
1223:            public boolean isAbstract() {
1224:                if (!isPopulated()) {
1225:                    return false;
1226:                }
1227:                return Modifier.isAbstract(modifiers);
1228:            }
1229:
1230:            // ------------------------------- Accessors -------------------------------
1231:
1232:            /**
1233:             * The value-strategy attribute specifies the strategy used to generate
1234:             * values for the field. This attribute has the same values and meaning as
1235:             * the strategy attribute in datastoreidentity.
1236:             * @return the value strategy
1237:             */
1238:            public IdentityStrategy getValueStrategy() {
1239:                return valueStrategy;
1240:            }
1241:
1242:            /**
1243:             * Name of a (user-provided) value generator to override the default JPOX generator for this strategy.
1244:             * @return Name of user provided value generator
1245:             */
1246:            public String getValueGeneratorName() {
1247:                return valueGeneratorName;
1248:            }
1249:
1250:            /**
1251:             * If the value-strategy is sequence, the sequence attribute specifies the
1252:             * name of the sequence to use to automatically generate a value for the
1253:             * field.
1254:             * @return the sequence name 
1255:             */
1256:            public String getSequence() {
1257:                return sequence;
1258:            }
1259:
1260:            /**
1261:             * Accessor for the (additional) fetch group for loading this field
1262:             * @return Returns the load fetch group
1263:             */
1264:            public String getLoadFetchGroup() {
1265:                return loadFetchGroup;
1266:            }
1267:
1268:            /**
1269:             * Convenience method to set the load fetch group if required after construction.
1270:             * @param loadFetchGroup Name of the load fetch group
1271:             */
1272:            public void setLoadFetchGroup(String loadFetchGroup) {
1273:                this .loadFetchGroup = loadFetchGroup;
1274:            }
1275:
1276:            /**
1277:             * Accessor for the depth of the fetch when recursing
1278:             * @return Returns the depth of the fetch when recursing
1279:             */
1280:            public int getRecursionDepth() {
1281:                return recursionDepth;
1282:            }
1283:
1284:            /**
1285:             * Convenience method to navigate back through the parents to find the overall
1286:             * ClassMetaData handling this object. This is to cater specifically for nested
1287:             * embedded fields where you can nest object several levels deep.
1288:             * @param metadata The metadata to check
1289:             * @return The overall class metadata for this element
1290:             */
1291:            protected MetaData getOverallParentClassMetaData(MetaData metadata) {
1292:                if (metadata == null) {
1293:                    return null;
1294:                } else if (metadata instanceof  AbstractClassMetaData) {
1295:                    return metadata;
1296:                } else {
1297:                    return getOverallParentClassMetaData(metadata.getParent());
1298:                }
1299:            }
1300:
1301:            /**
1302:             * Convenience accessor for the MetaData of the parent class.
1303:             * @return Returns the MetaData of the parent class.
1304:             */
1305:            public AbstractClassMetaData getAbstractClassMetaData() {
1306:                // TODO Consider replacing this method with the getOverallParentClassMetaData above since its generalised
1307:                if (parent == null) {
1308:                    return null;
1309:                } else if (parent instanceof  AbstractClassMetaData) {
1310:                    return (AbstractClassMetaData) parent;
1311:                } else if (parent instanceof  EmbeddedMetaData) {
1312:                    // <embedded> is contained in a <field>, <element>, <key>, <value>
1313:                    // but could be multiple levels deep so adopt a generic strategy for finding the parent class
1314:                    MetaData parentMd = ((EmbeddedMetaData) parent).getParent();
1315:                    return (AbstractClassMetaData) getOverallParentClassMetaData(parentMd
1316:                            .getParent());
1317:                }
1318:                return null;
1319:            }
1320:
1321:            /**
1322:             * Accessor for orderMetaData
1323:             * @return Returns the orderMetaData.
1324:             */
1325:            public final OrderMetaData getOrderMetaData() {
1326:                return orderMetaData;
1327:            }
1328:
1329:            /**
1330:             * Accessor for the field name 
1331:             * @return field name
1332:             */
1333:            public String getName() {
1334:                return name;
1335:            }
1336:
1337:            /**
1338:             * Accessor for the full field name. This prepends the class name. 
1339:             * @return full field name.
1340:             */
1341:            public String getFullFieldName() {
1342:                if (className != null) {
1343:                    return className + "." + name;
1344:                }
1345:                return getClassName(true) + "." + name;
1346:            }
1347:
1348:            /**
1349:             * Accessor for whether the field is for a superclass, and not for this class.
1350:             * @return Whether the field belongs to a superclass
1351:             */
1352:            public boolean fieldBelongsToClass() {
1353:                return (className == null);
1354:            }
1355:
1356:            /**
1357:             * Accessor for the fully-qualified class name owning this field.
1358:             * @return The class name
1359:             */
1360:            public String getClassName() {
1361:                return getClassName(true);
1362:            }
1363:
1364:            /**
1365:             * Convenience method so that ClassMetaData can update the name of the superclass
1366:             * to which this field belongs.
1367:             * @param className Name of the class
1368:             */
1369:            void setClassName(String className) {
1370:                this .className = className;
1371:            }
1372:
1373:            /**
1374:             * Convenience to return the class name that this a field of.
1375:             * @param fully_qualified Whether the name should be fully qualified.
1376:             * @return Class name
1377:             */
1378:            public String getClassName(boolean fully_qualified) {
1379:                if (className != null) {
1380:                    return className;
1381:                }
1382:
1383:                if (parent == null) {
1384:                    return null;
1385:                } else if (parent instanceof  AbstractClassMetaData) {
1386:                    AbstractClassMetaData cmd = (AbstractClassMetaData) parent;
1387:                    if (fully_qualified) {
1388:                        return cmd.getFullClassName();
1389:                    } else {
1390:                        return cmd.getName();
1391:                    }
1392:                } else if (parent instanceof  EmbeddedMetaData) {
1393:                    // <embedded> is contained in a <field>, <element>, <key>, <value>
1394:                    MetaData parentMd = ((EmbeddedMetaData) parent).getParent();
1395:                    if (parentMd instanceof  AbstractMemberMetaData) {
1396:                        return ((AbstractMemberMetaData) parentMd)
1397:                                .getTypeName();
1398:                    } else if (parentMd instanceof  ElementMetaData) {
1399:                        AbstractMemberMetaData fmd = (AbstractMemberMetaData) ((ElementMetaData) parentMd)
1400:                                .getParent();
1401:                        return fmd.getCollection().getElementType();
1402:                    } else if (parentMd instanceof  KeyMetaData) {
1403:                        AbstractMemberMetaData fmd = (AbstractMemberMetaData) ((KeyMetaData) parentMd)
1404:                                .getParent();
1405:                        return fmd.getMap().getKeyType();
1406:                    } else if (parentMd instanceof  ValueMetaData) {
1407:                        AbstractMemberMetaData fmd = (AbstractMemberMetaData) ((ValueMetaData) parentMd)
1408:                                .getParent();
1409:                        return fmd.getMap().getValueType();
1410:                    } else {
1411:                        // Should be impossible
1412:                        return null;
1413:                    }
1414:                } else if (parent instanceof  UniqueMetaData) {
1415:                    MetaData grandparent = ((UniqueMetaData) parent)
1416:                            .getParent();
1417:                    if (grandparent instanceof  AbstractClassMetaData) {
1418:                        return ((AbstractClassMetaData) grandparent)
1419:                                .getFullClassName();
1420:                    }
1421:                    // TODO Cater for other parent options
1422:                }
1423:                return null;
1424:            }
1425:
1426:            /**
1427:             * Accessor for the null-value tag
1428:             * @return null-value tag
1429:             */
1430:            public NullValue getNullValue() {
1431:                return nullValue;
1432:            }
1433:
1434:            /**
1435:             * Accessor for the persistence-modifier tag value
1436:             * @return persistence-modifier tag value
1437:             */
1438:            public FieldPersistenceModifier getPersistenceModifier() {
1439:                return persistenceModifier;
1440:            }
1441:
1442:            /**
1443:             * Convenience method to mark this field as not-persistent.
1444:             */
1445:            public void setNotPersistent() {
1446:                persistenceModifier = FieldPersistenceModifier.NONE;
1447:            }
1448:
1449:            /**
1450:             * Convenience method to mark this field as transactional.
1451:             */
1452:            public void setTransactional() {
1453:                persistenceModifier = FieldPersistenceModifier.TRANSACTIONAL;
1454:            }
1455:
1456:            /**
1457:             * Accessor for the default-fetch-group tag value
1458:             * @return default-fetch-group tag value
1459:             */
1460:            public boolean isDefaultFetchGroup() {
1461:                if (defaultFetchGroup == null) {
1462:                    return false;
1463:                } else {
1464:                    return defaultFetchGroup.booleanValue();
1465:                }
1466:            }
1467:
1468:            /**
1469:             * Convenience method to set the DFG if needing setting after construction.
1470:             * @param dfg DFG string value
1471:             */
1472:            public void setDefaultFetchGroup(boolean dfg) {
1473:                this .defaultFetchGroup = new Boolean(dfg);
1474:            }
1475:
1476:            /**
1477:             * Accessor for the dependent attribute indicates that the field contains a
1478:             * reference that is to be deleted from the datastore if the referring
1479:             * instance in which the field is declared is deleted, or if the referring
1480:             * field is nullified.
1481:             * 
1482:             * @return dependent tag value
1483:             */
1484:            public boolean isDependent() {
1485:                if (dependent == null) {
1486:                    return false;
1487:                } else {
1488:                    return dependent.booleanValue();
1489:                }
1490:            }
1491:
1492:            /**
1493:             * Accessor for the embedded tag value.
1494:             * This value is a hint only to the implementation so will not mean
1495:             * that the type is certainly embedded.
1496:             * @return embedded tag value
1497:             */
1498:            public boolean isEmbedded() {
1499:                if (embedded == null) {
1500:                    return false;
1501:                } else {
1502:                    return embedded.booleanValue();
1503:                }
1504:            }
1505:
1506:            /**
1507:             * Accessor for the serialized tag value
1508:             * @return serialized tag value
1509:             */
1510:            public boolean isSerialized() {
1511:                if (serialized == null) {
1512:                    return false;
1513:                } else {
1514:                    return serialized.booleanValue();
1515:                }
1516:            }
1517:
1518:            /**
1519:             * Convenience method to mark this field to be stored serialised.
1520:             */
1521:            public void setSerialised() {
1522:                serialized = Boolean.TRUE;
1523:            }
1524:
1525:            /**
1526:             * Accessor for the whether this field should be cascaded at persist
1527:             * @return Whether to cascade at persist
1528:             */
1529:            public boolean isCascadePersist() {
1530:                return cascadePersist;
1531:            }
1532:
1533:            /**
1534:             * Accessor for the whether this field should be cascaded at update
1535:             * @return Whether to cascade at update
1536:             */
1537:            public boolean isCascadeUpdate() {
1538:                return cascadeUpdate;
1539:            }
1540:
1541:            /**
1542:             * Accessor for the whether this field should be cascaded at delete
1543:             * @return Whether to cascade at delete
1544:             */
1545:            public boolean isCascadeDelete() {
1546:                return cascadeDelete;
1547:            }
1548:
1549:            /**
1550:             * Accessor for the whether this field should be cascaded at refresh
1551:             * @return Whether to cascade at refresh
1552:             */
1553:            public boolean isCascadeRefresh() {
1554:                return cascadeRefresh;
1555:            }
1556:
1557:            /**
1558:             * Accessor for the primary-key tag value.
1559:             * @return primary-key tag value.
1560:             */
1561:            public boolean isPrimaryKey() {
1562:                if (primaryKey == null) {
1563:                    return false;
1564:                } else {
1565:                    return primaryKey.booleanValue();
1566:                }
1567:            }
1568:
1569:            /**
1570:             * Convenience method to make this field (part of) the primary key.
1571:             */
1572:            public void setPrimaryKey() {
1573:                primaryKey = Boolean.TRUE;
1574:                this .defaultFetchGroup = Boolean.TRUE;
1575:            }
1576:
1577:            /**
1578:             * Whether this uses getter/setter accessors (Property) or
1579:             * used field based access (Field)
1580:             * @return true if this is a property
1581:             */
1582:            public abstract boolean isProperty();
1583:
1584:            /**
1585:             * Accessor for the table name 
1586:             * @return table name
1587:             */
1588:            public String getTable() {
1589:                return table;
1590:            }
1591:
1592:            /**
1593:             * Accessor for the catalog name 
1594:             * @return catalog name
1595:             */
1596:            public String getCatalog() {
1597:                return catalog;
1598:            }
1599:
1600:            /**
1601:             * Accessor for the schema name 
1602:             * @return schema name
1603:             */
1604:            public String getSchema() {
1605:                return schema;
1606:            }
1607:
1608:            /**
1609:             * Accessor for the field id.
1610:             * Not set when the field is an overriding field.
1611:             * @return field id
1612:             */
1613:            public int getFieldId() {
1614:                return fieldId;
1615:            }
1616:
1617:            /**
1618:             * Accessor for the implementation type(s) that can be stored in this field when it is a reference type.
1619:             * @return Returns the implementation type(s) for the field.
1620:             */
1621:            public final String[] getFieldTypes() {
1622:                return fieldTypes;
1623:            }
1624:
1625:            /**
1626:             * Accessor for the field id
1627:             * @return field id
1628:             */
1629:            public int getAbsoluteFieldNumber() {
1630:                if (className == null) {
1631:                    // Normal field, parented by its true class
1632:                    return fieldId
1633:                            + getAbstractClassMetaData()
1634:                                    .getNoOfInheritedManagedMembers();
1635:                } else {
1636:                    // Overriding field, parented by a foster class
1637:                    return getAbstractClassMetaData()
1638:                            .getAbsolutePositionOfMember(name);
1639:                }
1640:            }
1641:
1642:            /**
1643:             * Accessor for the field type
1644:             * @return Reflection field type
1645:             */
1646:            public Class getType() {
1647:                return type;
1648:            }
1649:
1650:            /**
1651:             * Accessor for the field type name
1652:             * @return Reflection field type name
1653:             */
1654:            public String getTypeName() {
1655:                if (type == null) {
1656:                    return null;
1657:                }
1658:                return type.getName();
1659:            }
1660:
1661:            /**
1662:             * Accessor for the container for this field.
1663:             * @return The MetaData of the container for this field.
1664:             **/
1665:            public ContainerMetaData getContainer() {
1666:                return container;
1667:            }
1668:
1669:            /**
1670:             * Accessor for an array container for this field. Returns null if no array
1671:             * attached.
1672:             * @return The MetaData of the container for this field if an array
1673:             **/
1674:            public ArrayMetaData getArray() {
1675:                if (container != null && container instanceof  ArrayMetaData) {
1676:                    return (ArrayMetaData) container;
1677:                }
1678:                return null;
1679:            }
1680:
1681:            /**
1682:             * Accessor for a collection container for this field. Returns null if no
1683:             * collection attached.
1684:             * @return The MetaData of the container for this field if a Collection.
1685:             **/
1686:            public CollectionMetaData getCollection() {
1687:                if (container != null
1688:                        && container instanceof  CollectionMetaData) {
1689:                    return (CollectionMetaData) container;
1690:                }
1691:                return null;
1692:            }
1693:
1694:            /**
1695:             * Accessor for a map container for this field. Returns null if no map
1696:             * attached.
1697:             * @return The MetaData of the container for this field if a Map.
1698:             **/
1699:            public MapMetaData getMap() {
1700:                if (container != null && container instanceof  MapMetaData) {
1701:                    return (MapMetaData) container;
1702:                }
1703:                return null;
1704:            }
1705:
1706:            /**
1707:             * Accessor for the column 
1708:             * @return Returns the column.
1709:             */
1710:            public final String getColumn() {
1711:                return column;
1712:            }
1713:
1714:            /**
1715:             * Accessor for mappedBy
1716:             * @return Returns the mappedBy.
1717:             */
1718:            public final String getMappedBy() {
1719:                return mappedBy;
1720:            }
1721:
1722:            /**
1723:             * Acessor for the columns
1724:             * @return Returns the columnMetaData.
1725:             */
1726:            public final ColumnMetaData[] getColumnMetaData() {
1727:                return columnMetaData;
1728:            }
1729:
1730:            /**
1731:             * Accessor for elementMetaData
1732:             * @return Returns the elementMetaData.
1733:             */
1734:            public final ElementMetaData getElementMetaData() {
1735:                return elementMetaData;
1736:            }
1737:
1738:            /**
1739:             * Accessor for keyMetaData
1740:             * @return Returns the keyMetaData.
1741:             */
1742:            public final KeyMetaData getKeyMetaData() {
1743:                return keyMetaData;
1744:            }
1745:
1746:            /**
1747:             * Accessor for valueMetaData
1748:             * @return Returns the valueMetaData.
1749:             */
1750:            public final ValueMetaData getValueMetaData() {
1751:                return valueMetaData;
1752:            }
1753:
1754:            /**
1755:             * Accessor for embeddedMetaData
1756:             * @return Returns the embeddedMetaData.
1757:             */
1758:            public final EmbeddedMetaData getEmbeddedMetaData() {
1759:                return embeddedMetaData;
1760:            }
1761:
1762:            /**
1763:             * Accessor for foreignKeyMetaData
1764:             * @return Returns the foreignKeyMetaData.
1765:             */
1766:            public final ForeignKeyMetaData getForeignKeyMetaData() {
1767:                return foreignKeyMetaData;
1768:            }
1769:
1770:            /**
1771:             * Accessor for indexMetaData
1772:             * @return Returns the indexMetaData.
1773:             */
1774:            public final IndexMetaData getIndexMetaData() {
1775:                return indexMetaData;
1776:            }
1777:
1778:            /**
1779:             * Accessor for uniqueMetaData
1780:             * @return Returns the uniqueMetaData.
1781:             */
1782:            public final UniqueMetaData getUniqueMetaData() {
1783:                return uniqueMetaData;
1784:            }
1785:
1786:            /**
1787:             * Accessor for joinMetaData
1788:             * @return Returns the joinMetaData.
1789:             */
1790:            public final JoinMetaData getJoinMetaData() {
1791:                return joinMetaData;
1792:            }
1793:
1794:            /**
1795:             * Add a new ColumnMetaData element
1796:             * @param colmd the ColumnMetaData to add
1797:             */
1798:            public void addColumn(ColumnMetaData colmd) {
1799:                columns.add(colmd);
1800:                colmd.parent = this ;
1801:                columnMetaData = new ColumnMetaData[columns.size()];
1802:                for (int i = 0; i < columnMetaData.length; i++) {
1803:                    columnMetaData[i] = (ColumnMetaData) columns.get(i);
1804:                }
1805:            }
1806:
1807:            /**
1808:             * Accessor for whether the field has a container.
1809:             * @return Whether it represents a container.
1810:             */
1811:            public boolean hasContainer() {
1812:                return (container != null);
1813:            }
1814:
1815:            /**
1816:             * Accessor for whether the field has an array
1817:             * @return return true if has array
1818:             */
1819:            public boolean hasArray() {
1820:                if (container == null) {
1821:                    return false;
1822:                }
1823:                return (container instanceof  ArrayMetaData);
1824:            }
1825:
1826:            /**
1827:             * Accessor for whether the field has a collection
1828:             * @return return true if has collection
1829:             */
1830:            public boolean hasCollection() {
1831:                if (container == null) {
1832:                    return false;
1833:                }
1834:                return (container instanceof  CollectionMetaData);
1835:            }
1836:
1837:            /**
1838:             * Accessor for whether the field has a map.
1839:             * @return return true if has map
1840:             */
1841:            public boolean hasMap() {
1842:                if (container == null) {
1843:                    return false;
1844:                }
1845:                return (container instanceof  MapMetaData);
1846:            }
1847:
1848:            /**
1849:             * Accessor for the JDO field flag
1850:             * @return JDO Field flag (for enhancing)
1851:             */
1852:            public byte getJdoFieldFlag() {
1853:                return jdoFieldFlag;
1854:            }
1855:
1856:            /**
1857:             * Accessor for whether the field is to be managed by JPOX.
1858:             * @return Whether it is JPOX managed
1859:             */
1860:            public boolean isJdoField() {
1861:                if (isPopulated()) {
1862:                    if (isStatic() || isFinal()) {
1863:                        return false;
1864:                    }
1865:                }
1866:
1867:                if (persistenceModifier == null) {
1868:                    return false;
1869:                } else if (persistenceModifier
1870:                        .equals(FieldPersistenceModifier.NONE)) {
1871:                    return false;
1872:                }
1873:                return true;
1874:            }
1875:
1876:            // ------------------------------ Mutators ---------------------------------
1877:
1878:            /**
1879:             * Mutator for whether the collection stored in this field is ordered.
1880:             * Only valid until the metadata is initialised.
1881:             */
1882:            public void setOrdered() {
1883:                ordered = true;
1884:            }
1885:
1886:            /**
1887:             * Mutator for the target class name. Only valid until the metadata is initialised.
1888:             * @param target Target class name
1889:             */
1890:            public void setTargetClassName(String target) {
1891:                if (!StringUtils.isWhitespace(target)) {
1892:                    this .targetClassName = target;
1893:                }
1894:            }
1895:
1896:            /**
1897:             * Mutator for whetehr to store as a "lob".
1898:             */
1899:            public void setStoreInLob() {
1900:                storeInLob = true;
1901:            }
1902:
1903:            /**
1904:             * Mutator for the cascading of persist operations on this field.
1905:             * @param cascade Whether to cascade at persist
1906:             */
1907:            public void setCascadePersist(boolean cascade) {
1908:                this .cascadePersist = cascade;
1909:            }
1910:
1911:            /**
1912:             * Mutator for the cascading of update operations on this field.
1913:             * @param cascade Whether to cascade at update
1914:             */
1915:            public void setCascadeUpdate(boolean cascade) {
1916:                this .cascadeUpdate = cascade;
1917:            }
1918:
1919:            /**
1920:             * Mutator for the cascading of delete operations on this field.
1921:             * @param cascade Whether to cascade at delete
1922:             */
1923:            public void setCascadeDelete(boolean cascade) {
1924:                this .cascadeDelete = cascade;
1925:            }
1926:
1927:            /**
1928:             * Mutator for the cascading of refresh operations on this field.
1929:             * @param cascade Whether to cascade at refresh
1930:             */
1931:            public void setCascadeRefresh(boolean cascade) {
1932:                this .cascadeRefresh = cascade;
1933:            }
1934:
1935:            /**
1936:             * The value-strategy attribute specifies the strategy used to generate
1937:             * values for the field. This attribute has the same values and meaning as
1938:             * the strategy attribute in datastoreidentity.
1939:             * @param valueStrategy the value strategy
1940:             */
1941:            public void setValueStrategy(IdentityStrategy valueStrategy) {
1942:                this .valueStrategy = valueStrategy;
1943:            }
1944:
1945:            /**
1946:             * Mutator for the name of the value generator to use for this strategy.
1947:             * @param generator Name of value generator
1948:             */
1949:            public void setValueGeneratorName(String generator) {
1950:                if (StringUtils.isWhitespace(generator)) {
1951:                    valueGeneratorName = null;
1952:                } else {
1953:                    this .valueGeneratorName = generator;
1954:                }
1955:            }
1956:
1957:            /**
1958:             * If the value-strategy is sequence, the sequence attribute specifies the
1959:             * name of the sequence to use to automatically generate a value for the field.
1960:             * @param sequence the sequence name 
1961:             */
1962:            public void setSequence(String sequence) {
1963:                this .sequence = sequence;
1964:            }
1965:
1966:            /**
1967:             * Mutator for dependent attribute.
1968:             * @param dependent Whether it is dependent.
1969:             */
1970:            public void setDependent(boolean dependent) {
1971:                this .dependent = new Boolean(dependent);
1972:            }
1973:
1974:            /**
1975:             * Mutator for mappedBy
1976:             * @param mappedby The mapped-by field.
1977:             */
1978:            public void setMappedBy(String mappedby) {
1979:                mappedBy = mappedby;
1980:            }
1981:
1982:            /**
1983:             * Method to set the container for this field (if this field represents a
1984:             * container (collection, map, array).
1985:             * @param conmd The MetaData of the container for this field.
1986:             **/
1987:            public void setContainer(ContainerMetaData conmd) {
1988:                container = conmd;
1989:                container.parent = this ;
1990:            }
1991:
1992:            /**
1993:             * Mutator for the element MetaData 
1994:             * @param elementMetaData The elementMetaData to set.
1995:             */
1996:            public final void setElementMetaData(ElementMetaData elementMetaData) {
1997:                this .elementMetaData = elementMetaData;
1998:                this .elementMetaData.parent = this ;
1999:            }
2000:
2001:            /**
2002:             * Mutator for the key MetaData 
2003:             * @param keyMetaData The keyMetaData to set.
2004:             */
2005:            public final void setKeyMetaData(KeyMetaData keyMetaData) {
2006:                this .keyMetaData = keyMetaData;
2007:                this .keyMetaData.parent = this ;
2008:            }
2009:
2010:            /**
2011:             * Mutator for the order MetaData 
2012:             * @param orderMetaData The orderMetaData to set.
2013:             */
2014:            public final void setOrderMetaData(OrderMetaData orderMetaData) {
2015:                this .orderMetaData = orderMetaData;
2016:                this .orderMetaData.parent = this ;
2017:            }
2018:
2019:            /**
2020:             * Mutator for the value MetaData 
2021:             * @param valueMetaData The valueMetaData to set.
2022:             */
2023:            public final void setValueMetaData(ValueMetaData valueMetaData) {
2024:                this .valueMetaData = valueMetaData;
2025:                this .valueMetaData.parent = this ;
2026:            }
2027:
2028:            /**
2029:             * Mutator for the embedded MetaData 
2030:             * @param embeddedMetaData The embeddedMetaData to set.
2031:             */
2032:            public final void setEmbeddedMetaData(
2033:                    EmbeddedMetaData embeddedMetaData) {
2034:                this .embeddedMetaData = embeddedMetaData;
2035:                this .embeddedMetaData.parent = this ;
2036:            }
2037:
2038:            /**
2039:             * Mutator for the foreignKey MetaData 
2040:             * @param foreignKeyMetaData The foreignKeyMetaData to set.
2041:             */
2042:            public final void setForeignKeyMetaData(
2043:                    ForeignKeyMetaData foreignKeyMetaData) {
2044:                this .foreignKeyMetaData = foreignKeyMetaData;
2045:            }
2046:
2047:            /**
2048:             * Mutator for the index MetaData 
2049:             * @param indexMetaData The indexMetaData to set.
2050:             */
2051:            public final void setIndexMetaData(IndexMetaData indexMetaData) {
2052:                this .indexMetaData = indexMetaData;
2053:            }
2054:
2055:            /**
2056:             * Mutator for the unique MetaData 
2057:             * @param uniqueMetaData The uniqueMetaData to set.
2058:             */
2059:            public final void setUniqueMetaData(UniqueMetaData uniqueMetaData) {
2060:                this .uniqueMetaData = uniqueMetaData;
2061:            }
2062:
2063:            /**
2064:             * Mutator for the join MetaData 
2065:             * @param joinMetaData The joinMetaData to set.
2066:             */
2067:            public final void setJoinMetaData(JoinMetaData joinMetaData) {
2068:                this .joinMetaData = joinMetaData;
2069:                this .joinMetaData.parent = this ;
2070:            }
2071:
2072:            /**
2073:             * Mutator for the field id.
2074:             * Given package access since updated by ClassMetaData typically.
2075:             * Only used when the field is not an overriding field.
2076:             * @param field_id Id of the field
2077:             */
2078:            void setFieldId(int field_id) {
2079:                fieldId = field_id;
2080:            }
2081:
2082:            /**
2083:             * Mutator for the table name
2084:             * @param table The table name
2085:             */
2086:            public void setTable(String table) {
2087:                this .table = (StringUtils.isWhitespace(table) ? null : table);
2088:            }
2089:
2090:            /**
2091:             * Mutator for the catalog name
2092:             * @param catalog The catalog name
2093:             */
2094:            public void setCatalog(String catalog) {
2095:                this .catalog = (StringUtils.isWhitespace(catalog) ? null
2096:                        : catalog);
2097:            }
2098:
2099:            /**
2100:             * Mutator for the schema name
2101:             * @param schema The schema name
2102:             */
2103:            public void setSchema(String schema) {
2104:                this .schema = (StringUtils.isWhitespace(schema) ? null : schema);
2105:            }
2106:
2107:            // ------------------------------ Utilities --------------------------------
2108:
2109:            /**
2110:             * Convenience method that sets up the relation type of this field, and the reference to 
2111:             * any related field when it is bidirectional. If the relation is bidirectional then will also
2112:             * set the other side of the relation (to relate to this side).
2113:             * @param clr ClassLoader resolver
2114:             * @throws JPOXUserException If mapped-by doesnt exist at other side
2115:             */
2116:            protected void setRelation(ClassLoaderResolver clr) {
2117:                if (getPersistenceModifier() != FieldPersistenceModifier.PERSISTENT) {
2118:                    // Only of use for persistent fields
2119:                    relationType = Relation.NONE;
2120:                    relatedMemberMetaData = null;
2121:                    return;
2122:                }
2123:
2124:                // Find the metadata for the field object
2125:                AbstractClassMetaData otherCmd = null;
2126:                if (hasCollection()) {
2127:                    otherCmd = getCollection().getElementClassMetaData();
2128:                    if (otherCmd == null) {
2129:                        // Maybe a reference field
2130:                        Class elementCls = clr.classForName(getCollection()
2131:                                .getElementType());
2132:                        if (getMetaDataManager().getOMFContext()
2133:                                .getTypeManager().isReferenceType(elementCls)) {
2134:                            try {
2135:                                String[] implNames = MetaDataUtils
2136:                                        .getInstance()
2137:                                        .getImplementationNamesForReferenceField(
2138:                                                this ,
2139:                                                DatastoreField.ROLE_COLLECTION_ELEMENT,
2140:                                                clr);
2141:                                if (implNames != null && implNames.length > 0) {
2142:                                    // Take the first implementation
2143:                                    otherCmd = getMetaDataManager()
2144:                                            .getMetaDataForClass(implNames[0],
2145:                                                    clr);
2146:                                }
2147:                            } catch (JPOXUserException jpe) {
2148:                                if (!getCollection().isSerializedElement()
2149:                                        && mappedBy != null) {
2150:                                    // Non-serialised, and with mapped-by so we need implementation classes
2151:                                    throw jpe;
2152:                                } else {
2153:                                    // Serialised element with no implementation types so ignore it
2154:                                    JPOXLogger.METADATA
2155:                                            .info("Field "
2156:                                                    + getFullFieldName()
2157:                                                    + " is a collection of elements of reference type yet no implementation-classes are provided."
2158:                                                    + " Assuming they arent PersistenceCapable");
2159:                                }
2160:                            }
2161:                        }
2162:                    }
2163:                } else if (hasMap()) {
2164:                    otherCmd = ((MapMetaData) container)
2165:                            .getValueClassMetaData();
2166:                    //TODO [CORE-2585] valueCMD may be null because its type is an interface (non persistent interface), 
2167:                    //so we should handle the implementation classes
2168:                    if (otherCmd == null) {
2169:                        // Value not PC so use the Key if it is specified
2170:                        otherCmd = ((MapMetaData) container)
2171:                                .getKeyClassMetaData();
2172:                    }
2173:                    if (otherCmd == null) {
2174:                        // Maybe a reference key/value
2175:                    }
2176:                } else if (hasArray()) {
2177:                    otherCmd = ((ArrayMetaData) container)
2178:                            .getElementClassMetaData();
2179:                } else {
2180:                    if (getType().isInterface()) {
2181:                        // Reference field - take the metadata of the first implementation
2182:                        String[] implNames = MetaDataUtils.getInstance()
2183:                                .getImplementationNamesForReferenceField(this ,
2184:                                        DatastoreField.ROLE_FIELD, clr);
2185:                        if (implNames != null && implNames.length > 0) {
2186:                            otherCmd = getMetaDataManager()
2187:                                    .getMetaDataForClass(implNames[0], clr);
2188:                        }
2189:                        /*otherCmd = getMetaDataManager().getMetaDataForImplementationOfReference(getType(), null, clr);*/
2190:                        /*otherCmd = getAbstractClassMetaData().getMetaDataManager().getMetaDataForInterface(getType(), clr);*/
2191:                    } else {
2192:                        otherCmd = getMetaDataManager().getMetaDataForClass(
2193:                                getType(), clr);
2194:                    }
2195:                }
2196:
2197:                //TODO [CORE-2585] when the element or value type is an interface (non persistent interface), 
2198:                //we should look at the implementation classes for the "otherCmd"
2199:                //for now the relationType will be Relation.NONE in these cases because the otherCmd is null
2200:                if (otherCmd == null) {
2201:                    if (hasArray()
2202:                            && getArray()
2203:                                    .mayContainPersistenceCapableElements()) {
2204:                        relatedMemberMetaData = null;
2205:                        relationType = Relation.ONE_TO_MANY_UNI;
2206:                    } else {
2207:                        // Field cannot have a relation
2208:                        relatedMemberMetaData = null;
2209:                        relationType = Relation.NONE;
2210:                    }
2211:                } else {
2212:                    // Field is bidirectional
2213:                    if (mappedBy != null) {
2214:                        // This class has the "mapped-by" specified
2215:                        AbstractMemberMetaData otherMmd = otherCmd
2216:                                .getMetaDataForMember(mappedBy);
2217:                        if (otherMmd == null) {
2218:                            throw new JPOXUserException(LOCALISER.msg("044115",
2219:                                    getAbstractClassMetaData()
2220:                                            .getFullClassName(), name,
2221:                                    mappedBy, otherCmd.getFullClassName()))
2222:                                    .setFatal();
2223:                        }
2224:
2225:                        relatedMemberMetaData = new AbstractMemberMetaData[] { otherMmd };
2226:                        if (hasContainer()
2227:                                && relatedMemberMetaData[0].hasContainer()) {
2228:                            relationType = Relation.MANY_TO_MANY_BI;
2229:                        } else if (hasContainer()
2230:                                && !relatedMemberMetaData[0].hasContainer()) {
2231:                            relationType = Relation.ONE_TO_MANY_BI;
2232:                        } else if (!hasContainer()
2233:                                && relatedMemberMetaData[0].hasContainer()) {
2234:                            relationType = Relation.MANY_TO_ONE_BI;
2235:                        } else {
2236:                            relationType = Relation.ONE_TO_ONE_BI;
2237:                        }
2238:                    } else {
2239:                        // The "other" class maybe has "mapped-by" across to this field so navigate through the fields to find this one
2240:                        int[] otherFieldNumbers = otherCmd
2241:                                .getAllMemberPositions();
2242:                        HashSet relatedFields = new HashSet();
2243:                        for (int i = 0; i < otherFieldNumbers.length; i++) {
2244:                            AbstractMemberMetaData otherFmd = otherCmd
2245:                                    .getMetaDataForManagedMemberAtAbsolutePosition(otherFieldNumbers[i]);
2246:                            if (otherFmd.getMappedBy() != null
2247:                                    && otherFmd.getMappedBy().equals(name)) {
2248:                                // e.g Look at org.jpox.samples.inheritance.marbles
2249:                                if (otherFmd.hasContainer()) {
2250:                                    // N-1, M-N
2251:                                    if ((otherFmd.hasCollection() && otherFmd
2252:                                            .getCollection().getElementType()
2253:                                            .equals(getClassName(true)))
2254:                                            || (otherFmd.hasArray() && otherFmd
2255:                                                    .getArray()
2256:                                                    .getElementType().equals(
2257:                                                            getClassName(true)))
2258:                                            || (otherFmd.hasMap() && otherFmd
2259:                                                    .getMap().getKeyType()
2260:                                                    .equals(getClassName(true)))
2261:                                            || (otherFmd.hasMap() && otherFmd
2262:                                                    .getMap().getValueType()
2263:                                                    .equals(getClassName(true)))) {
2264:                                        relatedFields.add(otherFmd);
2265:                                        if (hasContainer()) {
2266:                                            // Should we mark Arrays, Lists, Maps as M-N ?
2267:                                            relationType = Relation.MANY_TO_MANY_BI;
2268:                                        } else {
2269:                                            relationType = Relation.MANY_TO_ONE_BI;
2270:                                        }
2271:                                    }
2272:                                } else {
2273:                                    // 1-1, 1-N
2274:                                    Class cls = clr
2275:                                            .classForName(getClassName(true));
2276:                                    if (otherFmd.getType()
2277:                                            .isAssignableFrom(cls)
2278:                                            || cls.isAssignableFrom(otherFmd
2279:                                                    .getType())) {
2280:                                        // Consistent 1-1, 1-N types (allow subclasses of the defined types)
2281:                                        relatedFields.add(otherFmd);
2282:                                        if (hasContainer()) {
2283:                                            relationType = Relation.ONE_TO_MANY_BI;
2284:                                        } else {
2285:                                            relationType = Relation.ONE_TO_ONE_BI;
2286:                                        }
2287:                                    }
2288:                                }
2289:                            }
2290:                        }
2291:                        if (relatedFields.size() > 0) {
2292:                            relatedMemberMetaData = (AbstractMemberMetaData[]) relatedFields
2293:                                    .toArray(new AbstractMemberMetaData[relatedFields
2294:                                            .size()]);
2295:                            relatedFields.clear();
2296:                            relatedFields = null;
2297:                        } else {
2298:                            // No "mapped-by" found at either end so is unidirectional
2299:                            if (hasContainer()) {
2300:                                relationType = Relation.ONE_TO_MANY_UNI;
2301:                            } else {
2302:                                relationType = Relation.ONE_TO_ONE_UNI;
2303:                            }
2304:                        }
2305:                    }
2306:                }
2307:            }
2308:
2309:            /**
2310:             * Accessor for the relation type for this field.
2311:             * @param clr ClassLoader resolver
2312:             * @return The relation type.
2313:             */
2314:            public int getRelationType(ClassLoaderResolver clr) {
2315:                if (relationType == -1) {
2316:                    // Is possible that this could be done in the populate() step but depends on availability of the related class
2317:                    setRelation(clr);
2318:                }
2319:                return relationType;
2320:            }
2321:
2322:            /**
2323:             * Convenience method for whether this field is the owner of the relation.
2324:             * If the field has no relation will return true.
2325:             * If the field is in a unidirectional relation will return true.
2326:             * If the field is in a bidirectional relation and has no mapped-by will return true.
2327:             * Otherwise returns false.
2328:             * @param clr ClassLoader resolver
2329:             * @return Whether it is the owner side of a relation
2330:             */
2331:            public boolean isRelationOwner(ClassLoaderResolver clr) {
2332:                if (relationType == -1) {
2333:                    setRelation(clr);
2334:                }
2335:                if (relationType == Relation.NONE) {
2336:                    return true;
2337:                } else if (relationType == Relation.ONE_TO_MANY_UNI
2338:                        || relationType == Relation.ONE_TO_ONE_UNI) {
2339:                    return true;
2340:                } else if (relationType == Relation.MANY_TO_MANY_BI
2341:                        || relationType == Relation.MANY_TO_ONE_BI
2342:                        || relationType == Relation.ONE_TO_MANY_BI
2343:                        || relationType == Relation.ONE_TO_ONE_BI) {
2344:                    return (mappedBy == null);
2345:                }
2346:                return false;
2347:            }
2348:
2349:            /**
2350:             * Accessor for the FieldMetaData of any related field/property (where this field is part of a 
2351:             * bidirectional relation). Allows for 1-1, 1-N, and M-N. If this field is not part of a bidirectional 
2352:             * relation (no "mapped-by" at either end) then it returns null.
2353:             * @param clr the ClassLoaderResolver
2354:             * @return The MetaData for the field/property at the "other end".
2355:             */
2356:            public AbstractMemberMetaData[] getRelatedMemberMetaData(
2357:                    ClassLoaderResolver clr) {
2358:                if (relationType == -1) {
2359:                    // Is possible that this could be done in the populate() step but depends on availability of the related class
2360:                    setRelation(clr);
2361:                }
2362:                // TODO This doesnt allow for 1-1, 1-N reference fields where there may be multiple "other fields".
2363:                return relatedMemberMetaData;
2364:            }
2365:
2366:            /**
2367:             * Convenience accessor for the MetaData for the field/property at the other side of the bidirectional
2368:             * relation given the objects at this side and the other side.
2369:             * @param clr ClassLoader Resolver
2370:             * @param thisPC This object
2371:             * @param otherPC The related object
2372:             * @return The MetaData for the field in the related object
2373:             */
2374:            public AbstractMemberMetaData getRelatedMemberMetaDataForObject(
2375:                    ClassLoaderResolver clr, Object this PC, Object otherPC) {
2376:                if (relationType == -1) {
2377:                    setRelation(clr);
2378:                }
2379:
2380:                if (relatedMemberMetaData == null) {
2381:                    return null;
2382:                }
2383:
2384:                // TODO Cater for 1-N, M-N types
2385:                for (int i = 0; i < relatedMemberMetaData.length; i++) {
2386:                    if (relationType == Relation.ONE_TO_ONE_BI) {
2387:                        if (relatedMemberMetaData[i].getType()
2388:                                .isAssignableFrom(this PC.getClass())
2389:                                && getType().isAssignableFrom(
2390:                                        otherPC.getClass())) {
2391:                            return relatedMemberMetaData[i];
2392:                        }
2393:                    } else if (relationType == Relation.MANY_TO_ONE_BI) {
2394:                        // Just allow for Collections
2395:                        if (relatedMemberMetaData[i].hasCollection()) {
2396:                            Class elementType = clr
2397:                                    .classForName(relatedMemberMetaData[i]
2398:                                            .getCollection().getElementType());
2399:                            if (elementType.isAssignableFrom(this PC.getClass())
2400:                                    && getType().isAssignableFrom(
2401:                                            otherPC.getClass())) {
2402:                                return relatedMemberMetaData[i];
2403:                            }
2404:                        } else if (relatedMemberMetaData[i].hasMap()) {
2405:                            Class valueType = clr
2406:                                    .classForName(relatedMemberMetaData[i]
2407:                                            .getMap().getValueType());
2408:                            if (valueType.isAssignableFrom(this PC.getClass())
2409:                                    && getType().isAssignableFrom(
2410:                                            otherPC.getClass())) {
2411:                                return relatedMemberMetaData[i];
2412:                            }
2413:                            Class keyType = clr
2414:                                    .classForName(relatedMemberMetaData[i]
2415:                                            .getMap().getKeyType());
2416:                            if (keyType.isAssignableFrom(this PC.getClass())
2417:                                    && getType().isAssignableFrom(
2418:                                            otherPC.getClass())) {
2419:                                return relatedMemberMetaData[i];
2420:                            }
2421:                        }
2422:                    }
2423:                }
2424:                return null;
2425:            }
2426:
2427:            /**
2428:             * Accessor for all ClassMetaData referenced by this Field.
2429:             * <p>
2430:             * Part of the "persistence-by-reachability" concept. 
2431:             * @param orderedCMDs List of ordered ClassMetaData objects (added to).
2432:             * @param referencedCMDs Set of referenced ClassMetaData objects (added to)
2433:             * @param dba_vendor_id Vendor id of the DBA
2434:             * @param clr the ClassLoaderResolver
2435:             **/
2436:            void getReferencedClassMetaData(final List orderedCMDs,
2437:                    final Set referencedCMDs, final String dba_vendor_id,
2438:                    final ClassLoaderResolver clr) {
2439:                AbstractClassMetaData type_cmd = getAbstractClassMetaData()
2440:                        .getMetaDataManager().getMetaDataForClass(getType(),
2441:                                clr);
2442:                if (type_cmd != null) {
2443:                    type_cmd.getReferencedClassMetaData(orderedCMDs,
2444:                            referencedCMDs, dba_vendor_id, clr);
2445:                }
2446:
2447:                if (container != null) {
2448:                    if (container instanceof  CollectionMetaData) {
2449:                        ((CollectionMetaData) container)
2450:                                .getReferencedClassMetaData(orderedCMDs,
2451:                                        referencedCMDs, dba_vendor_id, clr);
2452:                    } else if (container instanceof  MapMetaData) {
2453:                        ((MapMetaData) container)
2454:                                .getReferencedClassMetaData(orderedCMDs,
2455:                                        referencedCMDs, dba_vendor_id, clr);
2456:                    } else if (container instanceof  ArrayMetaData) {
2457:                        ((ArrayMetaData) container)
2458:                                .getReferencedClassMetaData(orderedCMDs,
2459:                                        referencedCMDs, dba_vendor_id, clr);
2460:                    }
2461:                }
2462:            }
2463:
2464:            /**
2465:             *  Calculate wether this field should be a second class mutable field.
2466:             *  This calculation is a bit expensive.
2467:             *  Please note that this data will be cached in {@link AbstractClassMetaData#scoMutableMemberFlags}. 
2468:             *  
2469:             *  @return wether this field should be a second class mutable field.
2470:             */
2471:            public boolean calcIsSecondClassMutable() {
2472:                if (hasExtension("is-second-class")) {
2473:                    String isSecondClass = getValueForExtension("is-second-class");
2474:
2475:                    if (isSecondClass.equalsIgnoreCase("true")) {
2476:                        return true;
2477:                    } else if (isSecondClass.equalsIgnoreCase("false")) {
2478:                        return false;
2479:                    } else if (isSecondClass.equalsIgnoreCase("default")) { // fall through to default behaviour
2480:
2481:                    } else {
2482:                        // Be nice to JDO mapping authors and remind them that they may have a misspelling.
2483:                        throw new UnsupportedOperationException(
2484:                                this 
2485:                                        + ": extensions \"is-second-class\" may have only values \"true\", \"false\", \"default\" or it may not be set at all. But it is set to \""
2486:                                        + isSecondClass + "\".");
2487:                    }
2488:                } else { // fall through to default behaviour
2489:
2490:                }
2491:
2492:                return getMetaDataManager().getOMFContext().getTypeManager()
2493:                        .isSecondClassMutableType(getTypeName());
2494:            }
2495:
2496:            /**
2497:             * Returns a string representation of the object using a prefix
2498:             * This can be used as part of a facility to output a MetaData file. 
2499:             * @param prefix prefix string
2500:             * @param indent indent string
2501:             * @return a string representation of the object.
2502:             */
2503:            public String toString(String prefix, String indent) {
2504:                return super .toString(prefix, indent);
2505:            }
2506:
2507:            /**
2508:             * Comparator method. This allows the ClassMetaData to search for a
2509:             * FieldMetaData with a particular name.
2510:             * @param o The object to compare against
2511:             * @return The comparison result
2512:             */
2513:            public int compareTo(Object o) {
2514:                if (o instanceof  AbstractMemberMetaData) {
2515:                    AbstractMemberMetaData c = (AbstractMemberMetaData) o;
2516:                    return this .name.compareTo(c.name);
2517:                } else if (o instanceof  String) {
2518:                    return this .name.compareTo((String) o);
2519:                } else if (o == null) {
2520:                    throw new ClassCastException("object is null");
2521:                }
2522:                throw new ClassCastException(this .getClass().getName() + " != "
2523:                        + o.getClass().getName());
2524:            }
2525:
2526:            /**
2527:             * Convenience accessor for the MetaData Manager in use.
2528:             * @return MetaDataManager.
2529:             */
2530:            public MetaDataManager getMetaDataManager() {
2531:                MetaData overallCmd = getOverallParentClassMetaData(this );
2532:                return (overallCmd != null ? ((AbstractClassMetaData) overallCmd)
2533:                        .getMetaDataManager()
2534:                        : null);
2535:            }
2536:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.