Source Code Cross Referenced for DDLGenerator.java in  » GIS » deegree » org » deegree » tools » datastore » 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 » GIS » deegree » org.deegree.tools.datastore 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/tools/datastore/DDLGenerator.java $
0002:        /*----------------    FILE HEADER  ------------------------------------------
0003:
0004:         This file is part of deegree.
0005:         Copyright (C) 2001-2008 by:
0006:         EXSE, Department of Geography, University of Bonn
0007:         http://www.giub.uni-bonn.de/deegree/
0008:         lat/lon GmbH
0009:         http://www.lat-lon.de
0010:
0011:         This library is free software; you can redistribute it and/or
0012:         modify it under the terms of the GNU Lesser General Public
0013:         License as published by the Free Software Foundation; either
0014:         version 2.1 of the License, or (at your option) any later version.
0015:
0016:         This library is distributed in the hope that it will be useful,
0017:         but WITHOUT ANY WARRANTY; without even the implied warranty of
0018:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019:         Lesser General Public License for more details.
0020:
0021:         You should have received a copy of the GNU Lesser General Public
0022:         License along with this library; if not, write to the Free Software
0023:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0024:
0025:         Contact:
0026:
0027:         Andreas Poth
0028:         lat/lon GmbH
0029:         Aennchenstraße 19
0030:         53177 Bonn
0031:         Germany
0032:         E-Mail: poth@lat-lon.de
0033:
0034:         Prof. Dr. Klaus Greve
0035:         Department of Geography
0036:         University of Bonn
0037:         Meckenheimer Allee 166
0038:         53115 Bonn
0039:         Germany
0040:         E-Mail: greve@giub.uni-bonn.de
0041:        
0042:         ---------------------------------------------------------------------------*/
0043:        package org.deegree.tools.datastore;
0044:
0045:        import java.io.File;
0046:        import java.io.FileWriter;
0047:        import java.io.IOException;
0048:        import java.io.PrintWriter;
0049:        import java.net.MalformedURLException;
0050:        import java.net.URL;
0051:        import java.util.ArrayList;
0052:        import java.util.Collection;
0053:        import java.util.HashMap;
0054:        import java.util.HashSet;
0055:        import java.util.Iterator;
0056:        import java.util.LinkedHashMap;
0057:        import java.util.Map;
0058:        import java.util.Set;
0059:
0060:        import org.deegree.datatypes.Types;
0061:        import org.deegree.datatypes.UnknownTypeException;
0062:        import org.deegree.framework.xml.XMLParsingException;
0063:        import org.deegree.framework.xml.schema.XMLSchemaException;
0064:        import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
0065:        import org.deegree.io.datastore.schema.MappedFeatureType;
0066:        import org.deegree.io.datastore.schema.MappedGMLId;
0067:        import org.deegree.io.datastore.schema.MappedGMLSchema;
0068:        import org.deegree.io.datastore.schema.MappedGMLSchemaDocument;
0069:        import org.deegree.io.datastore.schema.MappedGeometryPropertyType;
0070:        import org.deegree.io.datastore.schema.MappedPropertyType;
0071:        import org.deegree.io.datastore.schema.MappedSimplePropertyType;
0072:        import org.deegree.io.datastore.schema.TableRelation;
0073:        import org.deegree.io.datastore.schema.content.MappingField;
0074:        import org.deegree.io.datastore.schema.content.MappingGeometryField;
0075:        import org.deegree.io.datastore.schema.content.SimpleContent;
0076:        import org.deegree.io.datastore.sql.idgenerator.DBSeqIdGenerator;
0077:        import org.deegree.model.crs.UnknownCRSException;
0078:        import org.deegree.model.feature.schema.FeatureType;
0079:        import org.deegree.model.feature.schema.PropertyType;
0080:        import org.xml.sax.SAXException;
0081:
0082:        /**
0083:         * Abstract base class for DDL generation from annotated GML schema files.
0084:         * <p>
0085:         * This abstract base class only implements the functionality needed to retrieve the necessary
0086:         * tables and columns used in an annotated GML schema. Some DDL generation may be dependent on the
0087:         * specific SQL backend to be used, so this is implemented in concrete extensions of this class.
0088:         * 
0089:         * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
0090:         * @author last edited by: $Author: apoth $
0091:         * 
0092:         * @version $Revision: 9346 $, $Date: 2007-12-27 08:39:07 -0800 (Thu, 27 Dec 2007) $
0093:         */
0094:        public abstract class DDLGenerator {
0095:
0096:            protected static final String FT_PREFIX = "FT_";
0097:
0098:            protected static final int FEATURE_TYPE_TABLE = 0;
0099:
0100:            protected static final int JOIN_TABLE = 1;
0101:
0102:            protected static final int MULTI_PROPERTY_TABLE = 2;
0103:
0104:            protected MappedGMLSchema schema;
0105:
0106:            // key type: String (table names), value type: TableDefinition
0107:            protected Map<String, TableDefinition> tables = new HashMap<String, TableDefinition>();
0108:
0109:            // names of sequences (for id generation)
0110:            protected Set<String> sequences = new HashSet<String>();
0111:
0112:            /**
0113:             * Generates the DDL statements necessary for the creation of the given table definition. Must
0114:             * be overwritten by the concrete implementation.
0115:             * 
0116:             * @param table
0117:             * @return the DDL statements necessary for the creation of the given table definition
0118:             */
0119:            protected abstract StringBuffer generateCreateTableStmt(
0120:                    TableDefinition table);
0121:
0122:            /**
0123:             * Generates the DDL statements necessary for the creation of standard indexes for the given
0124:             * table definition. Must be overwritten by the concrete implementation.
0125:             * 
0126:             * @param table
0127:             * @return the DDL statements necessary for the creation of standard indexes for the given table
0128:             *         definition
0129:             */
0130:            protected abstract StringBuffer generateCreateIndexStmts(
0131:                    TableDefinition table);
0132:
0133:            /**
0134:             * Generates the DDL statements necessary for the creation of the given sequence. May be
0135:             * overwritten by a concrete implementation.
0136:             * 
0137:             * @param sequenceName
0138:             * @return the DDL statements necessary for the creation of the given sequence definition
0139:             */
0140:            protected StringBuffer generateCreateSequenceStmt(
0141:                    String sequenceName) {
0142:                StringBuffer sb = new StringBuffer("CREATE SEQUENCE ");
0143:                sb.append(sequenceName);
0144:                sb.append(";\n");
0145:                return sb;
0146:            }
0147:
0148:            /**
0149:             * Generates the DDL statements necessary for the removal of the given table definition. May be
0150:             * overwritten by a concrete implementation.
0151:             * 
0152:             * @param table
0153:             * @return the DDL statements necessary for the removal of the given table definition
0154:             */
0155:            protected StringBuffer generateDropTableStmt(TableDefinition table) {
0156:                StringBuffer sb = new StringBuffer();
0157:                sb.append("DROP TABLE ");
0158:                sb.append(table.getName());
0159:                sb.append(" CASCADE;\n");
0160:                return sb;
0161:            }
0162:
0163:            /**
0164:             * Generates the DDL statements necessary for the dropping of standard indexes for the given
0165:             * table definition. May be overwritten by a concrete implementation.
0166:             * 
0167:             * @param table
0168:             * @return the DDL statements necessary for the dropping of standard indexes for the given table
0169:             *         definition
0170:             */
0171:            protected StringBuffer generateDropIndexStmts(TableDefinition table) {
0172:                StringBuffer sb = new StringBuffer();
0173:
0174:                // build drop statements for geometry indexes
0175:                Collection<ColumnDefinition> geometryColumns = new ArrayList<ColumnDefinition>();
0176:                for (ColumnDefinition column : table.getColumns()) {
0177:                    if (column.isGeometry()) {
0178:                        geometryColumns.add(column);
0179:                    }
0180:                }
0181:
0182:                Iterator<ColumnDefinition> iter = geometryColumns.iterator();
0183:                int spatialIdxCnt = 1;
0184:                while (iter.hasNext()) {
0185:                    iter.next();
0186:                    sb.append("DROP INDEX ");
0187:                    sb.append(table.getName() + (spatialIdxCnt++));
0188:                    sb.append("_SPATIAL_IDX;");
0189:                    sb.append('\n');
0190:                }
0191:
0192:                // build table type specific drop index statements
0193:                switch (table.getType()) {
0194:                case JOIN_TABLE: {
0195:                    // create an index on every column
0196:                    ColumnDefinition[] columns = table.getColumns();
0197:                    for (int i = 0; i < columns.length; i++) {
0198:                        sb.append("DROP INDEX ");
0199:                        sb.append(table.getName().toUpperCase());
0200:                        sb.append('_');
0201:                        sb.append(columns[i].getName());
0202:                        sb.append(';');
0203:                        sb.append('\n');
0204:                    }
0205:                    break;
0206:                }
0207:                default: {
0208:                    break;
0209:                }
0210:                }
0211:                return sb;
0212:            }
0213:
0214:            /**
0215:             * Generates the DDL statements necessary for the removal of the given sequence. May be
0216:             * overwritten by a concrete implementation.
0217:             * 
0218:             * @param sequenceName
0219:             * @return the DDL statements necessary for the removal of the given sequence definition
0220:             */
0221:            protected StringBuffer generateDropSequenceStmt(String sequenceName) {
0222:                StringBuffer sb = new StringBuffer("DROP SEQUENCE ");
0223:                sb.append(sequenceName);
0224:                sb.append(";\n");
0225:                return sb;
0226:            }
0227:
0228:            /**
0229:             * Creates a new instance of <code>DDLGenerator</code> from the given parameters.
0230:             * 
0231:             * @param schemaURL
0232:             * @throws MalformedURLException
0233:             * @throws IOException
0234:             * @throws SAXException
0235:             * @throws XMLParsingException
0236:             * @throws XMLSchemaException
0237:             * @throws UnknownCRSException
0238:             */
0239:            protected DDLGenerator(URL schemaURL) throws MalformedURLException,
0240:                    IOException, SAXException, XMLParsingException,
0241:                    XMLSchemaException, UnknownCRSException {
0242:
0243:                System.out.println(Messages.format("LOADING_SCHEMA_FILE",
0244:                        schemaURL));
0245:                MappedGMLSchemaDocument schemaDoc = new MappedGMLSchemaDocument();
0246:                schemaDoc.load(schemaURL);
0247:                schema = schemaDoc.parseMappedGMLSchema();
0248:                FeatureType[] featureTypes = schema.getFeatureTypes();
0249:                int concreteCount = 0;
0250:                for (int i = 0; i < featureTypes.length; i++) {
0251:                    if (!featureTypes[i].isAbstract()) {
0252:                        concreteCount++;
0253:                    }
0254:                }
0255:                System.out.println(Messages.format("SCHEMA_INFO", new Integer(
0256:                        featureTypes.length), new Integer(featureTypes.length
0257:                        - concreteCount), new Integer(concreteCount)));
0258:                System.out.println(Messages.getString("RETRIEVING_TABLES"));
0259:                buildTableMap();
0260:            }
0261:
0262:            /**
0263:             * Returns all table definitions of the given type.
0264:             * 
0265:             * @param type
0266:             *            FEATURE_TYPE_TABLE, JOIN_TABLE or MULTI_PROPERTY_TABLE
0267:             * @return all table definitions of the given type.
0268:             */
0269:            protected TableDefinition[] getTables(int type) {
0270:                Collection<TableDefinition> tableList = new ArrayList<TableDefinition>();
0271:                Iterator<String> iter = this .tables.keySet().iterator();
0272:                while (iter.hasNext()) {
0273:                    String tableName = iter.next();
0274:                    TableDefinition table = this .tables.get(tableName);
0275:                    if (table.getType() == type) {
0276:                        tableList.add(table);
0277:                    }
0278:                }
0279:                return tableList.toArray(new TableDefinition[tableList.size()]);
0280:            }
0281:
0282:            /**
0283:             * Returns the table definition for the table with the given name. If no such definition exists,
0284:             * a new table definition is created and added to the internal <code>tables</code> map.
0285:             * 
0286:             * @param tableName
0287:             *            table definition to look up
0288:             * @param type
0289:             *            type of the table (only respected, if a new TableDefinition instance is created)
0290:             * @return the table definition for the table with the given name.
0291:             */
0292:            private TableDefinition lookupTableDefinition(String tableName,
0293:                    int type) {
0294:                TableDefinition table = this .tables.get(tableName);
0295:                if (table == null) {
0296:                    table = new TableDefinition(tableName, type);
0297:                    this .tables.put(tableName, table);
0298:                }
0299:                return table;
0300:            }
0301:
0302:            /**
0303:             * Collects the referenced tables and their columns from the input schema. Builds the member map
0304:             * <code>tables</code> from this data.
0305:             */
0306:            private void buildTableMap() {
0307:                FeatureType[] featureTypes = schema.getFeatureTypes();
0308:                for (int i = 0; i < featureTypes.length; i++) {
0309:                    if (!featureTypes[i].isAbstract()) {
0310:                        buildTableMap((MappedFeatureType) featureTypes[i]);
0311:                    }
0312:                }
0313:            }
0314:
0315:            /**
0316:             * Collects the tables and their columns used in the annotation of the given feature type.
0317:             * Builds the member map <code>tables</code> from this data.
0318:             * 
0319:             * @param featureType
0320:             *            feature type to process
0321:             */
0322:            private void buildTableMap(MappedFeatureType featureType) {
0323:                TableDefinition table = lookupTableDefinition(featureType
0324:                        .getTable(), FEATURE_TYPE_TABLE);
0325:
0326:                MappedGMLId gmlId = featureType.getGMLId();
0327:                addGMLIdColumns(gmlId, table);
0328:
0329:                if (gmlId.getIdGenerator() instanceof  DBSeqIdGenerator) {
0330:                    extractSequence((DBSeqIdGenerator) featureType.getGMLId()
0331:                            .getIdGenerator());
0332:                }
0333:
0334:                PropertyType[] properties = featureType.getProperties();
0335:                for (int i = 0; i < properties.length; i++) {
0336:                    MappedPropertyType property = (MappedPropertyType) properties[i];
0337:                    if (property instanceof  MappedSimplePropertyType) {
0338:                        buildTableMap((MappedSimplePropertyType) property,
0339:                                table);
0340:                    } else if (property instanceof  MappedGeometryPropertyType) {
0341:                        buildTableMap((MappedGeometryPropertyType) property,
0342:                                table);
0343:                    } else if (property instanceof  MappedFeaturePropertyType) {
0344:                        buildTableMap((MappedFeaturePropertyType) property,
0345:                                table);
0346:                    } else {
0347:                        throw new RuntimeException(Messages.format(
0348:                                "ERROR_UNEXPECTED_PROPERTY_TYPE", property
0349:                                        .getClass().getName()));
0350:                    }
0351:                }
0352:            }
0353:
0354:            /**
0355:             * Adds the name of the sequence that the given {@link DBSeqIdGenerator} refers to.
0356:             * 
0357:             * @param idGenerator
0358:             *            generator instance
0359:             */
0360:            private void extractSequence(DBSeqIdGenerator idGenerator) {
0361:                this .sequences.add(idGenerator.getSequenceName());
0362:            }
0363:
0364:            /**
0365:             * Adds the columns used in the given <code>MappedGMLId</code> to the also given
0366:             * <code>TableDefinition</code>.
0367:             * 
0368:             * @param gmlId
0369:             *            columns are taken from this gmlId mapping
0370:             * @param table
0371:             *            columns are added to this table definition
0372:             */
0373:            private void addGMLIdColumns(MappedGMLId gmlId,
0374:                    TableDefinition table) {
0375:                MappingField[] idFields = gmlId.getIdFields();
0376:                for (int i = 0; i < idFields.length; i++) {
0377:                    ColumnDefinition column = new ColumnDefinition(idFields[i]
0378:                            .getField(), idFields[i].getType(), false, true,
0379:                            false, -1);
0380:                    table.addColumn(column);
0381:                }
0382:            }
0383:
0384:            /**
0385:             * Collects the tables and their columns used in the annotation of the given simple property
0386:             * type. Builds the <code>table</code> member map from this data.
0387:             * <p>
0388:             * If the data for the property is stored in a related table, the table and column information
0389:             * used on the path to this table is also added to the <code>tables</code> member map.
0390:             * 
0391:             * @param simpleProperty
0392:             *            simple property type to process
0393:             * @param table
0394:             *            table definition associated with the property definition
0395:             */
0396:            private void buildTableMap(MappedSimplePropertyType simpleProperty,
0397:                    TableDefinition table) {
0398:                Collection<ColumnDefinition> newColumns = new ArrayList<ColumnDefinition>();
0399:                // array must always have length 1
0400:                TableRelation[] relations = simpleProperty.getTableRelations();
0401:                if (simpleProperty.getMaxOccurs() != 1
0402:                        && (relations == null || relations.length < 1)) {
0403:                    throw new RuntimeException(Messages.format(
0404:                            "ERROR_INVALID_PROPERTY_DEFINITION", simpleProperty
0405:                                    .getName()));
0406:                }
0407:
0408:                SimpleContent content = simpleProperty.getContent();
0409:                if (content instanceof  MappingField) {
0410:                    MappingField mf = (MappingField) content;
0411:                    if (relations == null || relations.length == 0) {
0412:                        newColumns.add(new ColumnDefinition(mf.getField(), mf
0413:                                .getType(), simpleProperty.getMinOccurs() == 0,
0414:                                false, -1));
0415:                    } else {
0416:                        TableRelation firstRelation = relations[0];
0417:                        MappingField[] fromFields = firstRelation
0418:                                .getFromFields();
0419:                        for (int i = 0; i < fromFields.length; i++) {
0420:                            MappingField fromField = fromFields[i];
0421:                            newColumns.add(new ColumnDefinition(fromField
0422:                                    .getField(), fromField.getType(), false,
0423:                                    false, -1));
0424:                        }
0425:                        buildTableMap(relations, mf);
0426:                    }
0427:                } else {
0428:                    String msg = "Ignoring property '" + simpleProperty
0429:                            + "' - has virtual content.";
0430:                    System.out.println(msg);
0431:                }
0432:                table.addColumns(newColumns);
0433:            }
0434:
0435:            /**
0436:             * Collects the tables and their columns used in the annotation of the given geometry property
0437:             * type. Builds the <code>table</code> member map from this data.
0438:             * <p>
0439:             * If the geometry for the property is stored in a related table, the table and column
0440:             * information used on the path to this table is also added to the <code>tables</code> member
0441:             * map.
0442:             * 
0443:             * @param geometryProperty
0444:             *            feature property type to process
0445:             * @param table
0446:             *            table definition associated with the property definition
0447:             */
0448:            private void buildTableMap(
0449:                    MappedGeometryPropertyType geometryProperty,
0450:                    TableDefinition table) {
0451:                Collection<ColumnDefinition> newColumns = new ArrayList<ColumnDefinition>();
0452:                TableRelation[] relations = geometryProperty
0453:                        .getTableRelations();
0454:                if (geometryProperty.getMaxOccurs() != 1
0455:                        && (relations == null || relations.length < 1)) {
0456:                    throw new RuntimeException(Messages.format(
0457:                            "ERROR_INVALID_PROPERTY_DEFINITION",
0458:                            geometryProperty.getName()));
0459:                }
0460:                if (relations == null || relations.length == 0) {
0461:                    newColumns.add(new ColumnDefinition(geometryProperty
0462:                            .getMappingField().getField(), geometryProperty
0463:                            .getMappingField().getType(), geometryProperty
0464:                            .getMinOccurs() == 0, true, geometryProperty
0465:                            .getMappingField().getSRS()));
0466:                } else {
0467:                    TableRelation firstRelation = relations[0];
0468:                    MappingField[] fromFields = firstRelation.getFromFields();
0469:                    for (int i = 0; i < fromFields.length; i++) {
0470:                        MappingField fromField = fromFields[i];
0471:                        newColumns.add(new ColumnDefinition(fromField
0472:                                .getField(), fromField.getType(), false, true,
0473:                                geometryProperty.getMappingField().getSRS()));
0474:                    }
0475:                    buildTableMap(relations, geometryProperty.getMappingField());
0476:                }
0477:                table.addColumns(newColumns);
0478:            }
0479:
0480:            /**
0481:             * Collects the tables and their columns used in the annotation of the given feature property
0482:             * type. Builds the <code>table</code> member map from this data.
0483:             * <p>
0484:             * The table and column information used on the path to the table of the feature type is also
0485:             * added to the <code>tables</code> member map.
0486:             * 
0487:             * @param featureProperty
0488:             *            feature property type to process
0489:             * @param table
0490:             *            table definition associated with the property definition
0491:             */
0492:            private void buildTableMap(
0493:                    MappedFeaturePropertyType featureProperty,
0494:                    TableDefinition table) {
0495:                Collection<ColumnDefinition> newColumns = new ArrayList<ColumnDefinition>();
0496:
0497:                // array must always have length 1
0498:                TableRelation[] relations = featureProperty.getTableRelations();
0499:
0500:                // target feature type table must always be accessed via 'Relation'-elements
0501:                if (relations == null || relations.length < 1) {
0502:                    throw new RuntimeException(Messages.format(
0503:                            "ERROR_INVALID_FEATURE_PROPERTY_DEFINITION_1",
0504:                            featureProperty.getName()));
0505:                }
0506:
0507:                // maxOccurs > 1: target feature type table must be accessed via join table
0508:                if (featureProperty.getMaxOccurs() != 1
0509:                        && (relations.length < 2)) {
0510:                    throw new RuntimeException(Messages.format(
0511:                            "ERROR_INVALID_FEATURE_PROPERTY_DEFINITION_2",
0512:                            featureProperty.getName()));
0513:                }
0514:
0515:                // add this feature type's key columns to current table
0516:                TableRelation firstRelation = relations[0];
0517:                MappingField[] fromFields = firstRelation.getFromFields();
0518:                boolean isNullable = featureProperty.getMinOccurs() == 0
0519:                        && relations.length == 1;
0520:                for (int i = 0; i < fromFields.length; i++) {
0521:                    MappingField fromField = fromFields[i];
0522:                    newColumns.add(new ColumnDefinition(fromField.getField(),
0523:                            fromField.getType(), isNullable, false, -1));
0524:                }
0525:                table.addColumns(newColumns);
0526:
0527:                MappedFeatureType contentType = featureProperty
0528:                        .getFeatureTypeReference().getFeatureType();
0529:                buildTableMap(relations, featureProperty, contentType);
0530:            }
0531:
0532:            /**
0533:             * Collects the tables and their columns used in the relation tables from a simple/geometry
0534:             * property to it's content table. Builds the <code>table</code> member map from this data.
0535:             * 
0536:             * @param relations
0537:             *            relation tables from annotation of property type
0538:             * @param targetField
0539:             *            holds the properties data
0540:             */
0541:            private void buildTableMap(TableRelation[] relations,
0542:                    MappingField targetField) {
0543:
0544:                // process tables used in 'To'-element of each 'Relation'-element
0545:                for (int i = 0; i < relations.length; i++) {
0546:                    String tableName = relations[i].getToTable();
0547:                    TableDefinition table = lookupTableDefinition(tableName,
0548:                            MULTI_PROPERTY_TABLE);
0549:                    MappingField[] toFields = relations[i].getToFields();
0550:                    for (int j = 0; j < toFields.length; j++) {
0551:                        boolean toIsFK = relations[i].getFKInfo() == TableRelation.FK_INFO.fkIsToField;
0552:                        ColumnDefinition column = new ColumnDefinition(
0553:                                toFields[j].getField(), toFields[j].getType(),
0554:                                false, !toIsFK, false, -1);
0555:                        // schmitz: assuming not part of PK
0556:                        table.addColumn(column);
0557:                    }
0558:                }
0559:
0560:                // process table used in 'To'-element of last 'Relation'-element (targetField refers to
0561:                // this)
0562:                ColumnDefinition column = null;
0563:                if (targetField instanceof  MappingGeometryField) {
0564:
0565:                    column = new ColumnDefinition(targetField.getField(),
0566:                            targetField.getType(), false, true,
0567:                            ((MappingGeometryField) targetField).getSRS());
0568:                } else {
0569:                    column = new ColumnDefinition(targetField.getField(),
0570:                            targetField.getType(), false, false, -1);
0571:                }
0572:
0573:                TableDefinition table = lookupTableDefinition(
0574:                        relations[relations.length - 1].getToTable(),
0575:                        MULTI_PROPERTY_TABLE);
0576:                table.addColumn(column);
0577:            }
0578:
0579:            /**
0580:             * Collects the tables and their columns used in the relation tables from a feature property to
0581:             * it's content feature type. Builds the <code>table</code> member map from this data.
0582:             * 
0583:             * @param relations
0584:             *            relation tables from annotation of feature property type
0585:             * @param property
0586:             * @param targetType
0587:             *            type contained in the feature property
0588:             */
0589:            private void buildTableMap(TableRelation[] relations,
0590:                    MappedPropertyType property, MappedFeatureType targetType) {
0591:
0592:                TableDefinition table = lookupTableDefinition(relations[0]
0593:                        .getFromTable(), FEATURE_TYPE_TABLE);
0594:
0595:                // process tables used in 'To'-element of each 'Relation'-element (except the last)
0596:                for (int i = 0; i < relations.length - 1; i++) {
0597:                    String tableName = relations[i].getToTable();
0598:                    table = lookupTableDefinition(tableName, JOIN_TABLE);
0599:                    MappingField[] toFields = relations[i].getToFields();
0600:                    for (int j = 0; j < toFields.length; j++) {
0601:                        //                boolean toIsFK = relations[i].getFKInfo() == TableRelation.FK_INFO.fkIsToField;
0602:                        ColumnDefinition column = new ColumnDefinition(
0603:                                toFields[j].getField(), toFields[j].getType(),
0604:                                false, true, false, -1);
0605:                        // schmitz: assuming NOT part of PK
0606:                        table.addColumn(column);
0607:                    }
0608:                }
0609:
0610:                // process table used in 'To'-element of last 'Relation'-element
0611:                MappedFeatureType[] concreteTypes = targetType
0612:                        .getConcreteSubstitutions();
0613:                MappingField[] toFields = relations[relations.length - 1]
0614:                        .getToFields();
0615:
0616:                // if it refers to several target tables (target feature type is abstract), an additional
0617:                // column is needed (which determines the target feature type)
0618:                if (concreteTypes.length > 1) {
0619:                    String typeColumn = "featuretype";
0620:                    if (relations.length == 1) {
0621:                        typeColumn = FT_PREFIX
0622:                                + property.getTableRelations()[0]
0623:                                        .getFromFields()[0].getField();
0624:                    }
0625:                    ColumnDefinition column = new ColumnDefinition(typeColumn,
0626:                            Types.VARCHAR, property.getMinOccurs() == 0, false,
0627:                            -1);
0628:                    table.addColumn(column);
0629:                }
0630:                for (int i = 0; i < concreteTypes.length; i++) {
0631:                    MappedFeatureType concreteType = concreteTypes[i];
0632:                    String tableName = concreteType.getTable();
0633:                    table = lookupTableDefinition(tableName, FEATURE_TYPE_TABLE);
0634:                    for (int j = 0; j < toFields.length; j++) {
0635:                        ColumnDefinition column = new ColumnDefinition(
0636:                                toFields[j].getField(), toFields[j].getType(),
0637:                                false, false, -1);
0638:                        table.addColumn(column);
0639:                    }
0640:                }
0641:
0642:                // process tables used in 'From'-element of each 'Relation'-element (except the first)
0643:                for (int i = 1; i < relations.length; i++) {
0644:                    String tableName = relations[i].getFromTable();
0645:                    if (i != relations.length - 1) {
0646:                        table = lookupTableDefinition(tableName, JOIN_TABLE);
0647:                    } else {
0648:                        table = lookupTableDefinition(tableName,
0649:                                FEATURE_TYPE_TABLE);
0650:                    }
0651:                    MappingField[] fromFields = relations[i].getFromFields();
0652:                    for (int j = 0; j < fromFields.length; j++) {
0653:                        ColumnDefinition column = new ColumnDefinition(
0654:                                fromFields[j].getField(), fromFields[j]
0655:                                        .getType(), false, true, false, -1);
0656:                        table.addColumn(column);
0657:                    }
0658:                }
0659:            }
0660:
0661:            /**
0662:             * Generates the DDL statements that can be used to build a relational schema that backs the GML
0663:             * schema.
0664:             * 
0665:             * @param outputFile
0666:             * @throws IOException
0667:             */
0668:            public void generateCreateScript(String outputFile)
0669:                    throws IOException {
0670:                PrintWriter writer = new PrintWriter(new FileWriter(outputFile));
0671:
0672:                System.out.println(Messages.format("CREATE_SEQUENCES",
0673:                        new Integer(sequences.size())));
0674:                if (sequences.size() > 0) {
0675:                    writer.print("/* CREATE SEQUENCES (" + sequences.size()
0676:                            + ") */\n");
0677:                    for (String sequenceName : sequences) {
0678:                        writer.print('\n');
0679:                        writer.print(generateCreateSequenceStmt(sequenceName));
0680:                    }
0681:                }
0682:
0683:                TableDefinition[] tables = getTables(FEATURE_TYPE_TABLE);
0684:                System.out.println(Messages.format("CREATE_FEATURE_TYPE",
0685:                        new Integer(tables.length)));
0686:                writer.print("\n\n/* CREATE FEATURE TABLES (" + tables.length
0687:                        + ") */\n");
0688:                for (int i = 0; i < tables.length; i++) {
0689:                    System.out.println(tables[i].tableName);
0690:                    writer.print('\n');
0691:                    writer.print(generateCreateTableStmt(tables[i]));
0692:                    writer.print(generateCreateIndexStmts(tables[i]));
0693:                }
0694:
0695:                tables = getTables(JOIN_TABLE);
0696:                if (tables.length != 0) {
0697:                    writer.print("\n\n/* CREATE JOIN TABLES (" + tables.length
0698:                            + ") */\n");
0699:                }
0700:                System.out.println(Messages.format("CREATE_JOIN_TABLES",
0701:                        new Integer(tables.length)));
0702:                for (int i = 0; i < tables.length; i++) {
0703:                    System.out.println(tables[i].tableName);
0704:                    writer.print('\n');
0705:                    writer.print(generateCreateTableStmt(tables[i]));
0706:                    writer.print(generateCreateIndexStmts(tables[i]));
0707:                }
0708:
0709:                tables = getTables(MULTI_PROPERTY_TABLE);
0710:                if (tables.length != 0) {
0711:                    writer.print("\n\n/* CREATE PROPERTY TABLES ("
0712:                            + tables.length + ") */\n");
0713:                }
0714:                System.out.println(Messages.format("CREATE_PROPERTY_TABLES",
0715:                        new Integer(tables.length)));
0716:                for (int i = 0; i < tables.length; i++) {
0717:                    System.out.println(tables[i].tableName);
0718:                    writer.print('\n');
0719:                    writer.print(generateCreateTableStmt(tables[i]));
0720:                    writer.print(generateCreateIndexStmts(tables[i]));
0721:                }
0722:                writer.close();
0723:            }
0724:
0725:            /**
0726:             * Generates the DDL statements that can be used to remove the relational schema again.
0727:             * 
0728:             * @param outputFile
0729:             * @throws IOException
0730:             */
0731:            public void generateDropScript(String outputFile)
0732:                    throws IOException {
0733:                PrintWriter writer = new PrintWriter(new FileWriter(outputFile));
0734:
0735:                TableDefinition[] tables = getTables(FEATURE_TYPE_TABLE);
0736:                System.out.println(Messages.format("DROP_FEATURE_TYPE",
0737:                        new Integer(tables.length)));
0738:                writer.print("/* DROP FEATURE TABLES (" + tables.length
0739:                        + ") */\n");
0740:                for (int i = 0; i < tables.length; i++) {
0741:                    writer.print('\n');
0742:                    writer.print(generateDropIndexStmts(tables[i]));
0743:                    writer.print(generateDropTableStmt(tables[i]));
0744:                }
0745:
0746:                tables = getTables(JOIN_TABLE);
0747:                writer.print("\n\n/* DROP JOIN TABLES (" + tables.length
0748:                        + ") */\n");
0749:                System.out.println(Messages.format("DROP_JOIN_TABLES",
0750:                        new Integer(tables.length)));
0751:                for (int i = 0; i < tables.length; i++) {
0752:                    writer.print('\n');
0753:                    writer.print(generateDropIndexStmts(tables[i]));
0754:                    writer.print(generateDropTableStmt(tables[i]));
0755:                }
0756:
0757:                tables = getTables(MULTI_PROPERTY_TABLE);
0758:                writer.print("\n\n/* DROP PROPERTY TABLES (" + tables.length
0759:                        + ") */\n");
0760:                System.out.println(Messages.format("DROP_PROPERTY_TABLES",
0761:                        new Integer(tables.length)));
0762:                for (int i = 0; i < tables.length; i++) {
0763:                    writer.print('\n');
0764:                    writer.print(generateDropIndexStmts(tables[i]));
0765:                    writer.print(generateDropTableStmt(tables[i]));
0766:                }
0767:
0768:                System.out.println(Messages.format("DROP_SEQUENCES",
0769:                        new Integer(sequences.size())));
0770:                if (sequences.size() > 0) {
0771:                    writer.print("\n\n/* DROP SEQUENCES (" + sequences.size()
0772:                            + ") */\n");
0773:                    for (String sequenceName : sequences) {
0774:                        writer.print('\n');
0775:                        writer.print(generateDropSequenceStmt(sequenceName));
0776:                    }
0777:                }
0778:
0779:                writer.close();
0780:            }
0781:
0782:            /**
0783:             * @param args
0784:             * @throws IOException
0785:             * @throws SAXException
0786:             * @throws XMLParsingException
0787:             * @throws XMLSchemaException
0788:             * @throws UnknownCRSException
0789:             */
0790:            public static void main(String[] args) throws IOException,
0791:                    SAXException, XMLParsingException, XMLSchemaException,
0792:                    UnknownCRSException {
0793:
0794:                if (args.length != 4) {
0795:                    System.out
0796:                            .println("Usage: DDLGenerator [FLAVOUR] <input.xsd> <create.sql> <drop.sql>");
0797:                    System.exit(0);
0798:                }
0799:
0800:                String flavour = args[0];
0801:                String schemaFile = args[1];
0802:                String createFile = args[2];
0803:                String dropFile = args[3];
0804:
0805:                DDLGenerator generator = null;
0806:                if ("POSTGIS".equals(flavour)) {
0807:                    generator = new PostGISDDLGenerator(new File(schemaFile)
0808:                            .toURI().toURL());
0809:                } else if ("ORACLE".equals(flavour)) {
0810:                    generator = new OracleDDLGenerator(new File(schemaFile)
0811:                            .toURI().toURL());
0812:                } else {
0813:                    System.out.println(Messages.format(
0814:                            "ERROR_UNSUPPORTED_FLAVOUR", flavour));
0815:                }
0816:
0817:                generator.generateCreateScript(createFile);
0818:                generator.generateDropScript(dropFile);
0819:            }
0820:
0821:            /**
0822:             * Returns a string representation of the object.
0823:             * 
0824:             * @return a string representation of the object.
0825:             */
0826:            @Override
0827:            public String toString() {
0828:                StringBuffer sb = new StringBuffer(Messages
0829:                        .getString("RELATIONAL_SCHEMA"));
0830:                sb.append('\n');
0831:
0832:                TableDefinition[] tables = getTables(FEATURE_TYPE_TABLE);
0833:                sb.append('\n');
0834:                sb.append(tables.length);
0835:                sb.append(" feature type tables\n\n");
0836:                for (int i = 0; i < tables.length; i++) {
0837:                    sb.append(tables[i]);
0838:                    sb.append('\n');
0839:                }
0840:
0841:                sb.append('\n');
0842:                tables = getTables(JOIN_TABLE);
0843:                sb.append(tables.length);
0844:                sb.append(" join tables\n\n");
0845:                for (int i = 0; i < tables.length; i++) {
0846:                    sb.append(tables[i]);
0847:                    sb.append('\n');
0848:                }
0849:
0850:                sb.append('\n');
0851:                tables = getTables(MULTI_PROPERTY_TABLE);
0852:                sb.append(tables.length);
0853:                sb.append(" property tables\n\n");
0854:                for (int i = 0; i < tables.length; i++) {
0855:                    sb.append(tables[i]);
0856:                    sb.append('\n');
0857:                }
0858:                return sb.toString();
0859:            }
0860:
0861:            class TableDefinition {
0862:
0863:                private int type;
0864:
0865:                String tableName;
0866:
0867:                private Map<String, ColumnDefinition> columnsMap = new LinkedHashMap<String, ColumnDefinition>();
0868:
0869:                TableDefinition(String tableName, int type) {
0870:                    this .type = type;
0871:                    this .tableName = tableName;
0872:                }
0873:
0874:                String getName() {
0875:                    return this .tableName;
0876:                }
0877:
0878:                int getType() {
0879:                    return this .type;
0880:                }
0881:
0882:                ColumnDefinition[] getColumns() {
0883:                    Collection<ColumnDefinition> columns = new ArrayList<ColumnDefinition>();
0884:                    Iterator<String> iter = columnsMap.keySet().iterator();
0885:                    while (iter.hasNext()) {
0886:                        String columnName = iter.next();
0887:                        columns.add(columnsMap.get(columnName));
0888:                    }
0889:                    return columns
0890:                            .toArray(new ColumnDefinition[columns.size()]);
0891:                }
0892:
0893:                ColumnDefinition[] getPKColumns() {
0894:                    Collection<ColumnDefinition> columns = new ArrayList<ColumnDefinition>();
0895:                    Iterator<String> iter = columnsMap.keySet().iterator();
0896:                    while (iter.hasNext()) {
0897:                        String columnName = iter.next();
0898:                        ColumnDefinition column = columnsMap.get(columnName);
0899:                        if (column.isPartOfPK()) {
0900:                            columns.add(columnsMap.get(columnName));
0901:                        }
0902:                    }
0903:                    return columns
0904:                            .toArray(new ColumnDefinition[columns.size()]);
0905:                }
0906:
0907:                ColumnDefinition getColumn(String name) {
0908:                    return columnsMap.get(name);
0909:                }
0910:
0911:                void addColumn(ColumnDefinition column) {
0912:                    ColumnDefinition oldColumn = columnsMap.get(column
0913:                            .getName());
0914:                    if (oldColumn != null) {
0915:                        if (!(column.getType() == oldColumn.getType())) {
0916:                            String msg = Messages.format(
0917:                                    "ERROR_COLUMN_DEFINITION_TYPES", column
0918:                                            .getName(),
0919:                                    oldColumn.isNullable() ? "NULLABLE"
0920:                                            : "NOT NULLABLE", column
0921:                                            .isNullable() ? "NULLABLE"
0922:                                            : "NOT NULLABLE");
0923:                            throw new RuntimeException(msg);
0924:
0925:                        }
0926:                        if (oldColumn.isPartOfPK()) {
0927:                            column = oldColumn;
0928:                        }
0929:                    }
0930:                    columnsMap.put(column.getName(), column);
0931:                }
0932:
0933:                void addColumns(Collection<ColumnDefinition> columns) {
0934:                    Iterator<ColumnDefinition> iter = columns.iterator();
0935:                    while (iter.hasNext()) {
0936:                        ColumnDefinition column = iter.next();
0937:                        addColumn(column);
0938:                    }
0939:                }
0940:
0941:                @Override
0942:                public String toString() {
0943:                    StringBuffer sb = new StringBuffer();
0944:                    sb.append(Messages.format("TABLE", this .tableName));
0945:                    sb.append(Messages.getString("PRIMARY_KEY"));
0946:                    ColumnDefinition[] pkColumns = getPKColumns();
0947:                    for (int i = 0; i < pkColumns.length; i++) {
0948:                        sb.append('"');
0949:                        sb.append(pkColumns[i].getName());
0950:                        sb.append('"');
0951:                        if (i != pkColumns.length - 1) {
0952:                            sb.append(", ");
0953:                        }
0954:                    }
0955:                    sb.append('\n');
0956:                    Iterator<String> columnNameIter = this .columnsMap.keySet()
0957:                            .iterator();
0958:                    while (columnNameIter.hasNext()) {
0959:                        String columnName = columnNameIter.next();
0960:                        ColumnDefinition column = this .columnsMap
0961:                                .get(columnName);
0962:                        try {
0963:                            sb.append(Messages.format("COLUMN", columnName,
0964:                                    Types.getTypeNameForSQLTypeCode(column
0965:                                            .getType())
0966:                                            + ":" + column.getType(),
0967:                                    new Boolean(column.isNullable())));
0968:                        } catch (UnknownTypeException e) {
0969:                            // TODO Auto-generated catch block
0970:                            e.printStackTrace();
0971:                        }
0972:                        sb.append('\n');
0973:                    }
0974:                    return sb.toString();
0975:                }
0976:            }
0977:
0978:            class ColumnDefinition {
0979:
0980:                private String columnName;
0981:
0982:                private int type;
0983:
0984:                private boolean isNullable;
0985:
0986:                private boolean isGeometryColumn;
0987:
0988:                private int srsCode;
0989:
0990:                private boolean isPartOfPK;
0991:
0992:                ColumnDefinition(String columnName, int type,
0993:                        boolean isNullable, boolean isGeometryColumn,
0994:                        int srsCode) {
0995:                    this .columnName = columnName;
0996:                    this .type = type;
0997:                    this .isNullable = isNullable;
0998:                    this .isGeometryColumn = isGeometryColumn;
0999:                    this .srsCode = srsCode;
1000:                }
1001:
1002:                ColumnDefinition(String columnName, int type,
1003:                        boolean isNullable, boolean isPartOfPK,
1004:                        boolean isGeometryColumn, int srsCode) {
1005:                    this (columnName, type, isNullable, isGeometryColumn,
1006:                            srsCode);
1007:                    this .isPartOfPK = isPartOfPK;
1008:                }
1009:
1010:                String getName() {
1011:                    return this .columnName;
1012:                }
1013:
1014:                int getType() {
1015:                    return this .type;
1016:                }
1017:
1018:                boolean isNullable() {
1019:                    return this .isNullable;
1020:                }
1021:
1022:                boolean isGeometry() {
1023:                    return this .isGeometryColumn;
1024:                }
1025:
1026:                int getSRS() {
1027:                    return this .srsCode;
1028:                }
1029:
1030:                boolean isPartOfPK() {
1031:                    return this.isPartOfPK;
1032:                }
1033:            }
1034:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.