Source Code Cross Referenced for ORMappingGenerator.java in  » Database-ORM » Speedo_1.4.5 » org » objectweb » speedo » generation » mivisitor » 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 » Speedo_1.4.5 » org.objectweb.speedo.generation.mivisitor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Copyright (C) 2001-2004 France Telecom R&D
0003:         *
0004:         * This library is free software; you can redistribute it and/or
0005:         * modify it under the terms of the GNU Lesser General Public
0006:         * License as published by the Free Software Foundation; either
0007:         * version 2 of the License, or (at your option) any later version.
0008:         *
0009:         * This library is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012:         * Lesser General Public License for more details.
0013:         *
0014:         * You should have received a copy of the GNU Lesser General Public
0015:         * License along with this library; if not, write to the Free Software
0016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:         */package org.objectweb.speedo.generation.mivisitor;
0018:
0019:        import java.util.ArrayList;
0020:        import java.util.Arrays;
0021:        import java.util.Collection;
0022:        import java.util.Collections;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:        import java.util.StringTokenizer;
0028:
0029:        import org.objectweb.speedo.api.SpeedoException;
0030:        import org.objectweb.speedo.api.SpeedoProperties;
0031:        import org.objectweb.speedo.generation.lib.AbstractGeneratorComponent;
0032:        import org.objectweb.speedo.lib.Personality;
0033:        import org.objectweb.speedo.metadata.SpeedoClass;
0034:        import org.objectweb.speedo.metadata.SpeedoCollection;
0035:        import org.objectweb.speedo.metadata.SpeedoColumn;
0036:        import org.objectweb.speedo.metadata.SpeedoCommonField;
0037:        import org.objectweb.speedo.metadata.SpeedoDiscriminator;
0038:        import org.objectweb.speedo.metadata.SpeedoField;
0039:        import org.objectweb.speedo.metadata.SpeedoInheritance;
0040:        import org.objectweb.speedo.metadata.SpeedoInheritedField;
0041:        import org.objectweb.speedo.metadata.SpeedoJoin;
0042:        import org.objectweb.speedo.metadata.SpeedoJoinColumn;
0043:        import org.objectweb.speedo.metadata.SpeedoMap;
0044:        import org.objectweb.speedo.metadata.SpeedoPackage;
0045:        import org.objectweb.speedo.metadata.SpeedoTable;
0046:        import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
0047:        import org.objectweb.speedo.naming.api.NamingManager;
0048:        import org.objectweb.util.monolog.api.BasicLevel;
0049:
0050:        /**
0051:         * This Speedo Meta information visitor builds and fills the Speedo Meta 
0052:         * information concerning the OR mapping information. It defines a SpeedoTable,
0053:         * SpeedoColumn, SpeedoJoin where it is required.
0054:         * This SMI visitor cannot be inclued with other SMI visitor. Indeed it requires
0055:         * that all meta information is complete (for all classes). In particular it 
0056:         * needs the result of the Class analyser visitor. For this reason this SMI 
0057:         * visitor is a simple GeneratorComponent to use when SMI is complete.
0058:         * In addition, due to dependency between classes (relation ship, inheritance)
0059:         * the visit of classes must be done in a particular order. For these reasons,
0060:         * this Visitor visits the SMI with a help of two internal classes (
0061:         * VisitRequired and VisitRemeber).  
0062:         * 
0063:         * @author S.Chassande-Barrioz
0064:         */
0065:        public class ORMappingGenerator extends AbstractGeneratorComponent {
0066:            /**
0067:             * This class represents required element to be visited in a persistent 
0068:             * class.
0069:             *
0070:             * @author S.Chassande-Barrioz
0071:             */
0072:            public static class VisitRequired {
0073:                /**
0074:                 * constant representing a visit of nothing
0075:                 */
0076:                public final static VisitRequired NOTHING = new VisitRequired(
0077:                        false, false, null);
0078:                /**
0079:                 * constant representing a visit of all elements of a persistent class
0080:                 */
0081:                public final static VisitRequired ALL = new VisitRequired(true,
0082:                        true, null);
0083:                /**
0084:                 * constant representing a visit of base element of a persistent class
0085:                 */
0086:                public final static VisitRequired BASE = new VisitRequired(
0087:                        true, false, null);
0088:
0089:                /**
0090:                 * indicates if the base must be visited. The base represents:
0091:                 * - the table of the persistent class
0092:                 * - the identifier of the persistent class
0093:                 * - the primitivie fields of the persistent class
0094:                 */
0095:                public boolean base = false;
0096:                /**
0097:                 * Indicates if all references must be visisted (ClassRef 
0098:                 * and GenClassRef)
0099:                 */
0100:                public boolean references = false;
0101:                /**
0102:                 * indicates if the visit of a particular reference field is required.
0103:                 * It is often used in case of bi directional relationship with one side
0104:                 * of the relation mmped by the other one.
0105:                 */
0106:                public SpeedoField refField = null;
0107:
0108:                /**
0109:                 * Builds a new VisitRequired instance including the base elements and
0110:                 * a particular reference field.
0111:                 * @param refField the field to visit
0112:                 */
0113:                public VisitRequired(SpeedoField refField) {
0114:                    this .base = true;
0115:                    this .references = false;
0116:                    this .refField = refField;
0117:                }
0118:
0119:                /**
0120:                 * Private constructor for static constant only.
0121:                 */
0122:                private VisitRequired(boolean base, boolean references,
0123:                        SpeedoField refField) {
0124:                    this .base = base;
0125:                    this .references = references;
0126:                    this .refField = refField;
0127:                }
0128:
0129:                /**
0130:                 * Prints a string representing the current instance.
0131:                 */
0132:                public String toString() {
0133:                    if (base) {
0134:                        if (references) {
0135:                            return "ALL";
0136:                        } else if (refField == null) {
0137:                            return "BASE";
0138:                        } else {
0139:                            return "BASE, " + refField.name;
0140:                        }
0141:                    } else {
0142:                        return "NOTHING";
0143:                    }
0144:                }
0145:            }
0146:
0147:            /**
0148:             * This class represents the status of visited/treated elements of a
0149:             * persistent class.
0150:             *
0151:             * @author S.Chassande-Barrioz
0152:             */
0153:            public static class VisitRemember {
0154:                /**
0155:                 * The persistent class
0156:                 */
0157:                private SpeedoClass sc;
0158:                /**
0159:                 * indicates if the base elements have been visited:
0160:                 * - the table of the persistent class
0161:                 * - the identifier of the persistent class
0162:                 * - the primitivie fields of the persistent class
0163:                 */
0164:                private boolean baseVisited = false;
0165:                /**
0166:                 * Indicates if inherited fields have been visited.
0167:                 */
0168:                private boolean inheritedFieldsVisited = false;
0169:                /**
0170:                 * the list primitive fields of the persistent class
0171:                 * The content of the list is SpeedoField instances.
0172:                 */
0173:                public List primitiveFields = new ArrayList();
0174:                /**
0175:                 * the list reference fields of the persistent class (class reference
0176:                 * and generic class reference)
0177:                 * The content of the list is SpeedoField instances.
0178:                 */
0179:                public List references = new ArrayList();
0180:                /**
0181:                 * The list of reference fields already visisted.
0182:                 */
0183:                private List visitedReferencesFields = new ArrayList();
0184:
0185:                /**
0186:                 * Builds a new instance for a persistent class. This constructor fills
0187:                 * the list of persistent fields.
0188:                 */
0189:                public VisitRemember(SpeedoClass c) {
0190:                    sc = c;
0191:                    for (Iterator fieldIt = sc.fields.values().iterator(); fieldIt
0192:                            .hasNext();) {
0193:                        SpeedoField sf = (SpeedoField) fieldIt.next();
0194:                        if (sf.jdoTuple != null) {
0195:                            references.add(sf);
0196:                        } else {
0197:                            SpeedoClass rclass = sf.getReferencedClass();
0198:                            if (rclass == null) {
0199:                                primitiveFields.add(sf);
0200:                            } else {
0201:                                references.add(sf);
0202:                            }
0203:                        }
0204:                    }
0205:                }
0206:
0207:                /**
0208:                 * Print the status of the class visit
0209:                 */
0210:                public String toString() {
0211:                    if (baseVisited) {
0212:                        int nbref = references.size();
0213:                        int visitedref = visitedReferencesFields.size();
0214:                        if (nbref == visitedref) {
0215:                            return "ALL";
0216:                        } else if (visitedref == 0) {
0217:                            return "BASE";
0218:                        } else {
0219:                            StringBuffer sb = new StringBuffer();
0220:                            sb.append("BASE");
0221:                            for (Iterator it = visitedReferencesFields
0222:                                    .iterator(); it.hasNext();) {
0223:                                SpeedoField sf = (SpeedoField) it.next();
0224:                                sb.append(", ").append(sf.name);
0225:                            }
0226:                            return sb.toString();
0227:                        }
0228:                    } else {
0229:                        return "NOTHING";
0230:                    }
0231:                }
0232:
0233:                /**
0234:                 * Indicates if some elements specified by the VisitRequired parameter
0235:                 * have not been already visited. 
0236:                 */
0237:                public boolean hasUnvisitedPart(VisitRequired req) {
0238:                    if (req.base && !baseVisited) {
0239:                        return true;
0240:                    }
0241:                    if (req.references
0242:                            && references.size() > visitedReferencesFields
0243:                                    .size()) {
0244:                        return true;
0245:                    }
0246:                    if (req.refField != null
0247:                            && !visitedReferencesFields.contains(req.refField)) {
0248:                        return true;
0249:                    }
0250:                    if (req.references && !inheritedFieldsVisited) {
0251:                        return true;
0252:                    }
0253:                    return false;
0254:                }
0255:
0256:                /**
0257:                 * Indicates if the base must be visited according to the parameter
0258:                 * and the current status.
0259:                 */
0260:                public boolean visitBase(VisitRequired vr) {
0261:                    return vr.base && !baseVisited;
0262:                }
0263:
0264:                /**
0265:                 * Callback method to indicate that the base elements have been visited.
0266:                 */
0267:                public void baseVisited() {
0268:                    baseVisited = true;
0269:                }
0270:
0271:                /**
0272:                 * Indicates if one or several reference fields must be visited 
0273:                 * according to the parameter and the current status.
0274:                 */
0275:                public boolean visitReferences(VisitRequired vr) {
0276:                    return (vr.references || vr.refField != null)
0277:                            && references.size() > visitedReferencesFields
0278:                                    .size();
0279:                }
0280:
0281:                /**
0282:                 * Callback method to indicate that a reference field has been visited.
0283:                 */
0284:                public boolean visitReferenceField(SpeedoField sf,
0285:                        VisitRequired vr) {
0286:                    return (vr.references || vr.refField == sf)
0287:                            && !visitedReferencesFields.contains(sf);
0288:                }
0289:
0290:                /**
0291:                 * Callback method to indicate that a reference field has been visited.
0292:                 */
0293:                public void referenceFieldVisisted(SpeedoField sf) {
0294:                    visitedReferencesFields.add(sf);
0295:                }
0296:
0297:                /**
0298:                 * Indicates if inherited fields must be visited 
0299:                 * according to the parameter and the current status.
0300:                 */
0301:                public boolean visitInheritedFields(VisitRequired vr) {
0302:                    return vr.references && !inheritedFieldsVisited;
0303:                }
0304:
0305:                /**
0306:                 * Callback method to indicate that inherited fields have been visited.
0307:                 */
0308:                public void inheritedFieldsVisited() {
0309:                    inheritedFieldsVisited = true;
0310:                }
0311:            }
0312:
0313:            /**
0314:             * is the map of visited classes (partialy of totaly)
0315:             * key = fully qualified persistent class name
0316:             * value = VisitRemener instance 
0317:             */
0318:            private HashMap visitedClasses = new HashMap();
0319:            public final static String LOGGER_NAME = SpeedoProperties.LOGGER_NAME
0320:                    + ".generation.orm";
0321:
0322:            public ORMappingGenerator(Personality p) {
0323:                super (p);
0324:            }
0325:
0326:            public String getTitle() {
0327:                return "Auto O/R Mapping...";
0328:            }
0329:
0330:            protected String getLoggerName() {
0331:                return LOGGER_NAME;
0332:            }
0333:
0334:            public boolean init() throws SpeedoException {
0335:                visitedClasses.clear();
0336:                logger = scp.loggerFactory.getLogger(getLoggerName());
0337:                debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
0338:                return !scp.getXmldescriptor().isEmpty();
0339:            }
0340:
0341:            public void process() throws SpeedoException {
0342:                visitedClasses.clear();
0343:                for (Iterator xmlIt = scp.smi.xmlDescriptors.values()
0344:                        .iterator(); xmlIt.hasNext();) {
0345:                    SpeedoXMLDescriptor xml = (SpeedoXMLDescriptor) xmlIt
0346:                            .next();
0347:                    for (Iterator packIt = xml.packages.values().iterator(); packIt
0348:                            .hasNext();) {
0349:                        SpeedoPackage sp = (SpeedoPackage) packIt.next();
0350:                        for (Iterator classIt = sp.classes.values().iterator(); classIt
0351:                                .hasNext();) {
0352:                            SpeedoClass sc = (SpeedoClass) classIt.next();
0353:                            visitSpeedoClass(sc, VisitRequired.ALL);
0354:                        }
0355:                    }
0356:                }
0357:                visitedClasses.clear();
0358:            }
0359:
0360:            /**
0361:             * Visits a SpeedoClass.
0362:             * @param sc the class to visit
0363:             * @param toVisit
0364:             * @throws SpeedoException
0365:             */
0366:            private void visitSpeedoClass(SpeedoClass sc, VisitRequired toVisit)
0367:                    throws SpeedoException {
0368:                logger.log(BasicLevel.DEBUG, "* visit class '" + sc.getFQName()
0369:                        + "', " + toVisit + ".");
0370:                VisitRemember vr = (VisitRemember) visitedClasses.get(sc);
0371:                if (vr == null) {
0372:                    vr = new VisitRemember(sc);
0373:                    visitedClasses.put(sc, vr);
0374:                } else if (!vr.hasUnvisitedPart(toVisit)) {
0375:                    logger.log(BasicLevel.DEBUG, "\t=> already visited: " + vr
0376:                            + ".");
0377:                    return;
0378:                }
0379:                if (vr.visitBase(toVisit)) {
0380:                    logger.log(BasicLevel.DEBUG, "\tvisit base.");
0381:                    //visit parents first
0382:                    visitClassParent(sc, toVisit);
0383:                    //visit inheritance strategy
0384:                    visitClassInheritanceStrategy(sc);
0385:                    //visit table of the persistent class
0386:                    visitClassTable(sc);
0387:                    //visit identity column of the persistent class
0388:                    visitIdentityColumn(sc);
0389:                    //visit secondary tables (not the join associated)
0390:                    if (sc.joinToExtTables != null) {
0391:                        for (int i = 0; i < sc.joinToExtTables.length; i++) {
0392:                            SpeedoJoin join = sc.joinToExtTables[i];
0393:                            if (join.mainTable == null) {
0394:                                join.mainTable = sc.mainTable;
0395:                            }
0396:                            if (join.extTable == null) {
0397:                                join.extTable = new SpeedoTable();
0398:                                allocateTableName(sc, join.extTable);
0399:                            }
0400:                        }
0401:                    }
0402:                    //visit primitive Fields first because it can contain the pk fields used
0403:                    // for classRef or genClassRef
0404:                    //visit primitive fields (including pk fields)
0405:                    for (Iterator fieldIt = vr.primitiveFields.iterator(); fieldIt
0406:                            .hasNext();) {
0407:                        SpeedoField sf = (SpeedoField) fieldIt.next();
0408:                        visitPrimitiveField(sf);
0409:                    }
0410:                    if (sc.joinToExtTables != null) {
0411:                        for (int i = 0; i < sc.joinToExtTables.length; i++) {
0412:                            visitJoinOfSecondaryTable(sc.joinToExtTables[i], sc);
0413:                        }
0414:                    }
0415:                    vr.baseVisited();
0416:                }
0417:                if (vr.visitReferences(toVisit)) {
0418:                    logger.log(BasicLevel.DEBUG, "\tvisit reference fields:");
0419:
0420:                    //visit references fields
0421:                    for (Iterator fieldIt = vr.references.iterator(); fieldIt
0422:                            .hasNext();) {
0423:                        SpeedoField sf = (SpeedoField) fieldIt.next();
0424:                        if (vr.visitReferenceField(sf, toVisit)) {
0425:                            if (sf.jdoTuple == null) {
0426:                                visitClassRefField(sf);
0427:                            } else {
0428:                                visitGenClassRefField(sf);
0429:                            }
0430:                            vr.referenceFieldVisisted(sf);
0431:                        }
0432:                    }
0433:                }
0434:                if (vr.visitInheritedFields(toVisit)) {
0435:                    visitClassInheritance(sc);
0436:                    vr.inheritedFieldsVisited();
0437:                }
0438:                logger.log(BasicLevel.DEBUG, "End of visit class '"
0439:                        + sc.getFQName() + "', " + toVisit + ".");
0440:            }
0441:
0442:            private void visitJoinOfSecondaryTable(SpeedoJoin join,
0443:                    SpeedoClass sc) throws SpeedoException {
0444:                logger.log(BasicLevel.DEBUG,
0445:                        "\t\tvisit join to the secondary table '"
0446:                                + join.extTable.name + "'.");
0447:                if (join.columns.isEmpty()) {
0448:                    //create new JoinColumn to the pk column of the class
0449:                    join.columns.addAll(getFKJoinColumn(sc, "FK_",
0450:                            join.extTable));
0451:                } else {
0452:                    int size = join.columns.size();
0453:                    for (Iterator it = join.columns.iterator(); it.hasNext();) {
0454:                        SpeedoJoinColumn jc = (SpeedoJoinColumn) it.next();
0455:                        if (jc.targetColumn == null) {
0456:                            if (jc.targetField == null) {
0457:                                if (size == 1) {
0458:                                    SpeedoColumn[] cols = getIdColumns(sc);
0459:                                    if (cols.length > 1) {
0460:                                        throw new SpeedoException(
0461:                                                "The join to the '"
0462:                                                        + join.extTable.name
0463:                                                        + "' secondary table has not targetColumn defined and there is several identifier column in the "
0464:                                                        + sc.getSourceDesc());
0465:                                    }
0466:                                    jc.targetColumn = cols[0].name;
0467:                                    logger.log(BasicLevel.DEBUG,
0468:                                            "\t\tset the target column from the unique PK column: "
0469:                                                    + jc.targetColumn);
0470:                                } else {
0471:                                    throw new SpeedoException(
0472:                                            "The join columns to the '"
0473:                                                    + join.extTable.name
0474:                                                    + "' secondary table have not targetColumn defined in the "
0475:                                                    + sc.getSourceDesc());
0476:                                }
0477:                            } else {
0478:                                //find the column of the target field
0479:                                SpeedoField sf = sc.getField(jc.targetField);
0480:                                if (sf == null) {
0481:                                    throw new SpeedoException(
0482:                                            "Targeted field '"
0483:                                                    + jc.targetField
0484:                                                    + "' in the "
0485:                                                    + sc.getSourceDesc()
0486:                                                    + ". It is defined in the join to the secondary table '"
0487:                                                    + join.extTable.name + "'.");
0488:                                }
0489:                                if (sf.columns == null
0490:                                        || sf.columns.length != 1) {
0491:                                    throw new SpeedoException(
0492:                                            "In join column, target field must be a primitive field: "
0493:                                                    + sf.getSourceDesc()
0494:                                                    + ". It is defined in the join to the secondary table '"
0495:                                                    + join.extTable.name + "'.");
0496:                                }
0497:                                jc.targetColumn = sf.columns[0].name;
0498:                            }
0499:                        }
0500:                    }
0501:                }
0502:            }
0503:
0504:            /**
0505:             * Visits parent persistent class starting with the root class.
0506:             * @param sc the Speedoclass to visit.
0507:             * @param toVisit
0508:             * @throws SpeedoException
0509:             */
0510:            private void visitClassParent(SpeedoClass sc, VisitRequired toVisit)
0511:                    throws SpeedoException {
0512:
0513:                //find all not visited parents
0514:                List parents = new ArrayList();
0515:                SpeedoClass parent = sc.getSuper();
0516:                while (parent != null) {
0517:                    VisitRemember vr = (VisitRemember) visitedClasses
0518:                            .get(parent);
0519:                    if (vr == null || vr.hasUnvisitedPart(toVisit)) {
0520:                        //Add in first 
0521:                        parents.add(0, parent);
0522:                        parent = parent.getSuper();
0523:                    } else {
0524:                        //if a parent is visited all super parents are visited too
0525:                        parent = null;
0526:                    }
0527:                }
0528:                //visit parents
0529:                for (Iterator it = parents.iterator(); it.hasNext();) {
0530:                    logger.log(BasicLevel.DEBUG, "\tvisit parent of "
0531:                            + sc.getFQName());
0532:                    visitSpeedoClass((SpeedoClass) it.next(), toVisit);
0533:                }
0534:            }
0535:
0536:            /**
0537:             * Set inheritance strategy when it is not defined. 
0538:             */
0539:            private void visitClassInheritanceStrategy(SpeedoClass sc)
0540:                    throws SpeedoException {
0541:                //assign default inheritance strategy
0542:                if (sc.inheritance != null
0543:                        && sc.inheritance.super ClassName != null
0544:                        && sc.inheritance.strategy == SpeedoInheritance.STRATEGY_UNKOWN) {
0545:                    if (sc.mainTable == null) {
0546:                        //no table defined
0547:                        if (sc.inheritance.join == null) {
0548:                            //no join ==> choose filtered
0549:                            sc.inheritance.strategy = SpeedoInheritance.STRATEGY_SUPERCLASS_TABLE;
0550:                        } else {
0551:                            //there is a join ==> it means vertical
0552:                            sc.inheritance.strategy = SpeedoInheritance.STRATEGY_NEW_TABLE;
0553:                        }
0554:                    } else {
0555:                        // there is a table. It means horizontal or vertical 
0556:                        // either there is a join
0557:                        sc.inheritance.strategy = SpeedoInheritance.STRATEGY_NEW_TABLE;
0558:                    }
0559:                }
0560:            }
0561:
0562:            /**
0563:             * Computes the main table according to the inheritance strategy.
0564:             */
0565:            private void visitClassTable(SpeedoClass sc) throws SpeedoException {
0566:                //check the mainTable
0567:                if (sc.mainTable == null) {
0568:                    if (sc.inheritance == null
0569:                            || sc.inheritance.super ClassName == null) {
0570:                        sc.mainTable = new SpeedoTable();
0571:                    } else if (sc.inheritance.isFilteredMapping()) {
0572:                        //The table is one of the parent
0573:                        sc.mainTable = getRootTable(sc.getSuper());
0574:                    } else if (sc.inheritance.isHorizontalMapping()) {
0575:                        sc.mainTable = new SpeedoTable();
0576:                    } else if (sc.inheritance.isVerticalMapping()) {
0577:                        SpeedoClass parent = sc.getSuper();
0578:                        if (sc.inheritance.join == null) {
0579:                            sc.inheritance.join = new SpeedoJoin();
0580:                        }
0581:                        SpeedoJoin join = sc.inheritance.join;
0582:                        if (join.mainTable == null) {
0583:                            join.mainTable = getRootTable(parent);
0584:                        }
0585:                        if (sc.mainTable == null) {
0586:                            if (join.extTable == null) {
0587:                                join.extTable = new SpeedoTable();
0588:                            }
0589:                            sc.mainTable = join.extTable;
0590:                        } else {
0591:                            join.extTable = sc.mainTable;
0592:                        }
0593:                    } else if (sc.inheritance.strategy == SpeedoInheritance.STRATEGY_SUBCLASS_TABLE) {
0594:                        //allocate a temp table
0595:                        sc.mainTable = new SpeedoTable();
0596:                    } else {
0597:                        throw new SpeedoException(
0598:                                "Inheritance case not managed, class: "
0599:                                        + sc.getSourceDesc());
0600:                    }
0601:                }
0602:                if (sc.mainTable.name == null) {
0603:                    allocateTableName(sc, sc.mainTable);
0604:                }
0605:            }
0606:
0607:            /**
0608:             * Visit inheritance elements discriminators, inherited fields, join to 
0609:             * parent table, ...
0610:             */
0611:            private void visitClassInheritance(SpeedoClass sc)
0612:                    throws SpeedoException {
0613:                if (sc.inheritance == null
0614:                        || sc.inheritance.super ClassName == null) {
0615:                    return;
0616:                }
0617:                if (sc.inheritance.isFilteredMapping()) {
0618:                    if (scp.nmf.getNamingManager(sc)
0619:                            .needInheritanceDiscriminator(sc)) {
0620:                        SpeedoClass ancestor = sc.getAncestor();
0621:                        if (ancestor.inheritance == null
0622:                                || ancestor.inheritance.discriminator == null) {
0623:                            throw new SpeedoException(
0624:                                    "Filtered inheritance requires discriminator defined at root level: "
0625:                                            + ancestor.getSourceDesc());
0626:                        }
0627:                        if (sc.inheritance.discriminatorValues == null) {
0628:                            throw new SpeedoException(
0629:                                    "Filtered inheritance requires discriminator values defined for each sub class: "
0630:                                            + sc.getSourceDesc());
0631:                        }
0632:                    }
0633:                } else if (sc.inheritance.isHorizontalMapping()) {
0634:                    //maps all field of all parents
0635:                    List parents = sc.getParents();
0636:                    for (Iterator parentIt = parents.iterator(); parentIt
0637:                            .hasNext();) {
0638:                        SpeedoClass parent = (SpeedoClass) parentIt.next();
0639:                        for (Iterator fieldIt = parent.fields.values()
0640:                                .iterator(); fieldIt.hasNext();) {
0641:                            mapHorizontalInheritedField((SpeedoField) fieldIt
0642:                                    .next(), sc);
0643:                        }
0644:                    }
0645:                } else if (sc.inheritance.isVerticalMapping()) {
0646:                    //TODO: join columns between join.mainTable and join.extTable
0647:                    //TODO: discriminator
0648:                }
0649:            }
0650:
0651:            /**
0652:             * Visit identity column(s) when there is no primary key field
0653:             */
0654:            private void visitIdentityColumn(SpeedoClass sc)
0655:                    throws SpeedoException {
0656:                if (sc.identity.columns != null || sc.getPKFields().size() > 0) {
0657:                    return;
0658:                }
0659:                //no pk fields and no column defined in sc.identity
0660:                NamingManager nm = scp.nmf.getNamingManager(sc);
0661:                SpeedoColumn[] cols = nm.getDefaultColumn(sc);
0662:                if (cols == null) {
0663:                    throw new SpeedoException(
0664:                            "no identity mapping for the class '"
0665:                                    + sc.getFQName() + "'.");
0666:                }
0667:                sc.identity.setColumns(Arrays.asList(cols));
0668:            }
0669:
0670:            /**
0671:             * Visit primitive field. By default a primitive field is stored in the 
0672:             * main table except if a join is specified. The default column name is
0673:             * the field name.
0674:             */
0675:            private void visitPrimitiveField(SpeedoField sf)
0676:                    throws SpeedoException {
0677:                logger.log(BasicLevel.DEBUG, "\t\tvisit field primitive '"
0678:                        + sf.name + "'.");
0679:                if (sf.columns == null) {
0680:                    logger.log(BasicLevel.DEBUG, "\t\tcreate new Column.");
0681:                    sf.addColumn(new SpeedoColumn());
0682:                }
0683:                SpeedoColumn col = sf.columns[0];
0684:                if (col.table == null) {
0685:                    if (sf.join == null) {
0686:                        col.table = sf.moClass.mainTable;
0687:                    } else {
0688:                        col.table = sf.join.extTable;
0689:                    }
0690:                    logger.log(BasicLevel.DEBUG, "\t\tset column table: "
0691:                            + col.table.name);
0692:                }
0693:                if (col.name == null) {
0694:                    col.name = sf.name;
0695:                    logger.log(BasicLevel.DEBUG, "\t\tset column name: "
0696:                            + col.name);
0697:                }
0698:            }
0699:
0700:            /**
0701:             * Set the mapped-by visit for bidirectional relationship. 
0702:             * @param sf is a persistent field.
0703:             */
0704:            private void visitFieldMappedBy(SpeedoField sf)
0705:                    throws SpeedoException {
0706:                if (sf.relationType == SpeedoField.NO_BI_RELATION) {
0707:                    logger.log(BasicLevel.DEBUG,
0708:                            "\t\t\tNo bidirectional relation.");
0709:                } else {
0710:                    SpeedoField rf = sf.getReverseField();
0711:                    boolean sfHasMapping = sf.columns != null
0712:                            || (sf.join != null && !sf.join.columns.isEmpty());
0713:                    boolean rfHasMapping = rf.columns != null
0714:                            || (rf.join != null && !rf.join.columns.isEmpty());
0715:                    if (sfHasMapping) {
0716:                        if (rfHasMapping) {
0717:                            logger
0718:                                    .log(BasicLevel.DEBUG,
0719:                                            "\t\t\tOR Mapping already defined both side.");
0720:                            sf.mappedByReversefield = false;
0721:                            rf.mappedByReversefield = false;
0722:                        } else {
0723:                            logger.log(BasicLevel.DEBUG,
0724:                                    "\t\t\tthe field contains an OR Mapping.");
0725:                            sf.mappedByReversefield = false;
0726:                            rf.mappedByReversefield = true;
0727:                        }
0728:                    } else {
0729:                        if (rfHasMapping) {
0730:                            logger
0731:                                    .log(BasicLevel.DEBUG,
0732:                                            "\t\t\tthe reverse field contains an OR Mapping.");
0733:                            sf.mappedByReversefield = true;
0734:                            rf.mappedByReversefield = false;
0735:                        } else {
0736:                            if (sf.relationType == SpeedoField.MANY_ONE_BI_RELATION) {
0737:                                //for MANY_ONE relations, when no mappedBy is specifed, it is 
0738:                                // simpler that the collection reference is mapped by simple 
0739:                                // reference
0740:                                rf.mappedByReversefield = true;
0741:                                sf.mappedByReversefield = false;
0742:                                logger
0743:                                        .log(
0744:                                                BasicLevel.DEBUG,
0745:                                                "\t\t\tfield is a the MANY side of the relation, then it must contains the OR Mapping.");
0746:                            } else if (sf.relationType == SpeedoField.ONE_MANY_BI_RELATION) {
0747:                                rf.mappedByReversefield = false;
0748:                                sf.mappedByReversefield = true;
0749:                                logger
0750:                                        .log(
0751:                                                BasicLevel.DEBUG,
0752:                                                "\t\t\tfield is a the ONE side of the relation, then it is mapped by the reverse field.");
0753:                            } else {
0754:                                sf.mappedByReversefield = !rf.mappedByReversefield;
0755:                                logger.log(BasicLevel.DEBUG, "\t\t\tfield is "
0756:                                        + (sf.mappedByReversefield ? ""
0757:                                                : " NOT")
0758:                                        + " mapped by the reverse field.");
0759:                            }
0760:                        }
0761:                    }
0762:                }
0763:            }
0764:
0765:            /**
0766:             * Visit Class reference field. Manages the case of the foreign key is 
0767:             * managed by reverse field or not.
0768:             */
0769:            private void visitClassRefField(SpeedoField sf)
0770:                    throws SpeedoException {
0771:                logger.log(BasicLevel.DEBUG,
0772:                        "\t\tvisit field class reference '" + sf.name + "'.");
0773:                visitClassRefFieldExtension(sf);
0774:                visitFieldMappedBy(sf);
0775:                SpeedoClass rclass = sf.getReferencedClass();
0776:                if (sf.mappedByReversefield) {
0777:                    SpeedoField rf = sf.getReverseField();
0778:                    logger.log(BasicLevel.DEBUG, "\t\tfield '" + sf.name
0779:                            + "' is mapped by reverse field: "
0780:                            + rf.getFQFieldName());
0781:                    ;
0782:                    visitSpeedoClass(rclass, new VisitRequired(rf));
0783:                    computeFieldFromReverse(sf);
0784:                } else {
0785:                    SpeedoTable table;
0786:                    if (sf.join == null) {
0787:                        table = sf.moClass.mainTable;
0788:                    } else {
0789:                        table = sf.join.extTable;
0790:                    }
0791:                    if (sf.columns == null) {
0792:                        logger.log(BasicLevel.DEBUG, "\t\tfield '" + sf.name
0793:                                + "' requires pk fields of the class "
0794:                                + rclass.getFQName());
0795:                        visitSpeedoClass(rclass, VisitRequired.BASE);
0796:                        sf.columns = getFKColumn(rclass, sf.name + "_", table);
0797:                    } else {
0798:                        for (int i = 0; i < sf.columns.length; i++) {
0799:                            sf.columns[i].table = table;
0800:                            computeTargetColumn(sf, i, rclass);
0801:                        }
0802:                    }
0803:                }
0804:            }
0805:
0806:            /**
0807:             * Computes field mapping from its reverse field.
0808:             */
0809:            private void computeFieldFromReverse(SpeedoField sf)
0810:                    throws SpeedoException {
0811:                SpeedoField rField = sf.getReverseField();
0812:                sf.join = new SpeedoJoin();
0813:                sf.join.mainTable = sf.moClass.mainTable;
0814:                if (rField.join == null) {
0815:                    //compute the sf.column from the pk column of the referenced class
0816:                    sf.join.extTable = rField.moClass.mainTable;
0817:                    sf.columns = getFKColumn(rField.moClass, "",
0818:                            sf.join.extTable);
0819:                } else {
0820:                    sf.join.extTable = rField.join.extTable;
0821:                    //compute the sf.column from the pk column of the referenced class
0822:                    sf.columns = new SpeedoColumn[rField.join.columns.size()];
0823:                    int i = 0;
0824:                    for (Iterator jcolIt = rField.join.columns.iterator(); jcolIt
0825:                            .hasNext();) {
0826:                        SpeedoJoinColumn jcol = (SpeedoJoinColumn) jcolIt
0827:                                .next();
0828:                        sf.columns[i] = (SpeedoColumn) jcol.column.clone();
0829:                        sf.columns[i].targetColumn = jcol.targetColumn;
0830:                        sf.columns[i].targetField = jcol.targetField;
0831:                        i++;
0832:                    }
0833:                }
0834:                //compute the join
0835:                sf.join.columns.clear();
0836:                for (int i = 0; i < rField.columns.length; i++) {
0837:                    sf.join.columns
0838:                            .add(new SpeedoJoinColumn(rField.columns[i]));
0839:                }
0840:            }
0841:
0842:            /**
0843:             * Gets a list of SpeedoJoinColumn joining the identifier column of
0844:             * a referenced class
0845:             * @param rclass is the referenced
0846:             * @param colPrefix is prefix to the foreign key column name
0847:             * @param table is the table of the foreign key column
0848:             * @return list of SpeedoJoinColumn
0849:             */
0850:            private List getFKJoinColumn(SpeedoClass rclass, String colPrefix,
0851:                    SpeedoTable table) {
0852:                SpeedoColumn[] fkCols = getFKColumn(rclass, colPrefix, table);
0853:                ArrayList res = new ArrayList(fkCols.length);
0854:                for (int i = 0; i < fkCols.length; i++) {
0855:                    res.add(new SpeedoJoinColumn(fkCols[i]));
0856:                }
0857:                return res;
0858:            }
0859:
0860:            /**
0861:             * Gets a list of SpeedoColumn joining the identifier column of
0862:             * a referenced class.
0863:             * @param rclass is the referenced
0864:             * @param colPrefix is prefix to the foreign key column name
0865:             * @param table is the table of the foreign key column
0866:             * @return
0867:             */
0868:            private SpeedoColumn[] getFKColumn(SpeedoClass rclass,
0869:                    String colPrefix, SpeedoTable table) {
0870:                SpeedoColumn[] pkColumns = getIdColumns(rclass);
0871:                SpeedoColumn[] columns = new SpeedoColumn[pkColumns.length];
0872:                for (int i = 0; i < pkColumns.length; i++) {
0873:                    //create new SpeedoColumn instance targeting pk column
0874:                    // with the same description (sql type, length, scale, ...)
0875:                    columns[i] = new SpeedoColumn();
0876:                    columns[i].targetColumn = pkColumns[i].name;
0877:                    columns[i].name = colPrefix + columns[i].targetColumn;
0878:                    columns[i].table = table;
0879:                    columns[i].sqlType = pkColumns[i].sqlType;
0880:                    columns[i].scale = pkColumns[i].scale;
0881:                    columns[i].length = pkColumns[i].length;
0882:                }
0883:                return columns;
0884:            }
0885:
0886:            /**
0887:             * Gets the identifier column(s) of a persistent class
0888:             * @param sc is a persistent class
0889:             * @return the identifier column(s) of a persistent class
0890:             */
0891:            private SpeedoColumn[] getIdColumns(SpeedoClass sc) {
0892:                Collection pkFields = sc.getPKFields();
0893:                SpeedoColumn[] columns;
0894:                if (pkFields.isEmpty()) {
0895:                    //identifier is based on visible persistent field(s)
0896:                    columns = new SpeedoColumn[sc.identity.columns.length];
0897:                    for (int i = 0; i < sc.identity.columns.length; i++) {
0898:                        columns[i] = sc.identity.columns[i].column;
0899:                    }
0900:                } else {
0901:                    //identifier is based on hidden field(s) (ex: data store id)
0902:                    int i = 0;
0903:                    columns = new SpeedoColumn[pkFields.size()];
0904:                    for (Iterator it = pkFields.iterator(); it.hasNext();) {
0905:                        SpeedoField pkField = (SpeedoField) it.next();
0906:                        columns[i] = pkField.columns[0];
0907:                        i++;
0908:                    }
0909:                }
0910:                return columns;
0911:            }
0912:
0913:            /**
0914:             * Visit GenClassRef field (field referencing a collection or a map of 
0915:             * stuff). 
0916:             * @param sf is a persistent field referencing a collection, a map of stuff
0917:             * (persistent objects or primitive elements)
0918:             */
0919:            private void visitGenClassRefField(SpeedoField sf)
0920:                    throws SpeedoException {
0921:                logger.log(BasicLevel.DEBUG,
0922:                        "\t\tvisit field generic class reference '" + sf.name
0923:                                + "'.");
0924:                visitGenClassRefFieldExtension(sf);
0925:                visitFieldMappedBy(sf);
0926:                if (sf.mappedByReversefield) {
0927:                    SpeedoField rf = sf.getReverseField();
0928:                    logger.log(BasicLevel.DEBUG, "\t\tfield '" + sf.name
0929:                            + "' is mapped by reverse field: "
0930:                            + rf.getFQFieldName());
0931:                    visitSpeedoClass(sf.getReferencedClass(),
0932:                            new VisitRequired(rf));
0933:                    computeFieldFromReverse(sf);
0934:                    // do not forget index in case of map indexed by field of the 
0935:                    // referenced class
0936:                    visitGenClassIndex(sf);
0937:                    return;
0938:                }
0939:                boolean joinCreated = sf.join == null;
0940:                if (joinCreated) {
0941:                    //create the join between mainTable and the genClass table
0942:                    sf.join = new SpeedoJoin();
0943:                    //sf.moClass.addJoin(sf.join);
0944:                    if (logger.isLoggable(BasicLevel.DEBUG)) {
0945:                        logger.log(BasicLevel.DEBUG, "\t\t\tCreate SpeedoJoin");
0946:                    }
0947:                }
0948:                if (sf.join.mainTable == null) {
0949:                    sf.join.mainTable = sf.moClass.mainTable;
0950:                    if (logger.isLoggable(BasicLevel.DEBUG)) {
0951:                        logger.log(BasicLevel.DEBUG,
0952:                                "\t\t\tDefine the main table on join: "
0953:                                        + sf.join.mainTable.name);
0954:                    }
0955:                }
0956:                if (sf.join.extTable == null) {
0957:                    //compute the table of the genclass with regards to the relation type
0958:                    switch (sf.relationType) {
0959:                    case SpeedoField.MANY_MANY_BI_RELATION:
0960:                        SpeedoField rfield = sf.getReverseField();
0961:                        if (rfield.join != null && rfield.join.extTable != null) {
0962:                            sf.join.extTable = rfield.join.extTable;
0963:                            if (logger.isLoggable(BasicLevel.DEBUG)) {
0964:                                logger.log(BasicLevel.DEBUG,
0965:                                        "\t\t\tUse table of reverse field: "
0966:                                                + sf.join.extTable.name);
0967:                            }
0968:                        } else {
0969:                            sf.join.extTable = new SpeedoTable();
0970:                            sf.join.extTable.name = sf.moClass.name + "_"
0971:                                    + sf.name;
0972:                            if (logger.isLoggable(BasicLevel.DEBUG)) {
0973:                                logger.log(BasicLevel.DEBUG,
0974:                                        "\t\t\tDefine the join table of the relation: "
0975:                                                + sf.join.extTable.name);
0976:                            }
0977:                        }
0978:                        break;
0979:                    case SpeedoField.ONE_MANY_BI_RELATION:
0980:                        rfield = sf.getReverseField();
0981:                        if (rfield.join != null && rfield.join.extTable != null) {
0982:                            sf.join.extTable = rfield.join.extTable;
0983:                            if (logger.isLoggable(BasicLevel.DEBUG)) {
0984:                                logger.log(BasicLevel.DEBUG,
0985:                                        "\t\t\tUse table of reverse field: "
0986:                                                + sf.join.extTable.name);
0987:                            }
0988:                        } else {
0989:                            sf.join.extTable = rfield.moClass.mainTable;
0990:                            if (logger.isLoggable(BasicLevel.DEBUG)) {
0991:                                logger.log(BasicLevel.DEBUG,
0992:                                        "\tUse the table of the reference class: "
0993:                                                + sf.join.extTable.name);
0994:                            }
0995:                        }
0996:                        break;
0997:                    default:
0998:                        sf.join.extTable = new SpeedoTable();
0999:                        sf.join.extTable.name = sf.moClass.name + "_" + sf.name;
1000:                        if (logger.isLoggable(BasicLevel.DEBUG)) {
1001:                            logger.log(BasicLevel.DEBUG,
1002:                                    "\t\t\tDefine the GC table: "
1003:                                            + sf.join.extTable.name);
1004:                        }
1005:                        break;
1006:                    }
1007:                    sf.join.extTable.join = sf.join;
1008:                }
1009:                if (sf.join.columns.isEmpty()) {
1010:                    //Compute the join between the table of the owner class and the 
1011:                    // table of the genclass
1012:                    sf.join.columns.addAll(getFKJoinColumn(sf.moClass, "",
1013:                            sf.join.extTable));
1014:                    if (logger.isLoggable(BasicLevel.DEBUG)) {
1015:                        logger.log(BasicLevel.DEBUG,
1016:                                "\t\t\tDefine the join column: \n"
1017:                                        + sf.join.columns);
1018:                    }
1019:                } else {
1020:                    for (Iterator it = sf.join.columns.iterator(); it.hasNext();) {
1021:                        SpeedoJoinColumn jc = (SpeedoJoinColumn) it.next();
1022:                        if (jc.targetColumn == null) {
1023:                            computeTargetJoinColumn(sf, jc);
1024:                        }
1025:                    }
1026:                }
1027:                if (joinCreated && logger.isLoggable(BasicLevel.DEBUG)) {
1028:                    logger.log(BasicLevel.DEBUG, "\t\t\tCreated "
1029:                            + sf.join.toString());
1030:                }
1031:                //map the index of the genclass
1032:                visitGenClassIndex(sf);
1033:                //map the element of the genclass
1034:                visitGenClassElement(sf);
1035:            }
1036:
1037:            /**
1038:             * Visit genclass index. Indexes can be find for List or Map implementation. 
1039:             * @param sf a persistent field.
1040:             */
1041:            private void visitGenClassIndex(SpeedoField sf)
1042:                    throws SpeedoException {
1043:                if (sf.jdoTuple instanceof  SpeedoCollection) {
1044:                    SpeedoCollection collec = (SpeedoCollection) sf.jdoTuple;
1045:                    if (collec.indexColumns == null
1046:                            && List.class.isAssignableFrom(getGCClass(sf))) {
1047:                        collec.indexColumns = new SpeedoColumn("idx",
1048:                                sf.join.extTable);
1049:                        if (logger.isLoggable(BasicLevel.DEBUG)) {
1050:                            logger.log(BasicLevel.DEBUG,
1051:                                    "\t\t\tCreate column for the list index"
1052:                                            + collec.indexColumns.toString());
1053:                        }
1054:                    }
1055:                } else if (sf.jdoTuple instanceof  SpeedoMap) {
1056:                    SpeedoMap map = (SpeedoMap) sf.jdoTuple;
1057:                    if (map.keyColumns == null) {
1058:                        map.keyColumns = new SpeedoColumn("idx",
1059:                                sf.join.extTable);
1060:                        if (logger.isLoggable(BasicLevel.DEBUG)) {
1061:                            logger.log(BasicLevel.DEBUG,
1062:                                    "\t\t\tCreate column for the map key"
1063:                                            + map.keyColumns.toString());
1064:                        }
1065:                    }
1066:                }
1067:            }
1068:
1069:            /**
1070:             * Visit gen class element. The element can be a primitive element
1071:             * or a reference to a persistent class.
1072:             * @param sf is the SpeedoField meta object representing the genclass
1073:             */
1074:            private void visitGenClassElement(SpeedoField sf)
1075:                    throws SpeedoException {
1076:                SpeedoClass rclass = sf.getReferencedClass();
1077:                if (sf.columns == null) {
1078:                    if (rclass == null) {
1079:                        //primitive element
1080:                        sf.addColumn(new SpeedoColumn("element",
1081:                                sf.join.extTable));
1082:                    } else {
1083:                        logger.log(BasicLevel.DEBUG, "\t\tfield '" + sf.name
1084:                                + "' requires pk fields of the class "
1085:                                + rclass.getFQName());
1086:                        visitSpeedoClass(rclass, VisitRequired.BASE);
1087:                        //persistent class ==> classRef
1088:                        String prefix = "";
1089:                        if (sf.join.extTable != rclass.mainTable) {
1090:                            prefix = "elem_";
1091:                        }
1092:                        sf.columns = getFKColumn(rclass, prefix,
1093:                                sf.join.extTable);
1094:                    }
1095:                    if (logger.isLoggable(BasicLevel.DEBUG)) {
1096:                        StringBuffer sb = new StringBuffer();
1097:                        sb.append("\t\t\tCreate ").append(sf.columns.length);
1098:                        sb.append(" column(s) for the gen class element :\n");
1099:                        for (int i = 0; i < sf.columns.length; i++) {
1100:                            sb.append("\t\t-").append(sf.columns[i]).append(
1101:                                    "\n");
1102:                        }
1103:                        logger.log(BasicLevel.DEBUG, sb.toString());
1104:                    }
1105:                } else {
1106:                    if (rclass == null) {
1107:                        //primitive element
1108:                        if (sf.columns[0].name == null) {
1109:                            sf.columns[0].name = "element";
1110:                        }
1111:                        if (sf.columns[0].table == null) {
1112:                            sf.columns[0].table = sf.join.extTable;
1113:                        }
1114:                    } else {
1115:                        //persistent class ==> classRef
1116:                        SpeedoColumn[] cols = getFKColumn(rclass, "elem_",
1117:                                sf.join.extTable);
1118:                        for (int i = 0; i < sf.columns.length; i++) {
1119:                            if (sf.columns[i].name == null) {
1120:                                sf.columns[i].name = cols[i].name;
1121:                            }
1122:                            if (sf.columns[i].targetColumn == null) {
1123:                                computeTargetColumn(sf, i, rclass);
1124:                            }
1125:                            if (sf.columns[i].table == null) {
1126:                                sf.columns[i].table = sf.join.extTable;
1127:                            }
1128:                        }
1129:                    }
1130:                }
1131:            }
1132:
1133:            /**
1134:             * Computes the targetColumn field of the sf.column[colIdx] if it is 
1135:             * required. 
1136:             * @param sf is the SpeedoCommonField holding the column definition
1137:             * @param colIdx is the index of the column among sf.columns array
1138:             * @param rclass is the referenced persistent class. The target column are
1139:             * the identifier column of the referenced class. 
1140:             * @throws SpeedoException
1141:             */
1142:            private void computeTargetColumn(SpeedoCommonField sf, int colIdx,
1143:                    SpeedoClass rclass) throws SpeedoException {
1144:                if (sf.columns[colIdx].targetColumn != null) {
1145:                    return;
1146:                }
1147:                if (sf.columns[colIdx].targetField == null) {
1148:                    //both are null
1149:                    if (sf.columns.length == 1) {
1150:                        //compute the target column from the unique pk field
1151:                        try {
1152:                            SpeedoField pkField = rclass.getUniquePKField();
1153:                            sf.columns[colIdx].targetColumn = pkField.columns[0].name;
1154:                        } catch (SpeedoException e) {
1155:                            throw new SpeedoException(
1156:                                    "Bad number of column specified for the "
1157:                                            + sf.getSourceDesc(), e);
1158:                        }
1159:                    } else {
1160:                        SpeedoException se = new SpeedoException(
1161:                                "Target column is required for the reference "
1162:                                        + sf.getSourceDesc());
1163:                        logger.log(BasicLevel.ERROR, se.getMessage(), se);
1164:                        throw se;
1165:                    }
1166:                } else {
1167:                    //compute the target column from the target field
1168:                    SpeedoField pkField = rclass
1169:                            .getField(sf.columns[colIdx].targetField);
1170:                    sf.columns[colIdx].targetColumn = pkField.columns[0].name;
1171:                }
1172:            }
1173:
1174:            private void computeTargetJoinColumn(SpeedoCommonField sf,
1175:                    SpeedoJoinColumn jc) throws SpeedoException {
1176:                int nbcol = sf.join.columns.size();
1177:                if (jc.targetField == null) {
1178:                    //both are null
1179:                    if (nbcol == 1) {
1180:                        //compute the target column from the unique pk field
1181:                        SpeedoField pkField = sf.moClass.getUniquePKField();
1182:                        jc.targetColumn = pkField.columns[0].name;
1183:                    } else {
1184:                        SpeedoException se = new SpeedoException(
1185:                                "Target column is required for join column of the reference "
1186:                                        + sf.getSourceDesc());
1187:                        logger.log(BasicLevel.ERROR, se.getMessage(), se);
1188:                        throw se;
1189:                    }
1190:                } else {
1191:                    //compute the target column from the target field
1192:                    SpeedoField pkField = sf.moClass.getField(jc.targetField);
1193:                    jc.targetColumn = pkField.columns[0].name;
1194:                }
1195:            }
1196:
1197:            /**
1198:             * Get the type of the persistent field.
1199:             * @return the java.lang.Class representing the type of the field. 
1200:             */
1201:            private Class getGCClass(SpeedoField sf) throws SpeedoException {
1202:                try {
1203:                    return Class.forName(sf.type());
1204:                } catch (ClassNotFoundException e) {
1205:                    throw new SpeedoException("Class loading problem: ", e);
1206:                }
1207:            }
1208:
1209:            /**
1210:             * Creates a new table name for a SpeedoTable 
1211:             * @param sc is the SpeedoClass that has the table
1212:             * @param t is the table without name
1213:             */
1214:            private void allocateTableName(SpeedoClass sc, SpeedoTable t) {
1215:                if (t.name == null) {
1216:                    if (sc.mainTable == t) {
1217:                        t.name = sc.name.toUpperCase();
1218:                    } else {
1219:                        for (int i = 0; i < sc.joinToExtTables.length; i++) {
1220:                            if (sc.joinToExtTables[i].extTable == t) {
1221:                                t.name = sc.name.toUpperCase() + "_EXT_" + i;
1222:                                return;
1223:                            }
1224:                        }
1225:                        t.name = sc.name.toUpperCase();
1226:                    }
1227:                }
1228:            }
1229:
1230:            /**
1231:             * Builds, if required, the mapping of an inherited field.
1232:             * @param sif
1233:             */
1234:            private void mapHorizontalInheritedField(SpeedoField sf,
1235:                    SpeedoClass sc) throws SpeedoException {
1236:                SpeedoInheritedField sif = (SpeedoInheritedField) sc.inheritance.remappedInheritedFields
1237:                        .get(sf.getFQFieldName());
1238:                if (sif == null) {
1239:                    sif = sc.inheritance.newSpeedoInheritedField(sf);
1240:                }
1241:                if (sf.jdoTuple == null) {
1242:                    SpeedoClass rclass = sf.getReferencedClass();
1243:                    //primitive field or simple reference to a persistent class
1244:                    if (rclass != null
1245:                            && sf.join != null
1246:                            && sf.relationType == SpeedoField.ONE_ONE_BI_RELATION
1247:                            && sf.mappedByReversefield) {
1248:                        // the classref belongs a bidirectionnal relationship
1249:                        // ONE-ONE. In addition the foreign key is hold by the table
1250:                        // of the referenced class
1251:                        setJoinNColsFromParent(sif);
1252:                    } else {
1253:                        if (sif.columns == null) {
1254:                            // ClassRef or primtive element to map localy
1255:                            for (int i = 0; i < sf.columns.length; i++) {
1256:                                //Same column definition but in the table of the class
1257:                                SpeedoColumn col = (SpeedoColumn) sf.columns[i]
1258:                                        .clone();
1259:                                col.table = sif.moClass.mainTable;
1260:                                sif.addColumn(col);
1261:                            }
1262:                        } else {
1263:                            if (rclass != null) {
1264:                                for (int i = 0; i < sif.columns.length; i++) {
1265:                                    computeTargetColumn(sif, i, rclass);
1266:                                }
1267:                            }
1268:                        }
1269:                    }
1270:                } else {
1271:                    //reference to a generic class (Collection, Set, Map, ..)
1272:                    setJoinNColsFromParent(sif);
1273:                    //TODO: support index/key
1274:                }
1275:            }
1276:
1277:            private void setJoinNColsFromParent(SpeedoInheritedField sif) {
1278:                SpeedoField sf = sif.inheritedField;
1279:                if (sif.columns == null) {
1280:                    //Use the same column for the genclass value
1281:                    sif.columns = sf.columns;
1282:                }
1283:                if (sif.join == null) {
1284:                    sif.join = new SpeedoJoin();
1285:                    sif.join.extTable = sf.join.extTable;
1286:                    sif.join.mainTable = sf.moClass.mainTable;
1287:                    // Use the same join column name but with the targeted column
1288:                    // of the current table. We suppose than the id has the same 
1289:                    // structure 
1290:                    sif.join.columns = getFKJoinColumn(sf.moClass, "",
1291:                            sif.join.extTable);
1292:                    if (sif.join.columns.size() == 1) {
1293:                        ((SpeedoJoinColumn) sif.join.columns.get(0)).column.name = ((SpeedoJoinColumn) sf.join.columns
1294:                                .get(0)).column.name;
1295:                    } else {
1296:                        for (Iterator it = sf.moClass.getPKFields().iterator(); it
1297:                                .hasNext();) {
1298:                            SpeedoField pkField = (SpeedoField) it.next();
1299:                            SpeedoJoinColumn parentjc = sf
1300:                                    .getFKJoinColumn(pkField.columns[0].name);
1301:                            SpeedoJoinColumn newjc = sif
1302:                                    .getFKJoinColumn(pkField.columns[0].name);
1303:                            newjc.column.name = parentjc.column.name;
1304:                        }
1305:                    }
1306:                }
1307:
1308:            }
1309:
1310:            /**
1311:             * Get the root table of a persistent class. If the class has not 
1312:             * inheritance the root table is the maintable. If the inheritance mapping
1313:             * is vertical, the root table is the one of the parent.
1314:             */
1315:            private SpeedoTable getRootTable(SpeedoClass sc) {
1316:                if (sc.inheritance != null
1317:                        && sc.inheritance.isVerticalMapping()) {
1318:                    return sc.inheritance.join.mainTable;
1319:                } else {
1320:                    return sc.mainTable;
1321:                }
1322:            }
1323:
1324:            /**
1325:             * Visit extensions of field referencing a persistent class. This method
1326:             * converts old Extensions 'source-foreign-keys' and 'target-foreign-keys'
1327:             * to mapping definition in the Speedo meta information.
1328:             * @param sf a persistent field referencing a persistent class.
1329:             * @see SpeedoProperties#SOURCE_FK
1330:             * @see SpeedoProperties#TARGET_FK
1331:             */
1332:            public void visitClassRefFieldExtension(SpeedoField sf)
1333:                    throws SpeedoException {
1334:                SpeedoClass rclass = sf.getReferencedClass();
1335:                String sfk = sf
1336:                        .getExtensionValueByKey(SpeedoProperties.SOURCE_FK);
1337:                String tfk = sf
1338:                        .getExtensionValueByKey(SpeedoProperties.TARGET_FK);
1339:                if (sfk == null && tfk == null) {
1340:                    return;
1341:                }
1342:                if (sfk != null
1343:                        && sf.relationType == SpeedoField.ONE_ONE_BI_RELATION) {
1344:                    //The relation is mapped by the field having the foreign key
1345:                    return;
1346:                }
1347:                if (tfk != null) {
1348:                    SpeedoColumn[] cols = getFKColumn(tfk,
1349:                            sf.moClass.mainTable, sf.getReferencedClass());
1350:                    if (sf.columns != null && cols.length == sf.columns.length) {
1351:                        for (int i = 0; i < cols.length; i++) {
1352:                            sf.columns[i].merge(cols[i]);
1353:                        }
1354:                    } else {
1355:                        sf.columns = cols;
1356:                    }
1357:                } else if (sfk != null) { //backward reference
1358:                    sf.join = new SpeedoJoin();
1359:                    sf.join.mainTable = sf.moClass.mainTable;
1360:                    sf.join.extTable = rclass.mainTable;
1361:                    //compute the sf.column from the pk column of the referenced class
1362:                    Collection pkFields = rclass.getPKFields();
1363:                    if (pkFields.isEmpty()) {
1364:                        sf.columns = new SpeedoColumn[rclass.identity.columns.length];
1365:                        for (int i = 0; i < rclass.identity.columns.length; i++) {
1366:                            sf.columns[i] = rclass.identity.columns[i].column;
1367:                        }
1368:                    } else {
1369:                        int i = 0;
1370:                        sf.columns = new SpeedoColumn[pkFields.size()];
1371:                        for (Iterator it = pkFields.iterator(); it.hasNext();) {
1372:                            SpeedoField pkField = (SpeedoField) it.next();
1373:                            sf.columns[i] = pkField.columns[0];
1374:                            i++;
1375:                        }
1376:                    }
1377:                    //compute the join columns
1378:                    sf.join.columns.addAll(getFKJoinColumn(sfk,
1379:                            rclass.mainTable, sf.moClass));
1380:                }
1381:                logger.log(BasicLevel.DEBUG, "Field '" + sf.name
1382:                        + "' has deprecated extension(s): " + "\n\t-("
1383:                        + SpeedoProperties.SOURCE_FK + "=" + sfk + "\n\t-"
1384:                        + SpeedoProperties.TARGET_FK + "=" + tfk
1385:                        + "\nExtensions have been converted:" + "\n\t- column:"
1386:                        + sf.printColumns() + "\n\t- join:" + sf.join);
1387:            }
1388:
1389:            /**
1390:             * Visit extensions of field referencing a genclass. This method
1391:             * converts old Extensions 'source-foreign-keys', 'target-foreign-keys'
1392:             * and 'join-table' to mapping definition in the Speedo meta information.
1393:             * @param sf a persistent field referencing a genclass.
1394:             * @see SpeedoProperties#SOURCE_FK
1395:             * @see SpeedoProperties#TARGET_FK
1396:             * @see SpeedoProperties#JOIN_TABLE
1397:             */
1398:            public void visitGenClassRefFieldExtension(SpeedoField sf)
1399:                    throws SpeedoException {
1400:                String sfk = sf
1401:                        .getExtensionValueByKey(SpeedoProperties.SOURCE_FK);
1402:                String tfk = sf
1403:                        .getExtensionValueByKey(SpeedoProperties.TARGET_FK);
1404:                String jt = sf
1405:                        .getExtensionValueByKey(SpeedoProperties.JOIN_TABLE);
1406:                if (sfk == null && tfk == null && jt == null) {
1407:                    return;
1408:                }
1409:                if (sfk != null && tfk == null && jt == null
1410:                        && sf.relationType == SpeedoField.ONE_MANY_BI_RELATION) {
1411:                    //The relation is mapped by the field having the foreign key
1412:                    return;
1413:                }
1414:                sf.join = new SpeedoJoin();
1415:                sf.join.mainTable = sf.moClass.mainTable;
1416:                //sf.moClass.addJoin(sf.join);
1417:                if (jt != null) {
1418:                    sf.join.extTable = new SpeedoTable();
1419:                    sf.join.extTable.name = jt;
1420:                }
1421:                if (tfk != null
1422:                        && (sf.columns == null || sf.columns[0].name == null)) {
1423:                    //compute the value column(s)
1424:                    sf.columns = getFKColumn(tfk, sf.join.extTable, sf
1425:                            .getReferencedClass());
1426:                }
1427:                if (sfk != null && sf.join.columns.isEmpty()) {
1428:                    //compute the join column(s)
1429:                    sf.join.columns.addAll(getFKJoinColumn(sfk,
1430:                            sf.join.extTable, sf.moClass));
1431:                }
1432:                logger.log(BasicLevel.DEBUG, "Field '" + sf.name
1433:                        + "' has deprecated extension(s): " + "\n\t-("
1434:                        + SpeedoProperties.SOURCE_FK + "=" + sfk + "\n\t-"
1435:                        + SpeedoProperties.TARGET_FK + "=" + tfk + "\n\t"
1436:                        + SpeedoProperties.JOIN_TABLE + "=" + jt
1437:                        + "\nExtensions have been converted:" + "\n\t- column:"
1438:                        + sf.printColumns() + "\n\t- join:" + sf.join);
1439:            }
1440:
1441:            /**
1442:             * Gets array of new SpeedoColumn representing a join to a peristent class.
1443:             * @param pk2tfk is the map defining the name of the foreign key column from
1444:             * the primary key column (key=String pkColName/ value=String fkColName)
1445:             * @param table is the table hosting the foreign key column
1446:             * @param rclass is the referenced class having pk column 
1447:             */
1448:            private SpeedoColumn[] getFKColumn(String pk2tfk,
1449:                    SpeedoTable table, SpeedoClass rclass) {
1450:                Map map = getPk2Fk(pk2tfk);
1451:                SpeedoColumn[] columns = new SpeedoColumn[map.size()];
1452:                int i = 0;
1453:                for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
1454:                    Map.Entry me = (Map.Entry) it.next();
1455:                    columns[i] = new SpeedoColumn();
1456:                    columns[i].name = (String) me.getValue();
1457:                    columns[i].table = table;
1458:                    columns[i].targetColumn = (String) me.getKey();
1459:                    if (rclass != null) {
1460:                        SpeedoColumn pkcol = rclass.getColumn(
1461:                                columns[i].targetColumn, true);
1462:                        if (pkcol != null) {
1463:                            columns[i].sqlType = pkcol.sqlType;
1464:                            columns[i].scale = pkcol.scale;
1465:                            columns[i].length = pkcol.length;
1466:                        }
1467:                    }
1468:                    i++;
1469:                }
1470:                return columns;
1471:            }
1472:
1473:            /**
1474:             * Gets List of new SpeedoJoinColumn representing a join to a peristent class.
1475:             * @param pk2tfk is the map defining the name of the foreign key column from
1476:             * the primary key column (key=String pkColName/ value=String fkColName)
1477:             * @param table is the table hosting the foreign key column
1478:             * @param rclass is the referenced class having pk column 
1479:             */
1480:            private List getFKJoinColumn(String pk2sfk, SpeedoTable table,
1481:                    SpeedoClass rclass) {
1482:                SpeedoColumn[] cols = getFKColumn(pk2sfk, table, rclass);
1483:                ArrayList res = new ArrayList(cols.length);
1484:                for (int i = 0; i < cols.length; i++) {
1485:                    res.add(new SpeedoJoinColumn(cols[i]));
1486:                }
1487:                return res;
1488:            }
1489:
1490:            /**
1491:             * Converts the value of the extension 'source-foreign-keys' and 
1492:             * 'target-foreign-keys' to a map 
1493:             * @param fks
1494:             * @return a map (key=String pkColName / Value=String fkColName)
1495:             */
1496:            private Map getPk2Fk(String fks) {
1497:                Map res = new HashMap();
1498:                StringTokenizer st = new StringTokenizer(fks, "=,:;/", false);
1499:                String pk = null;
1500:                while (st.hasMoreTokens()) {
1501:                    String tok = st.nextToken();
1502:                    tok = tok.trim();
1503:                    if (pk == null) {
1504:                        pk = tok;
1505:                    } else {
1506:                        res.put(pk, tok);
1507:                        pk = null;
1508:                    }
1509:                }
1510:                return res;
1511:            }
1512:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.