Source Code Cross Referenced for AbstractGenerator.java in  » Database-ORM » castor » org » castor » ddlgen » 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 » castor » org.castor.ddlgen 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2006 Le Duc Bao, Ralf Joachim
0003:         * 
0004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
0005:         * use this file except in compliance with the License. You may obtain a copy of
0006:         * the License at
0007:         * 
0008:         * http://www.apache.org/licenses/LICENSE-2.0
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0013:         * License for the specific language governing permissions and limitations under
0014:         * the License.
0015:         */
0016:        package org.castor.ddlgen;
0017:
0018:        import java.io.OutputStream;
0019:        import java.util.Enumeration;
0020:        import java.util.HashMap;
0021:        import java.util.Iterator;
0022:        import java.util.Map;
0023:
0024:        import org.castor.ddlgen.schemaobject.Field;
0025:        import org.castor.ddlgen.schemaobject.ForeignKey;
0026:        import org.castor.ddlgen.schemaobject.KeyGenerator;
0027:        import org.castor.ddlgen.schemaobject.PrimaryKey;
0028:        import org.castor.ddlgen.schemaobject.Schema;
0029:        import org.castor.ddlgen.schemaobject.Table;
0030:        import org.castor.ddlgen.typeinfo.TypeInfo;
0031:        import org.exolab.castor.mapping.Mapping;
0032:        import org.exolab.castor.mapping.xml.ClassChoice;
0033:        import org.exolab.castor.mapping.xml.ClassMapping;
0034:        import org.exolab.castor.mapping.xml.FieldMapping;
0035:        import org.exolab.castor.mapping.xml.KeyGeneratorDef;
0036:        import org.exolab.castor.mapping.xml.MapTo;
0037:        import org.exolab.castor.mapping.xml.MappingRoot;
0038:        import org.exolab.castor.mapping.xml.Sql;
0039:
0040:        /**
0041:         * AbstractGenerator is the base class for various DDL generator of specific DB and
0042:         * handles following tasks: 
0043:         * <li/> Extract information from Mapping to Schema
0044:         * <li/> Loop through the schema and provide a skeleton for DDL creation
0045:         * 
0046:         * <p/>AbstractGenerator will automatically extract necessary information for DDL 
0047:         * creation. That information is handled by Schema.
0048:         * <p/>To create new generator for a DBMS, you should:
0049:         * <li/> Overwrite this class to create new generator for a DBMS. 
0050:         * <li/> If the syntax of DBMS is different to standard DDL syntax, you should 
0051:         * overwrite SchemaObject (Table, Field, KeyGenerator, Index, ForeignKey,...) classes. 
0052:         * The class SchemaObjectFactory who handles the SchemaObject creation must 
0053:         * be overwritten.
0054:         * <li/> You must overwrite the TypeMapper if mapping between JDBC types and 
0055:         * specific DBMS’s types is different among various DBMS.
0056:         * <p/>The example bellow shows how to create a generator for DB2:
0057:         * <li/> <b>Generator for DB2</b>
0058:         * <pre>
0059:         *public class Db2Generator extends AbstractGenerator {
0060:         *
0061:         *    public Db2Generator(final String globConf, final String dbConf)
0062:         *            throws GeneratorException {
0063:         *        super(globConf, dbConf);
0064:         *        setTypeMapper(new Db2TypeMapper(getConf()));
0065:         *    }
0066:         *}   
0067:         * </pre>
0068:         * <li/><b>TypeMapper for DB2</b>
0069:         * <pre>
0070:         *public final class Db2TypeMapper extends AbstractTypeMapper {
0071:         *    public Db2TypeMapper(final Configuration conf) {
0072:         *        super(conf);
0073:         *    }
0074:         * 
0075:         *    protected void initialize(final Configuration conf) {
0076:         *        // numeric types
0077:         *        this.add(new NotSupportedType("bit"));
0078:         *        LOG.warn("Db2 does not support 'TINY' type, use SMALLINT instead.");
0079:         *        this.add(new NoParamType("tinyint", "SMALLINT"));
0080:         *        this.add(new NoParamType("smallint", "SMALLINT"));
0081:         *        this.add(new NoParamType("integer", "INTEGER"));
0082:         *        this.add(new NoParamType("bigint", "BIGINT"));
0083:         *    }
0084:         *}
0085:         *</pre>
0086:         * <li/><b>Field for DB2</b>
0087:         *<pre> 
0088:         *public class Db2Field extends Field {
0089:         *    public Db2Field() {
0090:         *        super();
0091:         *    }
0092:         *
0093:         *    public String toDDL() throws GeneratorException {
0094:         *        StringBuffer buff = new StringBuffer();
0095:         *        buff.append(getName()).append(" ");
0096:         *        buff.append(getType().toDDL(this));
0097:         *        
0098:         *        if (isIdentity()) {
0099:         *            buff.append(" NOT NULL");
0100:         *        }
0101:         *        
0102:         *        KeyGenerator keyGen = getKeyGenerator();
0103:         *        if (keyGen != null && isIdentity()) {
0104:         *            
0105:         *            if (KeyGenerator.IDENTITY_KEY.equalsIgnoreCase(keyGen.getName())) {
0106:         *                buff.append(" GENERATED BY DEFAULT AS IDENTITY ").
0107:         *                    append("START WITH 1 INCREMENT BY 1");
0108:         *            }
0109:         *        }
0110:         *
0111:         *        return buff.toString();
0112:         *    }
0113:         *}
0114:         *</pre>
0115:         * <li/><b>Field for DB2</b>
0116:         *<pre> 
0117:         *public class Db2SchemaFactory extends SchemaFactory {
0118:         *    public Db2SchemaFactory() {
0119:         *        super();
0120:         *    }
0121:         *    public Field createField() {
0122:         *        return new Db2Field();
0123:         *    }
0124:         *
0125:         *}
0126:         *</pre>
0127:         * The GeneratorFactory class handles the specific database generator creation. 
0128:         * For example:
0129:         * <pre>
0130:         *  Generator generator = GeneratorFactory.
0131:         *      createDDLGenerator(“mysql”, “ddl.properties”, “mysql.properties”);
0132:         * </pre>
0133:         *  
0134:         * And to generate DDL, it should specify the printer and call generateDDL method.
0135:         * <pre>
0136:         *  generator.setPrinter(System.out);
0137:         *  Mapping mapping = new Mapping();
0138:         *  mapping.loadMapping("mapping.xml");
0139:         *  generator.generateDDL(mapping);            
0140:         * </pre>
0141:         * 
0142:         * @author <a href="mailto:leducbao AT gmail DOT com">Le Duc Bao</a>
0143:         * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
0144:         * @version $Revision: 5951 $ $Date: 2006-04-25 16:09:10 -0600 (Tue, 25 Apr 2006) $
0145:         * @since 1.1
0146:         */
0147:        public abstract class AbstractGenerator implements  Generator {
0148:            //--------------------------------------------------------------------------
0149:
0150:            /** handle all configurations (key, value). */
0151:            private final DDLGenConfiguration _configuration;
0152:
0153:            /** handle the key gen registry. */
0154:            private KeyGeneratorRegistry _keyGenRegistry;
0155:
0156:            /** handle the MappingHelper. */
0157:            private MappingHelper _mappingHelper;
0158:
0159:            /** handle the typemapper. */
0160:            private TypeMapper _typeMapper;
0161:
0162:            /** handle schema factory. */
0163:            private SchemaFactory _schemaFactory;
0164:
0165:            /** handle the _mapping document. */
0166:            private Mapping _mapping;
0167:
0168:            /** schema. */
0169:            private Schema _schema;
0170:
0171:            /** handle all resolving tables. */
0172:            private final Map _resolveTable = new HashMap();
0173:
0174:            //--------------------------------------------------------------------------
0175:
0176:            /**
0177:             * Constructor for AbstractGenerator.
0178:             * 
0179:             * @param configuration Configuration to use by the generator.
0180:             */
0181:            protected AbstractGenerator(final DDLGenConfiguration configuration) {
0182:                _configuration = configuration;
0183:            }
0184:
0185:            //--------------------------------------------------------------------------
0186:
0187:            /**
0188:             * Get configuration of generator.
0189:             * 
0190:             * @return Configuration of generator.
0191:             */
0192:            public final DDLGenConfiguration getConfiguration() {
0193:                return _configuration;
0194:            }
0195:
0196:            /**
0197:             * Set key generator registry.
0198:             * 
0199:             * @param keyGenRegistry Key generator registry.
0200:             */
0201:            public final void setKeyGenRegistry(
0202:                    final KeyGeneratorRegistry keyGenRegistry) {
0203:                _keyGenRegistry = keyGenRegistry;
0204:            }
0205:
0206:            /**
0207:             * Set mapping helper.
0208:             * 
0209:             * @param mappingHelper Mapping helper.
0210:             */
0211:            protected final void setMappingHelper(
0212:                    final MappingHelper mappingHelper) {
0213:                _mappingHelper = mappingHelper;
0214:                _mappingHelper.setTypeMapper(_typeMapper);
0215:            }
0216:
0217:            /**
0218:             * Get mapping helper.
0219:             * 
0220:             * @return Mapping helper.
0221:             */
0222:            public final MappingHelper getMappingHelper() {
0223:                return _mappingHelper;
0224:            }
0225:
0226:            /**
0227:             * Set type mapper.
0228:             * 
0229:             * @param typeMapper Type mapper.
0230:             */
0231:            public final void setTypeMapper(final TypeMapper typeMapper) {
0232:                _typeMapper = typeMapper;
0233:                _mappingHelper.setTypeMapper(_typeMapper);
0234:            }
0235:
0236:            /**
0237:             * Get type mapper.
0238:             * 
0239:             * @return Type mapper.
0240:             */
0241:            public final TypeMapper getTypeMapper() {
0242:                return _typeMapper;
0243:            }
0244:
0245:            /**
0246:             * Set schema factory.
0247:             * 
0248:             * @param schemaFactory Schema factory.
0249:             */
0250:            protected final void setSchemaFactory(
0251:                    final SchemaFactory schemaFactory) {
0252:                _schemaFactory = schemaFactory;
0253:            }
0254:
0255:            /**
0256:             * Get schema factory.
0257:             * 
0258:             * @return Schema factory.
0259:             */
0260:            public final SchemaFactory getSchemaFactory() {
0261:                return _schemaFactory;
0262:            }
0263:
0264:            /**
0265:             * Set mapping document.
0266:             * 
0267:             * @param mapping Mapping document.
0268:             */
0269:            public final void setMapping(final Mapping mapping) {
0270:                _mapping = mapping;
0271:                _mappingHelper.setMapping(_mapping);
0272:            }
0273:
0274:            /**
0275:             * Get mapping document.
0276:             * 
0277:             * @return Mapping document.
0278:             */
0279:            public final Mapping getMapping() {
0280:                return _mapping;
0281:            }
0282:
0283:            /**
0284:             * Get schema.
0285:             * 
0286:             * @return Schema
0287:             */
0288:            public final Schema getSchema() {
0289:                return _schema;
0290:            }
0291:
0292:            //--------------------------------------------------------------------------
0293:
0294:            /**
0295:             * {@inheritDoc}
0296:             */
0297:            public final void generateDDL(final OutputStream output)
0298:                    throws GeneratorException {
0299:                DDLWriter writer = new DDLWriter(output, _configuration);
0300:
0301:                // Create schema.
0302:                createSchema();
0303:
0304:                // Generate DDL.
0305:                String groupBy = _configuration.getStringValue(
0306:                        DDLGenConfiguration.GROUP_DDL_KEY,
0307:                        DDLGenConfiguration.GROUP_DDL_BY_TABLE);
0308:                if (DDLGenConfiguration.GROUP_DDL_BY_TABLE
0309:                        .equalsIgnoreCase(groupBy)) {
0310:                    generateDDLGroupByTable(writer);
0311:                } else if (DDLGenConfiguration.GROUP_DDL_BY_DDLTYPE
0312:                        .equalsIgnoreCase(groupBy)) {
0313:                    generateDDLGroupByDDLType(writer);
0314:                } else {
0315:                    throw new GeneratorException(
0316:                            "group ddl by do not support: " + groupBy);
0317:                }
0318:
0319:                writer.close();
0320:            }
0321:
0322:            /**
0323:             * Generating ddl grouped by ddl type of DDL (e.g DROP, CREATE TABLE, create 
0324:             * Primary key, create foreign key).
0325:             * 
0326:             * @param writer DDLWriter to write schema objects to.
0327:             * @throws GeneratorException If failed to generate DDL.
0328:             */
0329:            private void generateDDLGroupByDDLType(final DDLWriter writer)
0330:                    throws GeneratorException {
0331:                boolean genSchema = _configuration.getBoolValue(
0332:                        DDLGenConfiguration.GENERATE_DDL_FOR_SCHEMA_KEY, true);
0333:                boolean genDrop = _configuration.getBoolValue(
0334:                        DDLGenConfiguration.GENERATE_DDL_FOR_DROP_KEY, true);
0335:                boolean genCreate = _configuration.getBoolValue(
0336:                        DDLGenConfiguration.GENERATE_DDL_FOR_CREATE_KEY, true);
0337:                boolean genPrimaryKey = _configuration.getBoolValue(
0338:                        DDLGenConfiguration.GENERATE_DDL_FOR_PRIMARYKEY_KEY,
0339:                        true);
0340:                boolean genForeignKey = _configuration.getBoolValue(
0341:                        DDLGenConfiguration.GENERATE_DDL_FOR_FOREIRNKEY_KEY,
0342:                        true);
0343:                boolean genIndex = _configuration.getBoolValue(
0344:                        DDLGenConfiguration.GENERATE_DDL_FOR_INDEX_KEY, true);
0345:                boolean genKeyGen = _configuration.getBoolValue(
0346:                        DDLGenConfiguration.GENERATE_DDL_FOR_KEYGENERATOR_KEY,
0347:                        true);
0348:
0349:                generateHeader(writer);
0350:
0351:                //generate ddl for schema
0352:                if (genSchema) {
0353:                    _schema.toCreateDDL(writer);
0354:                }
0355:
0356:                //generate drop statemetn
0357:                if (genDrop) {
0358:                    generateDrop(writer);
0359:                }
0360:
0361:                //generate create statement
0362:                if (genCreate) {
0363:                    generateCreate(writer);
0364:                }
0365:
0366:                //generate primary key creation statement
0367:                if (genPrimaryKey) {
0368:                    generatePrimaryKey(writer);
0369:                }
0370:
0371:                //generate foreign key creation statement
0372:                if (genForeignKey) {
0373:                    generateForeignKey(writer);
0374:                }
0375:
0376:                //generate index creation statement
0377:                if (genIndex) {
0378:                    generateIndex(writer);
0379:                }
0380:
0381:                if (genKeyGen) {
0382:                    generateKeyGenerator(writer);
0383:                }
0384:            }
0385:
0386:            /**
0387:             * Generate DDL for drop statement of table.
0388:             * 
0389:             * @param writer DDLWriter to write schema objects to.
0390:             * @throws GeneratorException If failed to generate DDL.
0391:             */
0392:            public final void generateDrop(final DDLWriter writer)
0393:                    throws GeneratorException {
0394:                for (int i = 0; i < _schema.getTableCount(); i++) {
0395:                    _schema.getTable(i).toDropDDL(writer);
0396:                }
0397:            }
0398:
0399:            /**
0400:             * Generate DDL for create statementof table.
0401:             * <pre>
0402:             * CREATE TABLE prod (
0403:             *  id INTEGER NOT NULL,
0404:             *  name CHAR(16)
0405:             * );
0406:             * 
0407:             * CREATE TABLE prod_detail (
0408:             *  id INTEGER NOT NULL,
0409:             *  prod_id CHAR(16)
0410:             * );
0411:             * </pre>
0412:             * 
0413:             * @param writer DDLWriter to write schema objects to.
0414:             * @throws GeneratorException If failed to generate DDL.
0415:             */
0416:            public final void generateCreate(final DDLWriter writer)
0417:                    throws GeneratorException {
0418:                for (int i = 0; i < _schema.getTableCount(); i++) {
0419:                    _schema.getTable(i).toCreateDDL(writer);
0420:                }
0421:            }
0422:
0423:            /**
0424:             * Generate DDL for primany keys.
0425:             * 
0426:             * @param writer DDLWriter to write schema objects to.
0427:             * @throws GeneratorException If failed to generate DDL.
0428:             */
0429:            public final void generatePrimaryKey(final DDLWriter writer)
0430:                    throws GeneratorException {
0431:                for (int i = 0; i < _schema.getTableCount(); i++) {
0432:                    _schema.getTable(i).getPrimaryKey().toCreateDDL(writer);
0433:                }
0434:            }
0435:
0436:            /**
0437:             * Generate DDL for foreign keys.
0438:             * <pre>
0439:             * ALTER TABLE `prod_group` ADD CONSTRAINT `FK_prod_group_1` 
0440:             * FOREIGN KEY `FK_prod_group_1` (`id`, `name`)
0441:             * REFERENCES `category` (`id`, `name`)
0442:             * ON DELETE SET NULL
0443:             * ON UPDATE CASCADE;
0444:             * </pre>
0445:             * 
0446:             * @param writer DDLWriter to write schema objects to.
0447:             * @throws GeneratorException If failed to generate DDL.
0448:             */
0449:            public final void generateForeignKey(final DDLWriter writer)
0450:                    throws GeneratorException {
0451:                for (int i = 0; i < _schema.getTableCount(); i++) {
0452:                    createForeignKeyDDL(_schema.getTable(i), writer);
0453:                }
0454:            }
0455:
0456:            /**
0457:             * Generate DDL for indices.
0458:             * 
0459:             * @param writer DDLWriter to write schema objects to.
0460:             * @throws GeneratorException If failed to generate DDL.
0461:             */
0462:            public final void generateIndex(final DDLWriter writer)
0463:                    throws GeneratorException {
0464:                for (int i = 0; i < _schema.getTableCount(); i++) {
0465:                    createIndex(_schema.getTable(i), writer);
0466:                }
0467:            }
0468:
0469:            /**
0470:             * Generate DDL for key generators (sequence/trigger).
0471:             * 
0472:             * @param writer DDLWriter to write schema objects to.
0473:             * @throws GeneratorException If failed to generate DDL.
0474:             */
0475:            public final void generateKeyGenerator(final DDLWriter writer)
0476:                    throws GeneratorException {
0477:                for (int i = 0; i < _schema.getTableCount(); i++) {
0478:                    Table table = _schema.getTable(i);
0479:                    if (table.getKeyGenerator() != null) {
0480:                        table.getKeyGenerator().setTable(table);
0481:                        table.getKeyGenerator().toCreateDDL(writer);
0482:                    }
0483:                }
0484:            }
0485:
0486:            /**
0487:             * Generating ddl group by table.
0488:             * 
0489:             * @param writer DDLWriter to write schema objects to.
0490:             * @throws GeneratorException If failed to generate DDL.
0491:             */
0492:            private void generateDDLGroupByTable(final DDLWriter writer)
0493:                    throws GeneratorException {
0494:                boolean genSchema = _configuration.getBoolValue(
0495:                        DDLGenConfiguration.GENERATE_DDL_FOR_SCHEMA_KEY, true);
0496:                boolean genDrop = _configuration.getBoolValue(
0497:                        DDLGenConfiguration.GENERATE_DDL_FOR_DROP_KEY, true);
0498:                boolean genCreate = _configuration.getBoolValue(
0499:                        DDLGenConfiguration.GENERATE_DDL_FOR_CREATE_KEY, true);
0500:                boolean genPrimaryKey = _configuration.getBoolValue(
0501:                        DDLGenConfiguration.GENERATE_DDL_FOR_PRIMARYKEY_KEY,
0502:                        true);
0503:                boolean genForeignKey = _configuration.getBoolValue(
0504:                        DDLGenConfiguration.GENERATE_DDL_FOR_FOREIRNKEY_KEY,
0505:                        true);
0506:                boolean genIndex = _configuration.getBoolValue(
0507:                        DDLGenConfiguration.GENERATE_DDL_FOR_INDEX_KEY, true);
0508:                boolean genKeyGen = _configuration.getBoolValue(
0509:                        DDLGenConfiguration.GENERATE_DDL_FOR_KEYGENERATOR_KEY,
0510:                        true);
0511:
0512:                generateHeader(writer);
0513:
0514:                if (genSchema) {
0515:                    _schema.toCreateDDL(writer);
0516:                }
0517:
0518:                for (int i = 0; i < _schema.getTableCount(); i++) {
0519:                    Table table = _schema.getTable(i);
0520:
0521:                    if (genDrop) {
0522:                        table.toDropDDL(writer);
0523:                    }
0524:                    if (genCreate) {
0525:                        table.toCreateDDL(writer);
0526:                    }
0527:                    if (genPrimaryKey) {
0528:                        table.getPrimaryKey().toCreateDDL(writer);
0529:                    }
0530:                    if (genForeignKey) {
0531:                        createForeignKeyDDL(table, writer);
0532:                    }
0533:                    if (genIndex) {
0534:                        createIndex(table, writer);
0535:                    }
0536:                    if (genKeyGen && (table.getKeyGenerator() != null)) {
0537:                        table.getKeyGenerator().setTable(table);
0538:                        table.getKeyGenerator().toCreateDDL(writer);
0539:                    }
0540:                }
0541:            }
0542:
0543:            /**
0544:             * Generate DDL for foreign key.
0545:             * 
0546:             * @param table Table to generate DDL of foreign key for.
0547:             * @param writer DDLWriter to write schema objects to.
0548:             * @throws GeneratorException If failed to generate DDL.
0549:             */
0550:            protected final void createForeignKeyDDL(final Table table,
0551:                    final DDLWriter writer) throws GeneratorException {
0552:                for (int i = 0; i < table.getForeignKeyCount(); i++) {
0553:                    table.getForeignKey(i).toCreateDDL(writer);
0554:                }
0555:            }
0556:
0557:            /**
0558:             * Generate DDL for indices of given table.
0559:             * 
0560:             * @param table Table to generate DDL of indices for.
0561:             * @param writer DDLWriter to write schema objects to.
0562:             * @throws GeneratorException If failed to generate DDL.
0563:             */
0564:            public final void createIndex(final Table table,
0565:                    final DDLWriter writer) throws GeneratorException {
0566:                for (int i = 0; i < table.getIndexCount(); i++) {
0567:                    table.getIndex(i).toCreateDDL(writer);
0568:                }
0569:            }
0570:
0571:            //--------------------------------------------------------------------------
0572:
0573:            /**
0574:             * Generate header comment.
0575:             * 
0576:             * @param writer DDLWriter to write schema objects to.
0577:             */
0578:            public abstract void generateHeader(final DDLWriter writer);
0579:
0580:            //--------------------------------------------------------------------------
0581:
0582:            /**
0583:             * Extracting informations from mapping to schema, this is done by 3 steps.
0584:             * <ul>
0585:             *   <li>Create key generators</li>
0586:             *   <li>Create tables</li>
0587:             *   <li>Create additional tables for many-many relations</li>
0588:             * </ul>
0589:             * 
0590:             * @throws GeneratorException If failed to create schema objects.
0591:             */
0592:            public final void createSchema() throws GeneratorException {
0593:                // Create schema.
0594:                MappingRoot root = _mapping.getRoot();
0595:                _schema = _schemaFactory.createSchema();
0596:                _schema.setConfiguration(_configuration);
0597:
0598:                // Create key generators.
0599:                Enumeration ekg = root.enumerateKeyGeneratorDef();
0600:                while (ekg.hasMoreElements()) {
0601:                    KeyGeneratorDef definition = (KeyGeneratorDef) ekg
0602:                            .nextElement();
0603:                    _keyGenRegistry.createKeyGenerator(definition);
0604:                }
0605:
0606:                // Create tables.
0607:                Enumeration ec = root.enumerateClassMapping();
0608:                while (ec.hasMoreElements()) {
0609:                    ClassMapping cm = (ClassMapping) ec.nextElement();
0610:                    Table table = createTable(cm);
0611:                    if (table != null) {
0612:                        _schema.addTable(table);
0613:                    }
0614:                }
0615:
0616:                // Create N:M relation tables.
0617:                Iterator i = _resolveTable.keySet().iterator();
0618:                while (i.hasNext()) {
0619:                    ClassMapping cm = (ClassMapping) _resolveTable
0620:                            .get(i.next());
0621:                    Table table = createTable(cm);
0622:                    if (table != null) {
0623:                        _schema.addTable(table);
0624:                    }
0625:                }
0626:            }
0627:
0628:            /**
0629:             * Create table from a ClassMapping.
0630:             * 
0631:             * @param cm ClassMapping.
0632:             * @return Table schema object.
0633:             * @throws GeneratorException If failed to create schema objects.
0634:             */
0635:            private Table createTable(final ClassMapping cm)
0636:                    throws GeneratorException {
0637:                String tableName = cm.getMapTo().getTable();
0638:                if (tableName == null) {
0639:                    return null;
0640:                }
0641:
0642:                Table table = _schemaFactory.createTable();
0643:                table.setName(tableName);
0644:                table.setConfiguration(_configuration);
0645:                table.setSchema(_schema);
0646:
0647:                PrimaryKey primarykey = _schemaFactory.createPrimaryKey();
0648:                primarykey.setConfiguration(_configuration);
0649:                primarykey.setTable(table);
0650:                primarykey.setName("pk_" + tableName);
0651:                table.setPrimaryKey(primarykey);
0652:
0653:                // Return if there are no field in the table.
0654:                if (cm.getClassChoice() == null) {
0655:                    return table;
0656:                }
0657:
0658:                boolean isUseFieldIdentity = _mappingHelper
0659:                        .isUseFieldIdentity(cm);
0660:                Enumeration ef = cm.getClassChoice().enumerateFieldMapping();
0661:
0662:                // Process key generator.
0663:                String keygenerator = cm.getKeyGenerator();
0664:                KeyGenerator keyGen = null;
0665:                if (keygenerator != null) {
0666:                    keyGen = _keyGenRegistry.getKeyGenerator(keygenerator
0667:                            .toUpperCase());
0668:                }
0669:                table.setKeyGenerator(keyGen);
0670:
0671:                while (ef.hasMoreElements()) {
0672:                    FieldMapping fm = (FieldMapping) ef.nextElement();
0673:
0674:                    // Skip if <sql> tag is not defined and we have no mapping to DB.
0675:                    if (fm.getSql() == null) {
0676:                        continue;
0677:                    }
0678:
0679:                    boolean isFieldIdentity = fm.getIdentity();
0680:                    if (!isUseFieldIdentity) {
0681:                        isFieldIdentity = _mappingHelper.isIdentity(cm, fm);
0682:                    }
0683:
0684:                    // Checke for many-key, many-table definition.
0685:                    if (fm.getSql().getManyTable() != null) {
0686:                        // Generate resolving table for many-many relationship
0687:                        addResolveField(fm, cm);
0688:                    }
0689:
0690:                    // Process column creation if sql name is defined.
0691:                    String[] sqlnames = fm.getSql().getName();
0692:                    if ((sqlnames != null) && (sqlnames.length > 0)
0693:                            && (fm.getSql().getManyTable() == null)) {
0694:                        // Normal case, using sql name as column name.
0695:                        String sqltype = fm.getSql().getType();
0696:
0697:                        TypeInfo typeInfo = null;
0698:                        ClassMapping cmRef = null;
0699:                        String[] refIdTypes = null;
0700:                        boolean isUseReferenceType = false;
0701:
0702:                        // Get type info.
0703:                        if (sqltype != null) {
0704:                            typeInfo = _typeMapper.getType(sqltype);
0705:                        }
0706:
0707:                        // If typeInfo is null, this table has a reference to another one.
0708:                        if (typeInfo == null) {
0709:                            cmRef = _mappingHelper.getClassMappingByName(fm
0710:                                    .getType());
0711:                            // Use field type if reference class could not be found.
0712:                            if (cmRef == null) {
0713:                                typeInfo = _typeMapper.getType(fm.getType());
0714:
0715:                                if (typeInfo == null) {
0716:                                    throw new TypeNotFoundException(
0717:                                            "can not resolve type "
0718:                                                    + fm.getType()
0719:                                                    + " in class '"
0720:                                                    + cm.getName() + "'");
0721:                                }
0722:                            } else {
0723:                                isUseReferenceType = true;
0724:                                refIdTypes = _mappingHelper
0725:                                        .resolveTypeReferenceForIds(fm
0726:                                                .getType());
0727:
0728:                                // If number of reference table's Id's differ from number of
0729:                                // field elements.
0730:                                if (refIdTypes.length != sqlnames.length) {
0731:                                    throw new TypeNotFoundException(
0732:                                            "number of reference table's Id differs"
0733:                                                    + " to number of field elements '"
0734:                                                    + fm.getName()
0735:                                                    + "' of class '"
0736:                                                    + cm.getName() + "'"
0737:                                                    + refIdTypes.length + ","
0738:                                                    + sqlnames.length);
0739:                                }
0740:                            }
0741:                        }
0742:
0743:                        // Create fields.
0744:                        for (int i = 0; i < sqlnames.length; i++) {
0745:                            Field field = _schemaFactory.createField();
0746:                            field.setConfiguration(_configuration);
0747:
0748:                            if (isUseReferenceType) {
0749:                                // Each sqlname correspond to a identity of the reference table.
0750:                                // Should be able to get the original type of the reference 
0751:                                // field.
0752:                                typeInfo = _typeMapper.getType(refIdTypes[i]);
0753:                                if (typeInfo == null) {
0754:                                    throw new TypeNotFoundException(
0755:                                            "can not find reference type "
0756:                                                    + refIdTypes[i]
0757:                                                    + " of class "
0758:                                                    + cm.getName());
0759:                                }
0760:                            }
0761:
0762:                            // process attributes of field
0763:                            field.setName(sqlnames[i]);
0764:                            field.setTable(table);
0765:                            field.setType(typeInfo);
0766:                            field.setIdentity(isFieldIdentity);
0767:                            field.setRequired(fm.getRequired());
0768:                            field.setKeyGenerator(keyGen);
0769:
0770:                            table.addField(field);
0771:
0772:                            if (isFieldIdentity) {
0773:                                primarykey.addField(field);
0774:                            }
0775:                        }
0776:
0777:                        // Create foreign keys.
0778:                        if (isUseReferenceType) {
0779:                            addOneOneForeignKey(table, fm);
0780:                        }
0781:                    }
0782:                }
0783:
0784:                // Process extends, if extends is defined.
0785:                processExtendedClass(table, cm);
0786:
0787:                return table;
0788:            }
0789:
0790:            /**
0791:             * Extract identities from extended ClassMapping and add them to table.
0792:             * 
0793:             * @param table Table to add identities of extended mapping to.
0794:             * @param cm ClassMapping of table to extract get mappings from.
0795:             * @throws GeneratorException throw exception if key-gen is not found.
0796:             */
0797:            private void processExtendedClass(final Table table,
0798:                    final ClassMapping cm) throws GeneratorException {
0799:                Object extendClass = cm.getExtends();
0800:                if (extendClass == null) {
0801:                    return;
0802:                }
0803:
0804:                ClassMapping extendCm = (ClassMapping) extendClass;
0805:                String[] childIds = _mappingHelper.getClassMappingSqlIdentity(
0806:                        cm, false);
0807:
0808:                if (childIds.length != 0) {
0809:                    // Check consistency.
0810:                    String[] childTypes = _mappingHelper
0811:                            .resolveTypeReferenceForIds(cm);
0812:                    String[] parentTypes = _mappingHelper
0813:                            .resolveTypeReferenceForIds(extendCm);
0814:
0815:                    if (childTypes.length != parentTypes.length) {
0816:                        throw new GeneratorException(
0817:                                "Cannot resolve type for class '"
0818:                                        + cm.getName()
0819:                                        + "' from extend class '"
0820:                                        + extendCm.getName() + "'");
0821:                    }
0822:                    for (int i = 0; i < childTypes.length; i++) {
0823:                        if (!childTypes[i].equalsIgnoreCase(parentTypes[i])) {
0824:                            throw new GeneratorException(
0825:                                    "Cannot resolve type for class '"
0826:                                            + cm.getName()
0827:                                            + "' from extend class '"
0828:                                            + extendCm.getName() + "'");
0829:                        }
0830:                    }
0831:                    return;
0832:                }
0833:
0834:                boolean isUseFieldIdentity = _mappingHelper
0835:                        .isUseFieldIdentity(extendCm);
0836:                Enumeration extendEf = extendCm.getClassChoice()
0837:                        .enumerateFieldMapping();
0838:
0839:                // Process key generator.
0840:                String keygenerator = extendCm.getKeyGenerator();
0841:                KeyGenerator keyGen = null;
0842:                if (keygenerator != null) {
0843:                    keyGen = _keyGenRegistry.getKeyGenerator(keygenerator
0844:                            .toUpperCase());
0845:                }
0846:                table.setKeyGenerator(keyGen);
0847:
0848:                while (extendEf.hasMoreElements()) {
0849:                    FieldMapping extendFm = (FieldMapping) extendEf
0850:                            .nextElement();
0851:
0852:                    // Skip if <sql> tag is not defined.
0853:                    if (extendFm.getSql() == null) {
0854:                        continue;
0855:                    }
0856:
0857:                    boolean isFieldIdentity = extendFm.getIdentity();
0858:                    if (!isUseFieldIdentity) {
0859:                        isFieldIdentity = _mappingHelper.isIdentity(extendCm,
0860:                                extendFm);
0861:                    }
0862:
0863:                    // Checke for many-key, many-table definition.
0864:                    if (isFieldIdentity
0865:                            && extendFm.getSql().getManyKeyCount() <= 0) {
0866:                        // Column is defiend as normal column in child, but it is id which is
0867:                        // inherited from parent.
0868:                        if (mergeIfDefInBothClasses(table, cm, extendFm)) {
0869:                            continue;
0870:                        }
0871:
0872:                        String[] sqlnames = extendFm.getSql().getName();
0873:                        String sqltype = extendFm.getSql().getType();
0874:
0875:                        TypeInfo typeInfo = null;
0876:                        ClassMapping cmRef = null;
0877:                        String[] refIdTypes = null;
0878:                        boolean isUseReferenceType = false;
0879:
0880:                        if (sqltype != null) {
0881:                            typeInfo = _typeMapper.getType(sqltype);
0882:                        }
0883:
0884:                        // If typeInfo is null, this table has a reference to another one.
0885:                        if (typeInfo == null) {
0886:                            cmRef = _mappingHelper
0887:                                    .getClassMappingByName(extendFm.getType());
0888:                            // If cmRef is null, the reference class could not be found.
0889:                            if (cmRef == null) {
0890:                                typeInfo = _typeMapper.getType(extendFm
0891:                                        .getType());
0892:
0893:                                if (typeInfo == null) {
0894:                                    throw new TypeNotFoundException(
0895:                                            "can not resolve type "
0896:                                                    + extendFm.getType());
0897:                                }
0898:                            } else {
0899:                                isUseReferenceType = true;
0900:                                refIdTypes = _mappingHelper
0901:                                        .resolveTypeReferenceForIds(extendFm
0902:                                                .getType());
0903:
0904:                                // If number of reference table's Ids differ from number of
0905:                                // field elements.
0906:                                if (refIdTypes.length != sqlnames.length) {
0907:                                    throw new TypeNotFoundException(
0908:                                            "number of reference table's Id differs"
0909:                                                    + " to number of field elements '"
0910:                                                    + extendFm.getName()
0911:                                                    + "' of class '"
0912:                                                    + extendCm.getName() + "'"
0913:                                                    + refIdTypes.length + ","
0914:                                                    + sqlnames.length);
0915:                                }
0916:                            }
0917:                        }
0918:
0919:                        // Create fields.
0920:                        for (int i = 0; i < sqlnames.length; i++) {
0921:                            Field field = _schemaFactory.createField();
0922:                            field.setConfiguration(_configuration);
0923:
0924:                            if (isUseReferenceType) {
0925:                                // Each sqlname is correspond to an identity of the reference
0926:                                // table so, it should be possible to get the original type of
0927:                                // the reference field.
0928:                                typeInfo = _typeMapper.getType(refIdTypes[i]);
0929:                                if (typeInfo == null) {
0930:                                    throw new TypeNotFoundException(
0931:                                            "can not find reference type "
0932:                                                    + refIdTypes[i]
0933:                                                    + " of class "
0934:                                                    + extendCm.getName());
0935:                                }
0936:                            }
0937:
0938:                            field.setName(sqlnames[i]);
0939:                            field.setTable(table);
0940:                            field.setType(typeInfo);
0941:                            field.setIdentity(isFieldIdentity);
0942:                            field.setKeyGenerator(keyGen);
0943:
0944:                            if (isFieldIdentity) {
0945:                                table.getPrimaryKey().addField(field);
0946:                            }
0947:
0948:                            table.addField(field);
0949:                        }
0950:                    }
0951:                }
0952:
0953:                // Process extends.
0954:                if (extendCm.getExtends() != null) {
0955:                    processExtendedClass(table, extendCm);
0956:                }
0957:            }
0958:
0959:            /**
0960:             * This function is used to merge a table if it is mapped to many classes.
0961:             * 
0962:             * @param table Table to merge.
0963:             * @param cm ClassMapping of table.
0964:             * @param extendFm FieldMapping of extended class to be merged into table.
0965:             * @return <code>true</code> if column is defiend as normal column in child, but is
0966:             *         identity which is inherited from parent. 
0967:             */
0968:            private boolean mergeIfDefInBothClasses(final Table table,
0969:                    final ClassMapping cm, final FieldMapping extendFm) {
0970:                Enumeration ef = cm.getClassChoice().enumerateFieldMapping();
0971:
0972:                while (ef.hasMoreElements()) {
0973:                    FieldMapping fm = (FieldMapping) ef.nextElement();
0974:                    String fname = fm.getName();
0975:                    // If extend field has the same name with one of parent's fields.
0976:                    if (fname != null
0977:                            && fname.equalsIgnoreCase(extendFm.getName())) {
0978:                        if (fm.getSql() == null) {
0979:                            continue;
0980:                        }
0981:                        String[] sqlnames = fm.getSql().getName();
0982:                        for (int i = 0; i < sqlnames.length; i++) {
0983:                            table.getField(sqlnames[i]).setIdentity(true);
0984:                        }
0985:                        return true;
0986:                    }
0987:                }
0988:
0989:                return false;
0990:            }
0991:
0992:            /**
0993:             * Add foreign key for 1:1 relations to table schema object.
0994:             * 
0995:             * @param table Table to add foreign key to.
0996:             * @param fm FieldMapping of relation.
0997:             * @throws GeneratorException If failed to create foreign key schema object.
0998:             */
0999:            private void addOneOneForeignKey(final Table table,
1000:                    final FieldMapping fm) throws GeneratorException {
1001:                ForeignKey fk = _schemaFactory.createForeignKey();
1002:                fk.setConfiguration(_configuration);
1003:
1004:                fk.setTable(table);
1005:                fk.setName(table.getName() + "_" + fm.getName());
1006:
1007:                String[] fieldNames = fm.getSql().getName();
1008:                for (int i = 0; i < fieldNames.length; i++) {
1009:                    for (int j = 0; j < table.getFieldCount(); j++) {
1010:                        Field field = table.getField(j);
1011:                        if (fieldNames[i].equals(field.getName())) {
1012:                            fk.addField(field);
1013:                        }
1014:                    }
1015:                }
1016:
1017:                ClassMapping cm = _mappingHelper.getClassMappingByName(fm
1018:                        .getType());
1019:
1020:                if (cm == null) {
1021:                    throw new GeneratorException("can not find class "
1022:                            + fm.getType());
1023:                }
1024:
1025:                String referenceTableName = cm.getMapTo().getTable();
1026:                Table referenceTable = null;
1027:                referenceTable = table.getSchema().getTable(referenceTableName);
1028:                fk.setReferenceTable(referenceTable);
1029:
1030:                String[] manykeys = fm.getSql().getManyKey();
1031:                if (manykeys == null || manykeys.length == 0) {
1032:                    manykeys = _mappingHelper.getClassMappingSqlIdentity(cm,
1033:                            true);
1034:                }
1035:                for (int i = 0; i < manykeys.length; i++) {
1036:                    for (int j = 0; j < referenceTable.getFieldCount(); j++) {
1037:                        Field field = referenceTable.getField(j);
1038:                        if (manykeys[i].equals(field.getName())) {
1039:                            fk.addReferenceField(field);
1040:                        }
1041:                    }
1042:                }
1043:
1044:                fk.setRelationType(ForeignKey.ONE_ONE);
1045:                table.addForeignKey(fk);
1046:            }
1047:
1048:            /**
1049:             * Add column for a resolving table which is required by M:N relationship.
1050:             * 
1051:             * @param fm FieldMapping.
1052:             * @param cm ClassMapping.
1053:             */
1054:            private void addResolveField(final FieldMapping fm,
1055:                    final ClassMapping cm) {
1056:                String keyGen = cm.getKeyGenerator();
1057:                ClassMapping resolveCm = null;
1058:
1059:                // Get table, if not existe, create one.
1060:                if (_resolveTable.containsKey(fm.getSql().getManyTable())) {
1061:                    resolveCm = (ClassMapping) _resolveTable.get(fm.getSql()
1062:                            .getManyTable());
1063:                } else {
1064:                    resolveCm = new ClassMapping();
1065:                    resolveCm.setName(fm.getSql().getManyTable());
1066:                    resolveCm.setKeyGenerator(keyGen);
1067:
1068:                    MapTo mapto = new MapTo();
1069:                    mapto.setTable(fm.getSql().getManyTable());
1070:                    resolveCm.setMapTo(mapto);
1071:                    _resolveTable.put(fm.getSql().getManyTable(), resolveCm);
1072:                }
1073:
1074:                FieldMapping resolveFm = new FieldMapping();
1075:                resolveFm.setIdentity(true);
1076:                resolveFm.setName(cm.getMapTo().getTable());
1077:                resolveFm.setType(cm.getName());
1078:
1079:                ClassChoice cc = resolveCm.getClassChoice();
1080:                if (cc == null) {
1081:                    cc = new ClassChoice();
1082:                    resolveCm.setClassChoice(cc);
1083:                }
1084:                cc.addFieldMapping(resolveFm);
1085:
1086:                Sql sql = new Sql();
1087:                String[] sqlname = fm.getSql().getManyKey();
1088:                if (sqlname == null || sqlname.length == 0) {
1089:                    _mappingHelper.getClassMappingSqlIdentity(cm, true);
1090:                }
1091:                sql.setName(sqlname);
1092:                resolveFm.setSql(sql);
1093:            }
1094:
1095:            //--------------------------------------------------------------------------
1096:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.