Source Code Cross Referenced for ModelConstraints.java in  » Database-ORM » db-ojb » xdoclet » modules » ojb » constraints » 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 » db ojb » xdoclet.modules.ojb.constraints 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package xdoclet.modules.ojb.constraints;
0002:
0003:        /* Copyright 2004-2005 The Apache Software Foundation
0004:         *
0005:         * Licensed under the Apache License, Version 2.0 (the "License");
0006:         * you may not use this file except in compliance with the License.
0007:         * You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        import java.util.ArrayList;
0019:        import java.util.Collection;
0020:        import java.util.Iterator;
0021:
0022:        import org.apache.commons.collections.SequencedHashMap;
0023:
0024:        import xdoclet.modules.ojb.CommaListIterator;
0025:        import xdoclet.modules.ojb.LogHelper;
0026:        import xdoclet.modules.ojb.model.ClassDescriptorDef;
0027:        import xdoclet.modules.ojb.model.CollectionDescriptorDef;
0028:        import xdoclet.modules.ojb.model.FeatureDescriptorDef;
0029:        import xdoclet.modules.ojb.model.FieldDescriptorDef;
0030:        import xdoclet.modules.ojb.model.ModelDef;
0031:        import xdoclet.modules.ojb.model.PropertyHelper;
0032:        import xdoclet.modules.ojb.model.ReferenceDescriptorDef;
0033:
0034:        /**
0035:         * Checks constraints that span deal with parts of the model, not just with one class.
0036:         * This for instance means relationships (collections, references).
0037:         *
0038:         * @author <a href="mailto:tomdz@users.sourceforge.net">Thomas Dudziak (tomdz@users.sourceforge.net)</a>
0039:         */
0040:        public class ModelConstraints extends ConstraintsBase {
0041:            /**
0042:             * Checks the given model.
0043:             * 
0044:             * @param modelDef   The model
0045:             * @param checkLevel The amount of checks to perform
0046:             * @exception ConstraintException If a constraint has been violated
0047:             */
0048:            public void check(ModelDef modelDef, String checkLevel)
0049:                    throws ConstraintException {
0050:                ensureReferencedKeys(modelDef, checkLevel);
0051:                checkReferenceForeignkeys(modelDef, checkLevel);
0052:                checkCollectionForeignkeys(modelDef, checkLevel);
0053:                checkKeyModifications(modelDef, checkLevel);
0054:            }
0055:
0056:            /**
0057:             * Ensures that the primary/foreign keys referenced by references/collections are present
0058:             * in the target type even if generate-table-info="false", by evaluating the subtypes
0059:             * of the target type.
0060:             * 
0061:             * @param modelDef   The model
0062:             * @param checkLevel The current check level (this constraint is always checked)
0063:             * @throws ConstraintException If there is an error with the keys of the subtypes or there
0064:             *                             ain't any subtypes 
0065:             */
0066:            private void ensureReferencedKeys(ModelDef modelDef,
0067:                    String checkLevel) throws ConstraintException {
0068:                ClassDescriptorDef classDef;
0069:                CollectionDescriptorDef collDef;
0070:                ReferenceDescriptorDef refDef;
0071:
0072:                for (Iterator it = modelDef.getClasses(); it.hasNext();) {
0073:                    classDef = (ClassDescriptorDef) it.next();
0074:                    for (Iterator refIt = classDef.getReferences(); refIt
0075:                            .hasNext();) {
0076:                        refDef = (ReferenceDescriptorDef) refIt.next();
0077:                        if (!refDef.getBooleanProperty(
0078:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0079:                            ensureReferencedPKs(modelDef, refDef);
0080:                        }
0081:                    }
0082:                    for (Iterator collIt = classDef.getCollections(); collIt
0083:                            .hasNext();) {
0084:                        collDef = (CollectionDescriptorDef) collIt.next();
0085:                        if (!collDef.getBooleanProperty(
0086:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0087:                            if (collDef
0088:                                    .hasProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE)) {
0089:                                ensureReferencedPKs(modelDef, collDef);
0090:                            } else {
0091:                                ensureReferencedFKs(modelDef, collDef);
0092:                            }
0093:                        }
0094:                    }
0095:                }
0096:            }
0097:
0098:            /**
0099:             * Ensures that the primary keys required by the given reference are present in the referenced class.
0100:             * 
0101:             * @param modelDef The model
0102:             * @param refDef   The reference
0103:             * @throws ConstraintException If there is a conflict between the primary keys
0104:             */
0105:            private void ensureReferencedPKs(ModelDef modelDef,
0106:                    ReferenceDescriptorDef refDef) throws ConstraintException {
0107:                String targetClassName = refDef
0108:                        .getProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF);
0109:                ClassDescriptorDef targetClassDef = modelDef
0110:                        .getClass(targetClassName);
0111:
0112:                ensurePKsFromHierarchy(targetClassDef);
0113:            }
0114:
0115:            /**
0116:             * Ensures that the primary keys required by the given collection with indirection table are present in
0117:             * the element class.
0118:             * 
0119:             * @param modelDef The model
0120:             * @param collDef  The collection
0121:             * @throws ConstraintException If there is a problem with the fitting collection (if any) or the primary keys
0122:             */
0123:            private void ensureReferencedPKs(ModelDef modelDef,
0124:                    CollectionDescriptorDef collDef) throws ConstraintException {
0125:                String elementClassName = collDef
0126:                        .getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF);
0127:                ClassDescriptorDef elementClassDef = modelDef
0128:                        .getClass(elementClassName);
0129:                String indirTable = collDef
0130:                        .getProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE);
0131:                String localKey = collDef
0132:                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0133:                String remoteKey = collDef
0134:                        .getProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY);
0135:                boolean hasRemoteKey = remoteKey != null;
0136:                ArrayList fittingCollections = new ArrayList();
0137:
0138:                // we're checking for the fitting remote collection(s) and also
0139:                // use their foreignkey as remote-foreignkey in the original collection definition
0140:                for (Iterator it = elementClassDef.getAllExtentClasses(); it
0141:                        .hasNext();) {
0142:                    ClassDescriptorDef subTypeDef = (ClassDescriptorDef) it
0143:                            .next();
0144:
0145:                    // find the collection in the element class that has the same indirection table
0146:                    for (Iterator collIt = subTypeDef.getCollections(); collIt
0147:                            .hasNext();) {
0148:                        CollectionDescriptorDef curCollDef = (CollectionDescriptorDef) collIt
0149:                                .next();
0150:
0151:                        if (indirTable
0152:                                .equals(curCollDef
0153:                                        .getProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE))
0154:                                && (collDef != curCollDef)
0155:                                && (!hasRemoteKey || CommaListIterator
0156:                                        .sameLists(
0157:                                                remoteKey,
0158:                                                curCollDef
0159:                                                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY)))
0160:                                && (!curCollDef
0161:                                        .hasProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY) || CommaListIterator
0162:                                        .sameLists(
0163:                                                localKey,
0164:                                                curCollDef
0165:                                                        .getProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY)))) {
0166:                            fittingCollections.add(curCollDef);
0167:                        }
0168:                    }
0169:                }
0170:                if (!fittingCollections.isEmpty()) {
0171:                    // if there is more than one, check that they match, i.e. that they all have the same foreignkeys
0172:                    if (!hasRemoteKey && (fittingCollections.size() > 1)) {
0173:                        CollectionDescriptorDef firstCollDef = (CollectionDescriptorDef) fittingCollections
0174:                                .get(0);
0175:                        String foreignKey = firstCollDef
0176:                                .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0177:
0178:                        for (int idx = 1; idx < fittingCollections.size(); idx++) {
0179:                            CollectionDescriptorDef curCollDef = (CollectionDescriptorDef) fittingCollections
0180:                                    .get(idx);
0181:
0182:                            if (!CommaListIterator
0183:                                    .sameLists(
0184:                                            foreignKey,
0185:                                            curCollDef
0186:                                                    .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY))) {
0187:                                throw new ConstraintException(
0188:                                        "Cannot determine the element-side collection that corresponds to the collection "
0189:                                                + collDef.getName()
0190:                                                + " in type "
0191:                                                + collDef.getOwner().getName()
0192:                                                + " because there are at least two different collections that would fit."
0193:                                                + " Specifying remote-foreignkey in the original collection "
0194:                                                + collDef.getName()
0195:                                                + " will perhaps help");
0196:                            }
0197:                        }
0198:                        // store the found keys at the collections
0199:                        collDef.setProperty(
0200:                                PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY,
0201:                                foreignKey);
0202:                        for (int idx = 0; idx < fittingCollections.size(); idx++) {
0203:                            CollectionDescriptorDef curCollDef = (CollectionDescriptorDef) fittingCollections
0204:                                    .get(idx);
0205:
0206:                            curCollDef
0207:                                    .setProperty(
0208:                                            PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY,
0209:                                            localKey);
0210:                        }
0211:                    }
0212:                }
0213:
0214:                // copy subclass pk fields into target class (if not already present)
0215:                ensurePKsFromHierarchy(elementClassDef);
0216:            }
0217:
0218:            /**
0219:             * Ensures that the foreign keys required by the given collection are present in the element class.
0220:             * 
0221:             * @param modelDef The model
0222:             * @param collDef  The collection
0223:             * @throws ConstraintException If there is a problem with the foreign keys
0224:             */
0225:            private void ensureReferencedFKs(ModelDef modelDef,
0226:                    CollectionDescriptorDef collDef) throws ConstraintException {
0227:                String elementClassName = collDef
0228:                        .getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF);
0229:                ClassDescriptorDef elementClassDef = modelDef
0230:                        .getClass(elementClassName);
0231:                String fkFieldNames = collDef
0232:                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0233:                ArrayList missingFields = new ArrayList();
0234:                SequencedHashMap fkFields = new SequencedHashMap();
0235:
0236:                // first we gather all field names
0237:                for (CommaListIterator it = new CommaListIterator(fkFieldNames); it
0238:                        .hasNext();) {
0239:                    String fieldName = (String) it.next();
0240:                    FieldDescriptorDef fieldDef = elementClassDef
0241:                            .getField(fieldName);
0242:
0243:                    if (fieldDef == null) {
0244:                        missingFields.add(fieldName);
0245:                    }
0246:                    fkFields.put(fieldName, fieldDef);
0247:                }
0248:
0249:                // next we traverse all sub types and gather fields as we go
0250:                for (Iterator it = elementClassDef.getAllExtentClasses(); it
0251:                        .hasNext()
0252:                        && !missingFields.isEmpty();) {
0253:                    ClassDescriptorDef subTypeDef = (ClassDescriptorDef) it
0254:                            .next();
0255:
0256:                    for (int idx = 0; idx < missingFields.size();) {
0257:                        FieldDescriptorDef fieldDef = subTypeDef
0258:                                .getField((String) missingFields.get(idx));
0259:
0260:                        if (fieldDef != null) {
0261:                            fkFields.put(fieldDef.getName(), fieldDef);
0262:                            missingFields.remove(idx);
0263:                        } else {
0264:                            idx++;
0265:                        }
0266:                    }
0267:                }
0268:                if (!missingFields.isEmpty()) {
0269:                    throw new ConstraintException("Cannot find field "
0270:                            + missingFields.get(0).toString()
0271:                            + " in the hierarchy with root type "
0272:                            + elementClassDef.getName()
0273:                            + " which is used as foreignkey in collection "
0274:                            + collDef.getName() + " in "
0275:                            + collDef.getOwner().getName());
0276:                }
0277:
0278:                // copy the found fields into the element class
0279:                ensureFields(elementClassDef, fkFields.values());
0280:            }
0281:
0282:            /**
0283:             * Gathers the pk fields from the hierarchy of the given class, and copies them into the class.
0284:             * 
0285:             * @param classDef The root of the hierarchy
0286:             * @throws ConstraintException If there is a conflict between the pk fields 
0287:             */
0288:            private void ensurePKsFromHierarchy(ClassDescriptorDef classDef)
0289:                    throws ConstraintException {
0290:                SequencedHashMap pks = new SequencedHashMap();
0291:
0292:                for (Iterator it = classDef.getAllExtentClasses(); it.hasNext();) {
0293:                    ClassDescriptorDef subTypeDef = (ClassDescriptorDef) it
0294:                            .next();
0295:
0296:                    ArrayList subPKs = subTypeDef.getPrimaryKeys();
0297:
0298:                    // check against already present PKs
0299:                    for (Iterator pkIt = subPKs.iterator(); pkIt.hasNext();) {
0300:                        FieldDescriptorDef fieldDef = (FieldDescriptorDef) pkIt
0301:                                .next();
0302:                        FieldDescriptorDef foundPKDef = (FieldDescriptorDef) pks
0303:                                .get(fieldDef.getName());
0304:
0305:                        if (foundPKDef != null) {
0306:                            if (!isEqual(fieldDef, foundPKDef)) {
0307:                                throw new ConstraintException(
0308:                                        "Cannot pull up the declaration of the required primary key "
0309:                                                + fieldDef.getName()
0310:                                                + " because its definitions in "
0311:                                                + fieldDef.getOwner().getName()
0312:                                                + " and "
0313:                                                + foundPKDef.getOwner()
0314:                                                        .getName() + " differ");
0315:                            }
0316:                        } else {
0317:                            pks.put(fieldDef.getName(), fieldDef);
0318:                        }
0319:                    }
0320:                }
0321:
0322:                ensureFields(classDef, pks.values());
0323:            }
0324:
0325:            /**
0326:             * Ensures that the specified fields are present in the given class.
0327:             * 
0328:             * @param classDef The class to copy the fields into
0329:             * @param fields   The fields to copy
0330:             * @throws ConstraintException If there is a conflict between the new fields and fields in the class  
0331:             */
0332:            private void ensureFields(ClassDescriptorDef classDef,
0333:                    Collection fields) throws ConstraintException {
0334:                boolean forceVirtual = !classDef.getBooleanProperty(
0335:                        PropertyHelper.OJB_PROPERTY_GENERATE_REPOSITORY_INFO,
0336:                        true);
0337:
0338:                for (Iterator it = fields.iterator(); it.hasNext();) {
0339:                    FieldDescriptorDef fieldDef = (FieldDescriptorDef) it
0340:                            .next();
0341:
0342:                    // First we check whether this field is already present in the class
0343:                    FieldDescriptorDef foundFieldDef = classDef
0344:                            .getField(fieldDef.getName());
0345:
0346:                    if (foundFieldDef != null) {
0347:                        if (isEqual(fieldDef, foundFieldDef)) {
0348:                            if (forceVirtual) {
0349:                                foundFieldDef
0350:                                        .setProperty(
0351:                                                PropertyHelper.OJB_PROPERTY_VIRTUAL_FIELD,
0352:                                                "true");
0353:                            }
0354:                            continue;
0355:                        } else {
0356:                            throw new ConstraintException(
0357:                                    "Cannot pull up the declaration of the required field "
0358:                                            + fieldDef.getName()
0359:                                            + " from type "
0360:                                            + fieldDef.getOwner().getName()
0361:                                            + " to basetype "
0362:                                            + classDef.getName()
0363:                                            + " because there is already a different field of the same name");
0364:                        }
0365:                    }
0366:
0367:                    // perhaps a reference or collection ?
0368:                    if (classDef.getCollection(fieldDef.getName()) != null) {
0369:                        throw new ConstraintException(
0370:                                "Cannot pull up the declaration of the required field "
0371:                                        + fieldDef.getName()
0372:                                        + " from type "
0373:                                        + fieldDef.getOwner().getName()
0374:                                        + " to basetype "
0375:                                        + classDef.getName()
0376:                                        + " because there is already a collection of the same name");
0377:                    }
0378:                    if (classDef.getReference(fieldDef.getName()) != null) {
0379:                        throw new ConstraintException(
0380:                                "Cannot pull up the declaration of the required field "
0381:                                        + fieldDef.getName()
0382:                                        + " from type "
0383:                                        + fieldDef.getOwner().getName()
0384:                                        + " to basetype "
0385:                                        + classDef.getName()
0386:                                        + " because there is already a reference of the same name");
0387:                    }
0388:                    classDef.addFieldClone(fieldDef);
0389:                    classDef.getField(fieldDef.getName()).setProperty(
0390:                            PropertyHelper.OJB_PROPERTY_VIRTUAL_FIELD, "true");
0391:                }
0392:            }
0393:
0394:            /**
0395:             * Tests whether the two field descriptors are equal, i.e. have same name, same column
0396:             * and same jdbc-type.
0397:             * 
0398:             * @param first  The first field
0399:             * @param second The second field
0400:             * @return <code>true</code> if they are equal
0401:             */
0402:            private boolean isEqual(FieldDescriptorDef first,
0403:                    FieldDescriptorDef second) {
0404:                return first.getName().equals(second.getName())
0405:                        && first
0406:                                .getProperty(PropertyHelper.OJB_PROPERTY_COLUMN)
0407:                                .equals(
0408:                                        second
0409:                                                .getProperty(PropertyHelper.OJB_PROPERTY_COLUMN))
0410:                        && first
0411:                                .getProperty(
0412:                                        PropertyHelper.OJB_PROPERTY_JDBC_TYPE)
0413:                                .equals(
0414:                                        second
0415:                                                .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE));
0416:            }
0417:
0418:            /**
0419:             * Checks the foreignkeys of all collections in the model.
0420:             * 
0421:             * @param modelDef   The model
0422:             * @param checkLevel The current check level (this constraint is checked in basic and strict)
0423:             * @exception ConstraintException If the value for foreignkey is invalid
0424:             */
0425:            private void checkCollectionForeignkeys(ModelDef modelDef,
0426:                    String checkLevel) throws ConstraintException {
0427:                if (CHECKLEVEL_NONE.equals(checkLevel)) {
0428:                    return;
0429:                }
0430:
0431:                ClassDescriptorDef classDef;
0432:                CollectionDescriptorDef collDef;
0433:
0434:                for (Iterator it = modelDef.getClasses(); it.hasNext();) {
0435:                    classDef = (ClassDescriptorDef) it.next();
0436:                    for (Iterator collIt = classDef.getCollections(); collIt
0437:                            .hasNext();) {
0438:                        collDef = (CollectionDescriptorDef) collIt.next();
0439:                        if (!collDef.getBooleanProperty(
0440:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0441:                            if (collDef
0442:                                    .hasProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE)) {
0443:                                checkIndirectionTable(modelDef, collDef);
0444:                            } else {
0445:                                checkCollectionForeignkeys(modelDef, collDef);
0446:                            }
0447:                        }
0448:                    }
0449:                }
0450:            }
0451:
0452:            /**
0453:             * Checks the indirection-table and foreignkey of the collection. This constraint also ensures that
0454:             * for the collections on both ends (if they exist), the remote-foreignkey property is set correctly.
0455:             * 
0456:             * @param modelDef The model
0457:             * @param collDef  The collection descriptor
0458:             * @exception ConstraintException If the value for foreignkey is invalid
0459:             */
0460:            private void checkIndirectionTable(ModelDef modelDef,
0461:                    CollectionDescriptorDef collDef) throws ConstraintException {
0462:                String foreignkey = collDef
0463:                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0464:
0465:                if ((foreignkey == null) || (foreignkey.length() == 0)) {
0466:                    throw new ConstraintException("The collection "
0467:                            + collDef.getName() + " in class "
0468:                            + collDef.getOwner().getName()
0469:                            + " has no foreignkeys");
0470:                }
0471:
0472:                // we know that the class is present because the collection constraints have been checked already
0473:                // TODO: we must check whether there is a collection at the other side; if the type does not map to a
0474:                // table then we have to check its subtypes
0475:                String elementClassName = collDef
0476:                        .getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF);
0477:                ClassDescriptorDef elementClass = modelDef
0478:                        .getClass(elementClassName);
0479:                CollectionDescriptorDef remoteCollDef = collDef
0480:                        .getRemoteCollection();
0481:
0482:                if (remoteCollDef == null) {
0483:                    // error if there is none and we don't have remote-foreignkey specified
0484:                    if (!collDef
0485:                            .hasProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY)) {
0486:                        throw new ConstraintException(
0487:                                "The collection "
0488:                                        + collDef.getName()
0489:                                        + " in class "
0490:                                        + collDef.getOwner().getName()
0491:                                        + " must specify remote-foreignkeys as the class on the other side of the m:n association has no corresponding collection");
0492:                    }
0493:                } else {
0494:                    String remoteKeys2 = remoteCollDef
0495:                            .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0496:
0497:                    if (collDef
0498:                            .hasProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY)) {
0499:                        // check that the specified remote-foreignkey equals the remote foreignkey setting
0500:                        String remoteKeys1 = collDef
0501:                                .getProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY);
0502:
0503:                        if (!CommaListIterator.sameLists(remoteKeys1,
0504:                                remoteKeys2)) {
0505:                            throw new ConstraintException(
0506:                                    "The remote-foreignkey property specified for collection "
0507:                                            + collDef.getName()
0508:                                            + " in class "
0509:                                            + collDef.getOwner().getName()
0510:                                            + " doesn't match the foreignkey property of the corresponding collection "
0511:                                            + remoteCollDef.getName()
0512:                                            + " in class "
0513:                                            + elementClass.getName());
0514:                        }
0515:                    } else {
0516:                        // ensure the remote-foreignkey setting
0517:                        collDef.setProperty(
0518:                                PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY,
0519:                                remoteKeys2);
0520:                    }
0521:                }
0522:
0523:                // issue a warning if the foreignkey and remote-foreignkey columns are the same (issue OJB-67)
0524:                String remoteForeignkey = collDef
0525:                        .getProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY);
0526:
0527:                if (CommaListIterator.sameLists(foreignkey, remoteForeignkey)) {
0528:                    LogHelper
0529:                            .warn(
0530:                                    true,
0531:                                    getClass(),
0532:                                    "checkIndirectionTable",
0533:                                    "The remote foreignkey ("
0534:                                            + remoteForeignkey
0535:                                            + ") for the collection "
0536:                                            + collDef.getName()
0537:                                            + " in class "
0538:                                            + collDef.getOwner().getName()
0539:                                            + " is identical (ignoring case) to the foreign key ("
0540:                                            + foreignkey + ").");
0541:                }
0542:
0543:                // for torque we generate names for the m:n relation that are unique across inheritance
0544:                // but only if we don't have inherited collections
0545:                if (collDef.getOriginal() != null) {
0546:                    CollectionDescriptorDef origDef = (CollectionDescriptorDef) collDef
0547:                            .getOriginal();
0548:                    CollectionDescriptorDef origRemoteDef = origDef
0549:                            .getRemoteCollection();
0550:
0551:                    // we're removing any torque relation name properties from the base collection
0552:                    origDef.setProperty(
0553:                            PropertyHelper.TORQUE_PROPERTY_RELATION_NAME, null);
0554:                    origDef.setProperty(
0555:                            PropertyHelper.TORQUE_PROPERTY_INV_RELATION_NAME,
0556:                            null);
0557:                    if (origRemoteDef != null) {
0558:                        origRemoteDef.setProperty(
0559:                                PropertyHelper.TORQUE_PROPERTY_RELATION_NAME,
0560:                                null);
0561:                        origRemoteDef
0562:                                .setProperty(
0563:                                        PropertyHelper.TORQUE_PROPERTY_INV_RELATION_NAME,
0564:                                        null);
0565:                    }
0566:                } else if (!collDef
0567:                        .hasProperty(PropertyHelper.TORQUE_PROPERTY_RELATION_NAME)) {
0568:                    if (remoteCollDef == null) {
0569:                        collDef.setProperty(
0570:                                PropertyHelper.TORQUE_PROPERTY_RELATION_NAME,
0571:                                collDef.getName());
0572:                        collDef
0573:                                .setProperty(
0574:                                        PropertyHelper.TORQUE_PROPERTY_INV_RELATION_NAME,
0575:                                        "inverse " + collDef.getName());
0576:                    } else {
0577:                        String relName = collDef.getName() + "-"
0578:                                + remoteCollDef.getName();
0579:
0580:                        collDef.setProperty(
0581:                                PropertyHelper.TORQUE_PROPERTY_RELATION_NAME,
0582:                                relName);
0583:                        remoteCollDef
0584:                                .setProperty(
0585:                                        PropertyHelper.TORQUE_PROPERTY_INV_RELATION_NAME,
0586:                                        relName);
0587:
0588:                        relName = remoteCollDef.getName() + "-"
0589:                                + collDef.getName();
0590:
0591:                        collDef
0592:                                .setProperty(
0593:                                        PropertyHelper.TORQUE_PROPERTY_INV_RELATION_NAME,
0594:                                        relName);
0595:                        remoteCollDef.setProperty(
0596:                                PropertyHelper.TORQUE_PROPERTY_RELATION_NAME,
0597:                                relName);
0598:                    }
0599:                }
0600:            }
0601:
0602:            /**
0603:             * Checks the foreignkeys of the collection.
0604:             * 
0605:             * @param modelDef The model
0606:             * @param collDef  The collection descriptor
0607:             * @exception ConstraintException If the value for foreignkey is invalid
0608:             */
0609:            private void checkCollectionForeignkeys(ModelDef modelDef,
0610:                    CollectionDescriptorDef collDef) throws ConstraintException {
0611:                String foreignkey = collDef
0612:                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0613:
0614:                if ((foreignkey == null) || (foreignkey.length() == 0)) {
0615:                    throw new ConstraintException("The collection "
0616:                            + collDef.getName() + " in class "
0617:                            + collDef.getOwner().getName()
0618:                            + " has no foreignkeys");
0619:                }
0620:
0621:                String remoteForeignkey = collDef
0622:                        .getProperty(PropertyHelper.OJB_PROPERTY_REMOTE_FOREIGNKEY);
0623:
0624:                if ((remoteForeignkey != null)
0625:                        && (remoteForeignkey.length() > 0)) {
0626:                    // warning because a remote-foreignkey was specified for a 1:n collection (issue OJB-67)
0627:                    LogHelper
0628:                            .warn(
0629:                                    true,
0630:                                    getClass(),
0631:                                    "checkCollectionForeignkeys",
0632:                                    "For the collection "
0633:                                            + collDef.getName()
0634:                                            + " in class "
0635:                                            + collDef.getOwner().getName()
0636:                                            + ", a remote foreignkey was specified though it is a 1:n, not a m:n collection");
0637:                }
0638:
0639:                ClassDescriptorDef ownerClass = (ClassDescriptorDef) collDef
0640:                        .getOwner();
0641:                ArrayList primFields = ownerClass.getPrimaryKeys();
0642:                String elementClassName = collDef
0643:                        .getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF);
0644:                ArrayList queue = new ArrayList();
0645:                ClassDescriptorDef elementClass;
0646:                ArrayList keyFields;
0647:                FieldDescriptorDef keyField;
0648:                FieldDescriptorDef primField;
0649:                String primType;
0650:                String keyType;
0651:
0652:                // we know that the class is present because the collection constraints have been checked already
0653:                queue.add(modelDef.getClass(elementClassName));
0654:                while (!queue.isEmpty()) {
0655:                    elementClass = (ClassDescriptorDef) queue.get(0);
0656:                    queue.remove(0);
0657:
0658:                    for (Iterator it = elementClass.getExtentClasses(); it
0659:                            .hasNext();) {
0660:                        queue.add(it.next());
0661:                    }
0662:                    if (!elementClass
0663:                            .getBooleanProperty(
0664:                                    PropertyHelper.OJB_PROPERTY_GENERATE_REPOSITORY_INFO,
0665:                                    true)) {
0666:                        continue;
0667:                    }
0668:                    try {
0669:                        keyFields = elementClass.getFields(foreignkey);
0670:                    } catch (NoSuchFieldException ex) {
0671:                        throw new ConstraintException(
0672:                                "The collection "
0673:                                        + collDef.getName()
0674:                                        + " in class "
0675:                                        + collDef.getOwner().getName()
0676:                                        + " specifies a foreignkey "
0677:                                        + ex.getMessage()
0678:                                        + " that is not a persistent field in the element class (or its subclass) "
0679:                                        + elementClass.getName());
0680:                    }
0681:                    if (primFields.size() != keyFields.size()) {
0682:                        throw new ConstraintException(
0683:                                "The number of foreignkeys ("
0684:                                        + keyFields.size()
0685:                                        + ") of the collection "
0686:                                        + collDef.getName()
0687:                                        + " in class "
0688:                                        + collDef.getOwner().getName()
0689:                                        + " doesn't match the number of primarykeys ("
0690:                                        + primFields.size()
0691:                                        + ") of its owner class "
0692:                                        + ownerClass.getName());
0693:                    }
0694:                    for (int idx = 0; idx < keyFields.size(); idx++) {
0695:                        keyField = (FieldDescriptorDef) keyFields.get(idx);
0696:                        if (keyField.getBooleanProperty(
0697:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0698:                            throw new ConstraintException(
0699:                                    "The collection "
0700:                                            + collDef.getName()
0701:                                            + " in class "
0702:                                            + ownerClass.getName()
0703:                                            + " uses the field "
0704:                                            + keyField.getName()
0705:                                            + " as foreignkey although this field is ignored in the element class (or its subclass) "
0706:                                            + elementClass.getName());
0707:                        }
0708:                    }
0709:                    // the jdbc types of the primary keys must match the jdbc types of the foreignkeys (in the correct order)
0710:                    for (int idx = 0; idx < primFields.size(); idx++) {
0711:                        keyField = (FieldDescriptorDef) keyFields.get(idx);
0712:                        if (keyField.getBooleanProperty(
0713:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0714:                            throw new ConstraintException(
0715:                                    "The collection "
0716:                                            + collDef.getName()
0717:                                            + " in class "
0718:                                            + ownerClass.getName()
0719:                                            + " uses the field "
0720:                                            + keyField.getName()
0721:                                            + " as foreignkey although this field is ignored in the element class (or its subclass) "
0722:                                            + elementClass.getName());
0723:                        }
0724:                        primField = (FieldDescriptorDef) primFields.get(idx);
0725:                        primType = primField
0726:                                .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
0727:                        keyType = keyField
0728:                                .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
0729:                        if (!primType.equals(keyType)) {
0730:                            throw new ConstraintException(
0731:                                    "The jdbc-type of foreignkey "
0732:                                            + keyField.getName()
0733:                                            + " in the element class (or its subclass) "
0734:                                            + elementClass.getName()
0735:                                            + " used by the collection "
0736:                                            + collDef.getName()
0737:                                            + " in class "
0738:                                            + ownerClass.getName()
0739:                                            + " doesn't match the jdbc-type of the corresponding primarykey "
0740:                                            + primField.getName());
0741:                        }
0742:                    }
0743:                }
0744:            }
0745:
0746:            /**
0747:             * Checks the foreignkeys of all references in the model.
0748:             * 
0749:             * @param modelDef   The model
0750:             * @param checkLevel The current check level (this constraint is checked in basic and strict)
0751:             * @exception ConstraintException If the value for foreignkey is invalid
0752:             */
0753:            private void checkReferenceForeignkeys(ModelDef modelDef,
0754:                    String checkLevel) throws ConstraintException {
0755:                if (CHECKLEVEL_NONE.equals(checkLevel)) {
0756:                    return;
0757:                }
0758:
0759:                ClassDescriptorDef classDef;
0760:                ReferenceDescriptorDef refDef;
0761:
0762:                for (Iterator it = modelDef.getClasses(); it.hasNext();) {
0763:                    classDef = (ClassDescriptorDef) it.next();
0764:                    for (Iterator refIt = classDef.getReferences(); refIt
0765:                            .hasNext();) {
0766:                        refDef = (ReferenceDescriptorDef) refIt.next();
0767:                        if (!refDef.getBooleanProperty(
0768:                                PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0769:                            checkReferenceForeignkeys(modelDef, refDef);
0770:                        }
0771:                    }
0772:                }
0773:            }
0774:
0775:            /**
0776:             * Checks the foreignkeys of a reference.
0777:             * 
0778:             * @param modelDef The model
0779:             * @param refDef   The reference descriptor
0780:             * @exception ConstraintException If the value for foreignkey is invalid
0781:             */
0782:            private void checkReferenceForeignkeys(ModelDef modelDef,
0783:                    ReferenceDescriptorDef refDef) throws ConstraintException {
0784:                String foreignkey = refDef
0785:                        .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
0786:
0787:                if ((foreignkey == null) || (foreignkey.length() == 0)) {
0788:                    throw new ConstraintException("The reference "
0789:                            + refDef.getName() + " in class "
0790:                            + refDef.getOwner().getName()
0791:                            + " has no foreignkeys");
0792:                }
0793:
0794:                // we know that the class is present because the reference constraints have been checked already
0795:                ClassDescriptorDef ownerClass = (ClassDescriptorDef) refDef
0796:                        .getOwner();
0797:                ArrayList keyFields;
0798:                FieldDescriptorDef keyField;
0799:
0800:                try {
0801:                    keyFields = ownerClass.getFields(foreignkey);
0802:                } catch (NoSuchFieldException ex) {
0803:                    throw new ConstraintException(
0804:                            "The reference "
0805:                                    + refDef.getName()
0806:                                    + " in class "
0807:                                    + refDef.getOwner().getName()
0808:                                    + " specifies a foreignkey "
0809:                                    + ex.getMessage()
0810:                                    + " that is not a persistent field in its owner class "
0811:                                    + ownerClass.getName());
0812:                }
0813:                for (int idx = 0; idx < keyFields.size(); idx++) {
0814:                    keyField = (FieldDescriptorDef) keyFields.get(idx);
0815:                    if (keyField.getBooleanProperty(
0816:                            PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0817:                        throw new ConstraintException(
0818:                                "The reference "
0819:                                        + refDef.getName()
0820:                                        + " in class "
0821:                                        + ownerClass.getName()
0822:                                        + " uses the field "
0823:                                        + keyField.getName()
0824:                                        + " as foreignkey although this field is ignored in this class");
0825:                    }
0826:                }
0827:
0828:                // for the referenced class and any subtype that is instantiable (i.e. not an interface or abstract class)
0829:                // there must be the same number of primary keys and the jdbc types of the primary keys must
0830:                // match the jdbc types of the foreignkeys (in the correct order)
0831:                String targetClassName = refDef
0832:                        .getProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF);
0833:                ArrayList queue = new ArrayList();
0834:                ClassDescriptorDef referencedClass;
0835:                ArrayList primFields;
0836:                FieldDescriptorDef primField;
0837:                String primType;
0838:                String keyType;
0839:
0840:                queue.add(modelDef.getClass(targetClassName));
0841:
0842:                while (!queue.isEmpty()) {
0843:                    referencedClass = (ClassDescriptorDef) queue.get(0);
0844:                    queue.remove(0);
0845:
0846:                    for (Iterator it = referencedClass.getExtentClasses(); it
0847:                            .hasNext();) {
0848:                        queue.add(it.next());
0849:                    }
0850:                    if (!referencedClass
0851:                            .getBooleanProperty(
0852:                                    PropertyHelper.OJB_PROPERTY_GENERATE_REPOSITORY_INFO,
0853:                                    true)) {
0854:                        continue;
0855:                    }
0856:                    primFields = referencedClass.getPrimaryKeys();
0857:                    if (primFields.size() != keyFields.size()) {
0858:                        throw new ConstraintException(
0859:                                "The number of foreignkeys ("
0860:                                        + keyFields.size()
0861:                                        + ") of the reference "
0862:                                        + refDef.getName()
0863:                                        + " in class "
0864:                                        + refDef.getOwner().getName()
0865:                                        + " doesn't match the number of primarykeys ("
0866:                                        + primFields.size()
0867:                                        + ") of the referenced class (or its subclass) "
0868:                                        + referencedClass.getName());
0869:                    }
0870:                    for (int idx = 0; idx < primFields.size(); idx++) {
0871:                        keyField = (FieldDescriptorDef) keyFields.get(idx);
0872:                        primField = (FieldDescriptorDef) primFields.get(idx);
0873:                        primType = primField
0874:                                .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
0875:                        keyType = keyField
0876:                                .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
0877:                        if (!primType.equals(keyType)) {
0878:                            throw new ConstraintException(
0879:                                    "The jdbc-type of foreignkey "
0880:                                            + keyField.getName()
0881:                                            + " of the reference "
0882:                                            + refDef.getName()
0883:                                            + " in class "
0884:                                            + refDef.getOwner().getName()
0885:                                            + " doesn't match the jdbc-type of the corresponding primarykey "
0886:                                            + primField.getName()
0887:                                            + " of the referenced class (or its subclass) "
0888:                                            + referencedClass.getName());
0889:                        }
0890:                    }
0891:                }
0892:            }
0893:
0894:            /**
0895:             * Checks the modifications of fields used as foreignkeys in references/collections or the corresponding primarykeys,
0896:             * e.g. that the jdbc-type is not changed etc.
0897:             * 
0898:             * @param modelDef   The model to check
0899:             * @param checkLevel The current check level (this constraint is checked in basic and strict)
0900:             * @throws ConstraintException If such a field has invalid modifications
0901:             */
0902:            private void checkKeyModifications(ModelDef modelDef,
0903:                    String checkLevel) throws ConstraintException {
0904:                if (CHECKLEVEL_NONE.equals(checkLevel)) {
0905:                    return;
0906:                }
0907:
0908:                ClassDescriptorDef classDef;
0909:                FieldDescriptorDef fieldDef;
0910:
0911:                // we check for every inherited field
0912:                for (Iterator classIt = modelDef.getClasses(); classIt
0913:                        .hasNext();) {
0914:                    classDef = (ClassDescriptorDef) classIt.next();
0915:                    for (Iterator fieldIt = classDef.getFields(); fieldIt
0916:                            .hasNext();) {
0917:                        fieldDef = (FieldDescriptorDef) fieldIt.next();
0918:                        if (fieldDef.isInherited()) {
0919:                            checkKeyModifications(modelDef, fieldDef);
0920:                        }
0921:                    }
0922:                }
0923:            }
0924:
0925:            /**
0926:             * Checks the modifications of the given inherited field if it is used as a foreignkey in a
0927:             * reference/collection or as the corresponding primarykey, e.g. that the jdbc-type is not changed etc.
0928:             * 
0929:             * @param modelDef The model to check
0930:             * @throws ConstraintException If the field has invalid modifications
0931:             */
0932:            private void checkKeyModifications(ModelDef modelDef,
0933:                    FieldDescriptorDef keyDef) throws ConstraintException {
0934:                // we check the field if it changes the primarykey-status or the jdbc-type
0935:                FieldDescriptorDef baseFieldDef = (FieldDescriptorDef) keyDef
0936:                        .getOriginal();
0937:                boolean isIgnored = keyDef.getBooleanProperty(
0938:                        PropertyHelper.OJB_PROPERTY_IGNORE, false);
0939:                boolean changesJdbcType = !baseFieldDef
0940:                        .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE)
0941:                        .equals(
0942:                                keyDef
0943:                                        .getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE));
0944:                boolean changesPrimary = baseFieldDef.getBooleanProperty(
0945:                        PropertyHelper.OJB_PROPERTY_PRIMARYKEY, false) != keyDef
0946:                        .getBooleanProperty(
0947:                                PropertyHelper.OJB_PROPERTY_PRIMARYKEY, false);
0948:
0949:                if (isIgnored || changesJdbcType || changesPrimary) {
0950:                    FeatureDescriptorDef usingFeature = null;
0951:
0952:                    do {
0953:                        usingFeature = usedByReference(modelDef, baseFieldDef);
0954:                        if (usingFeature != null) {
0955:                            if (isIgnored) {
0956:                                throw new ConstraintException(
0957:                                        "Cannot ignore field "
0958:                                                + keyDef.getName()
0959:                                                + " in class "
0960:                                                + keyDef.getOwner().getName()
0961:                                                + " because it is used in class "
0962:                                                + baseFieldDef.getOwner()
0963:                                                        .getName()
0964:                                                + " by the reference "
0965:                                                + usingFeature.getName()
0966:                                                + " from class "
0967:                                                + usingFeature.getOwner()
0968:                                                        .getName());
0969:                            } else if (changesJdbcType) {
0970:                                throw new ConstraintException(
0971:                                        "Modification of the jdbc-type for the field "
0972:                                                + keyDef.getName()
0973:                                                + " in class "
0974:                                                + keyDef.getOwner().getName()
0975:                                                + " is not allowed because it is used in class "
0976:                                                + baseFieldDef.getOwner()
0977:                                                        .getName()
0978:                                                + " by the reference "
0979:                                                + usingFeature.getName()
0980:                                                + " from class "
0981:                                                + usingFeature.getOwner()
0982:                                                        .getName());
0983:                            } else {
0984:                                throw new ConstraintException(
0985:                                        "Cannot change the primarykey status of field "
0986:                                                + keyDef.getName()
0987:                                                + " in class "
0988:                                                + keyDef.getOwner().getName()
0989:                                                + " as primarykeys are used in class "
0990:                                                + baseFieldDef.getOwner()
0991:                                                        .getName()
0992:                                                + " by the reference "
0993:                                                + usingFeature.getName()
0994:                                                + " from class "
0995:                                                + usingFeature.getOwner()
0996:                                                        .getName());
0997:                            }
0998:                        }
0999:
1000:                        usingFeature = usedByCollection(modelDef, baseFieldDef,
1001:                                changesPrimary);
1002:                        if (usingFeature != null) {
1003:                            if (isIgnored) {
1004:                                throw new ConstraintException(
1005:                                        "Cannot ignore field "
1006:                                                + keyDef.getName()
1007:                                                + " in class "
1008:                                                + keyDef.getOwner().getName()
1009:                                                + " because it is used in class "
1010:                                                + baseFieldDef.getOwner()
1011:                                                        .getName()
1012:                                                + " as a foreignkey of the collection "
1013:                                                + usingFeature.getName()
1014:                                                + " from class "
1015:                                                + usingFeature.getOwner()
1016:                                                        .getName());
1017:                            } else if (changesJdbcType) {
1018:                                throw new ConstraintException(
1019:                                        "Modification of the jdbc-type for the field "
1020:                                                + keyDef.getName()
1021:                                                + " in class "
1022:                                                + keyDef.getOwner().getName()
1023:                                                + " is not allowed because it is used in class "
1024:                                                + baseFieldDef.getOwner()
1025:                                                        .getName()
1026:                                                + " as a foreignkey of the collecton "
1027:                                                + usingFeature.getName()
1028:                                                + " from class "
1029:                                                + usingFeature.getOwner()
1030:                                                        .getName());
1031:                            } else {
1032:                                throw new ConstraintException(
1033:                                        "Cannot change the primarykey status of field "
1034:                                                + keyDef.getName()
1035:                                                + " in class "
1036:                                                + keyDef.getOwner().getName()
1037:                                                + " as primarykeys are used in class "
1038:                                                + baseFieldDef.getOwner()
1039:                                                        .getName()
1040:                                                + " by the collection "
1041:                                                + usingFeature.getName()
1042:                                                + " from class "
1043:                                                + usingFeature.getOwner()
1044:                                                        .getName());
1045:                            }
1046:                        }
1047:
1048:                        baseFieldDef = (FieldDescriptorDef) baseFieldDef
1049:                                .getOriginal();
1050:                    } while (baseFieldDef != null);
1051:                }
1052:            }
1053:
1054:            /**
1055:             * Checks whether the given field definition is used as a remote-foreignkey in an m:n
1056:             * association where the class owning the field has no collection for the association.
1057:             * 
1058:             * @param modelDef             The model
1059:             * @param fieldDef             The current field descriptor def
1060:             * @param elementClassSuffices Whether it suffices that the owner class of the field is an
1061:             *                             element class of a collection (for primary key tests)
1062:             * @return The collection that uses the field or <code>null</code> if the field is not
1063:             *         used in this way
1064:             */
1065:            private CollectionDescriptorDef usedByCollection(ModelDef modelDef,
1066:                    FieldDescriptorDef fieldDef, boolean elementClassSuffices) {
1067:                ClassDescriptorDef ownerClass = (ClassDescriptorDef) fieldDef
1068:                        .getOwner();
1069:                String ownerClassName = ownerClass.getQualifiedName();
1070:                String name = fieldDef.getName();
1071:                ClassDescriptorDef classDef;
1072:                CollectionDescriptorDef collDef;
1073:                String elementClassName;
1074:
1075:                for (Iterator classIt = modelDef.getClasses(); classIt
1076:                        .hasNext();) {
1077:                    classDef = (ClassDescriptorDef) classIt.next();
1078:                    for (Iterator collIt = classDef.getCollections(); collIt
1079:                            .hasNext();) {
1080:                        collDef = (CollectionDescriptorDef) collIt.next();
1081:                        elementClassName = collDef.getProperty(
1082:                                PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF)
1083:                                .replace('$', '.');
1084:                        // if the owner class of the field is the element class of a normal collection
1085:                        // and the field is a foreignkey of this collection
1086:                        if (ownerClassName.equals(elementClassName)) {
1087:                            if (collDef
1088:                                    .hasProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE)) {
1089:                                if (elementClassSuffices) {
1090:                                    return collDef;
1091:                                }
1092:                            } else if (new CommaListIterator(
1093:                                    collDef
1094:                                            .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY))
1095:                                    .contains(name)) {
1096:                                // if the field is a foreignkey of this normal 1:n collection
1097:                                return collDef;
1098:                            }
1099:                        }
1100:                    }
1101:                }
1102:                return null;
1103:            }
1104:
1105:            /**
1106:             * Checks whether the given field definition is used as the primary key of a class referenced by
1107:             * a reference.
1108:             * 
1109:             * @param modelDef The model
1110:             * @param fieldDef The current field descriptor def
1111:             * @return The reference that uses the field or <code>null</code> if the field is not used in this way
1112:             */
1113:            private ReferenceDescriptorDef usedByReference(ModelDef modelDef,
1114:                    FieldDescriptorDef fieldDef) {
1115:                String ownerClassName = ((ClassDescriptorDef) fieldDef
1116:                        .getOwner()).getQualifiedName();
1117:                ClassDescriptorDef classDef;
1118:                ReferenceDescriptorDef refDef;
1119:                String targetClassName;
1120:
1121:                // only relevant for primarykey fields
1122:                if (PropertyHelper.toBoolean(fieldDef
1123:                        .getProperty(PropertyHelper.OJB_PROPERTY_PRIMARYKEY),
1124:                        false)) {
1125:                    for (Iterator classIt = modelDef.getClasses(); classIt
1126:                            .hasNext();) {
1127:                        classDef = (ClassDescriptorDef) classIt.next();
1128:                        for (Iterator refIt = classDef.getReferences(); refIt
1129:                                .hasNext();) {
1130:                            refDef = (ReferenceDescriptorDef) refIt.next();
1131:                            targetClassName = refDef.getProperty(
1132:                                    PropertyHelper.OJB_PROPERTY_CLASS_REF)
1133:                                    .replace('$', '.');
1134:                            if (ownerClassName.equals(targetClassName)) {
1135:                                // the field is a primary key of the class referenced by this reference descriptor
1136:                                return refDef;
1137:                            }
1138:                        }
1139:                    }
1140:                }
1141:                return null;
1142:            }
1143:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.