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


0001:        //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/io/datastore/sql/transaction/insert/InsertHandler.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.io.datastore.sql.transaction.insert;
0044:
0045:        import java.sql.Connection;
0046:        import java.sql.PreparedStatement;
0047:        import java.sql.ResultSet;
0048:        import java.sql.SQLException;
0049:        import java.util.ArrayList;
0050:        import java.util.Collection;
0051:        import java.util.HashMap;
0052:        import java.util.Iterator;
0053:        import java.util.List;
0054:        import java.util.Map;
0055:
0056:        import org.deegree.datatypes.Types;
0057:        import org.deegree.datatypes.UnknownTypeException;
0058:        import org.deegree.framework.log.ILogger;
0059:        import org.deegree.framework.log.LoggerFactory;
0060:        import org.deegree.i18n.Messages;
0061:        import org.deegree.io.datastore.DatastoreException;
0062:        import org.deegree.io.datastore.FeatureId;
0063:        import org.deegree.io.datastore.TransactionException;
0064:        import org.deegree.io.datastore.idgenerator.FeatureIdAssigner;
0065:        import org.deegree.io.datastore.idgenerator.IdGenerationException;
0066:        import org.deegree.io.datastore.idgenerator.ParentIDGenerator;
0067:        import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
0068:        import org.deegree.io.datastore.schema.MappedFeatureType;
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.AbstractRequestHandler;
0077:        import org.deegree.io.datastore.sql.StatementBuffer;
0078:        import org.deegree.io.datastore.sql.TableAliasGenerator;
0079:        import org.deegree.io.datastore.sql.transaction.SQLTransaction;
0080:        import org.deegree.model.feature.Feature;
0081:        import org.deegree.model.feature.FeatureProperty;
0082:        import org.deegree.model.feature.schema.FeaturePropertyType;
0083:        import org.deegree.model.feature.schema.GeometryPropertyType;
0084:        import org.deegree.model.feature.schema.SimplePropertyType;
0085:        import org.deegree.model.spatialschema.Geometry;
0086:        import org.deegree.ogcwebservices.wfs.operation.transaction.Insert;
0087:        import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction;
0088:
0089:        /**
0090:         * Handler for {@link Insert} operations (usually contained in {@link Transaction} requests).
0091:         * 
0092:         * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
0093:         * @author last edited by: $Author: aschmitz $
0094:         * 
0095:         * @version $Revision: 10506 $, $Date: 2008-03-06 08:50:33 -0800 (Thu, 06 Mar 2008) $
0096:         */
0097:        public class InsertHandler extends AbstractRequestHandler {
0098:
0099:            private static final ILogger LOG = LoggerFactory
0100:                    .getLogger(InsertHandler.class);
0101:
0102:            // features that are currently being processed
0103:            private Map<FeatureId, FeatureRow> featuresInInsertion = new HashMap<FeatureId, FeatureRow>();
0104:
0105:            // contains only property rows and join table rows (but no feature rows)
0106:            private List<InsertRow> insertRows = new ArrayList<InsertRow>();
0107:
0108:            private SQLTransaction dsTa;
0109:
0110:            /**
0111:             * Creates a new <code>InsertHandler</code> from the given parameters.
0112:             * 
0113:             * @param dsTa
0114:             * @param aliasGenerator
0115:             * @param conn
0116:             */
0117:            public InsertHandler(SQLTransaction dsTa,
0118:                    TableAliasGenerator aliasGenerator, Connection conn) {
0119:                super (dsTa.getDatastore(), aliasGenerator, conn);
0120:                this .dsTa = dsTa;
0121:            }
0122:
0123:            /**
0124:             * Inserts the given feature instance into the datastore.
0125:             * 
0126:             * @param features
0127:             *            (which have a MappedFeatureType as feature type)
0128:             * @return feature ids of inserted (root) feature instances
0129:             * @throws DatastoreException
0130:             *             if the insert could not be performed
0131:             */
0132:            public List<FeatureId> performInsert(List<Feature> features)
0133:                    throws DatastoreException {
0134:
0135:                List<FeatureId> fids = new ArrayList<FeatureId>();
0136:                for (int i = 0; i < features.size(); i++) {
0137:                    Feature feature = features.get(i);
0138:
0139:                    MappedFeatureType ft = (MappedFeatureType) feature
0140:                            .getFeatureType();
0141:                    if (feature.getId().startsWith(
0142:                            FeatureIdAssigner.EXISTS_MARKER)) {
0143:                        String msg = Messages.getMessage(
0144:                                "DATASTORE_FEATURE_EXISTS", feature.getName(),
0145:                                feature.getId().substring(1));
0146:                        throw new TransactionException(msg);
0147:                    }
0148:                    LOG.logDebug("Inserting root feature '" + feature.getId()
0149:                            + "'...");
0150:                    insertFeature(feature);
0151:                    FeatureId fid = new FeatureId(ft, feature.getId());
0152:                    fids.add(fid);
0153:
0154:                }
0155:
0156:                // merge inserts rows that are identical (except their pks)
0157:                this .insertRows = mergeInsertRows(this .insertRows);
0158:
0159:                // add featureRows to insertRows
0160:                Iterator<FeatureRow> iter = this .featuresInInsertion.values()
0161:                        .iterator();
0162:                while (iter.hasNext()) {
0163:                    this .insertRows.add(iter.next());
0164:                }
0165:
0166:                // check for cyclic fk constraints
0167:                Collection<InsertRow> cycle = InsertRow
0168:                        .findCycle(this .insertRows);
0169:                if (cycle != null) {
0170:                    Iterator<InsertRow> cycleIter = cycle.iterator();
0171:                    StringBuffer sb = new StringBuffer();
0172:                    while (cycleIter.hasNext()) {
0173:                        sb.append(cycleIter.next());
0174:                        if (cycle.iterator().hasNext()) {
0175:                            sb.append(" -> ");
0176:                        }
0177:                    }
0178:                    String msg = Messages.getMessage("DATASTORE_FK_CYCLE", sb
0179:                            .toString());
0180:                    throw new TransactionException(msg);
0181:                }
0182:
0183:                // sort the insert rows topologically
0184:                List<InsertRow> sortedInserts = InsertRow
0185:                        .sortInsertRows(this .insertRows);
0186:
0187:                if (LOG.getLevel() == ILogger.LOG_DEBUG) {
0188:                    LOG.logDebug(sortedInserts.size()
0189:                            + " rows to be inserted: ");
0190:                    for (InsertRow row : sortedInserts) {
0191:                        LOG.logDebug(row.toString());
0192:                    }
0193:                }
0194:
0195:                executeInserts(sortedInserts);
0196:                return fids;
0197:            }
0198:
0199:            /**
0200:             * Builds the <code>InsertRows</code> that are necessary to insert the given feature instance
0201:             * (including all properties + subfeatures).
0202:             * 
0203:             * @param feature
0204:             * @return InsertRows that are necessary to insert the given feature instance
0205:             * @throws TransactionException
0206:             */
0207:            private FeatureRow insertFeature(Feature feature)
0208:                    throws TransactionException {
0209:
0210:                MappedFeatureType ft = (MappedFeatureType) feature
0211:                        .getFeatureType();
0212:                if (!ft.isInsertable()) {
0213:                    String msg = Messages.getMessage(
0214:                            "DATASTORE_FT_NOT_INSERTABLE", ft.getName());
0215:                    throw new TransactionException(msg);
0216:                }
0217:
0218:                LOG
0219:                        .logDebug("Creating InsertRow for feature with type '"
0220:                                + ft.getName() + "' and id: '"
0221:                                + feature.getId() + "'.");
0222:
0223:                // extract feature id column value
0224:                MappingField[] fidFields = ft.getGMLId().getIdFields();
0225:                if (fidFields.length > 1) {
0226:                    throw new TransactionException(
0227:                            "Insertion of features with compound feature "
0228:                                    + "ids is not supported.");
0229:                }
0230:                FeatureId fid = null;
0231:                try {
0232:                    fid = new FeatureId(ft, feature.getId());
0233:                } catch (IdGenerationException e) {
0234:                    throw new TransactionException(e.getMessage(), e);
0235:                }
0236:
0237:                // check if the feature id is already being inserted (happens for cyclic features)
0238:                FeatureRow insertRow = this .featuresInInsertion.get(fid);
0239:                if (insertRow != null) {
0240:                    return insertRow;
0241:                }
0242:
0243:                insertRow = new FeatureRow(ft.getTable());
0244:                this .featuresInInsertion.put(fid, insertRow);
0245:
0246:                // add column value for fid (primary key)
0247:                String fidColumn = fidFields[0].getField();
0248:                insertRow.setColumn(fidColumn, fid.getValue(0), ft.getGMLId()
0249:                        .getIdFields()[0].getType(), true);
0250:
0251:                // process properties
0252:                FeatureProperty[] properties = feature.getProperties();
0253:                for (int i = 0; i < properties.length; i++) {
0254:                    FeatureProperty property = properties[i];
0255:                    MappedPropertyType propertyType = (MappedPropertyType) ft
0256:                            .getProperty(property.getName());
0257:                    if (propertyType == null) {
0258:                        String msg = Messages.getMessage(
0259:                                "DATASTORE_PROPERTY_TYPE_NOT_KNOWN", property
0260:                                        .getName());
0261:                        LOG.logDebug(msg);
0262:                        throw new TransactionException(msg);
0263:                    }
0264:                    insertProperty(property, propertyType, insertRow);
0265:                }
0266:                return insertRow;
0267:            }
0268:
0269:            /**
0270:             * Builds the <code>InsertRow</code>s that are necessary to insert the given property
0271:             * instance (including all it's subfeatures).
0272:             * 
0273:             * @param property
0274:             *            property instance to be inserted
0275:             * @param propertyType
0276:             *            property type of the property
0277:             * @param featureRow
0278:             *            table row of the parent feature instance
0279:             * @throws TransactionException
0280:             */
0281:            private void insertProperty(FeatureProperty property,
0282:                    MappedPropertyType propertyType, InsertRow featureRow)
0283:                    throws TransactionException {
0284:
0285:                if (propertyType instanceof  SimplePropertyType) {
0286:                    LOG.logDebug("- Simple property '" + propertyType.getName()
0287:                            + "', value='" + getPropertyValue(property) + "'.");
0288:                    insertProperty((MappedSimplePropertyType) propertyType,
0289:                            property, featureRow);
0290:                } else if (propertyType instanceof  GeometryPropertyType) {
0291:                    LOG.logDebug("- Geometry property: '"
0292:                            + propertyType.getName() + "'");
0293:                    insertProperty((MappedGeometryPropertyType) propertyType,
0294:                            property, featureRow);
0295:                } else if (propertyType instanceof  FeaturePropertyType) {
0296:                    LOG.logDebug("- Feature property: '"
0297:                            + propertyType.getName() + "'");
0298:                    insertProperty((MappedFeaturePropertyType) propertyType,
0299:                            property, featureRow);
0300:                } else {
0301:                    throw new TransactionException("Unhandled property type '"
0302:                            + propertyType.getClass().getName() + "'.");
0303:                }
0304:            }
0305:
0306:            /**
0307:             * Inserts the given simple property (stored in feature table or in related table).
0308:             * 
0309:             * @param pt
0310:             * @param property
0311:             * @param featureRow
0312:             * @throws TransactionException
0313:             */
0314:            private void insertProperty(MappedSimplePropertyType pt,
0315:                    FeatureProperty property, InsertRow featureRow)
0316:                    throws TransactionException {
0317:
0318:                SimpleContent content = pt.getContent();
0319:                if (content.isUpdateable()) {
0320:                    if (content instanceof  MappingField) {
0321:                        MappingField mf = (MappingField) content;
0322:                        String propertyColumn = mf.getField();
0323:                        Object propertyValue = property.getValue();
0324:                        int propertyType = mf.getType();
0325:                        TableRelation[] relations = pt.getTableRelations();
0326:                        insertProperty(propertyColumn, propertyValue,
0327:                                propertyType, relations, featureRow);
0328:                    }
0329:                }
0330:            }
0331:
0332:            /**
0333:             * Inserts the given geometry property (stored in feature table or in related table).
0334:             * 
0335:             * @param pt
0336:             * @param property
0337:             * @param featureRow
0338:             * @throws TransactionException
0339:             */
0340:            private void insertProperty(MappedGeometryPropertyType pt,
0341:                    FeatureProperty property, InsertRow featureRow)
0342:                    throws TransactionException {
0343:
0344:                String propertyColumn = pt.getMappingField().getField();
0345:                MappingGeometryField dbField = pt.getMappingField();
0346:                Geometry deegreeGeometry = (Geometry) property.getValue();
0347:                Object dbGeometry;
0348:
0349:                int createSrsCode = dbField.getSRS();
0350:                int targetSrsCode = -1;
0351:                if (deegreeGeometry.getCoordinateSystem() == null) {
0352:                    LOG
0353:                            .logDebug("No SRS information for geometry available. Assuming '"
0354:                                    + pt.getSRS() + "'.");
0355:                } else if (!pt.getSRS().toString().equals(
0356:                        deegreeGeometry.getCoordinateSystem().getIdentifier())) {
0357:                    String msg = "Insert-Transformation: geometry srs: "
0358:                            + deegreeGeometry.getCoordinateSystem()
0359:                                    .getIdentifier() + " -> property srs: "
0360:                            + pt.getSRS();
0361:                    LOG.logDebug(msg);
0362:                    if (createSrsCode == -1) {
0363:                        msg = Messages.getMessage(
0364:                                "DATASTORE_SRS_NOT_SPECIFIED", pt.getName(),
0365:                                deegreeGeometry.getCoordinateSystem(), pt
0366:                                        .getSRS());
0367:                        throw new TransactionException(msg);
0368:                    }
0369:                    try {
0370:                        createSrsCode = datastore
0371:                                .getNativeSRSCode(deegreeGeometry
0372:                                        .getCoordinateSystem().getIdentifier());
0373:                    } catch (DatastoreException e) {
0374:                        throw new TransactionException(e.getMessage(), e);
0375:                    }
0376:                    targetSrsCode = dbField.getSRS();
0377:                }
0378:
0379:                try {
0380:                    dbGeometry = this .datastore.convertDeegreeToDBGeometry(
0381:                            deegreeGeometry, createSrsCode, this .conn);
0382:                } catch (DatastoreException e) {
0383:                    throw new TransactionException(e.getMessage(), e);
0384:                }
0385:
0386:                int propertyType = pt.getMappingField().getType();
0387:
0388:                // TODO remove this Oracle hack
0389:                if (this .datastore.getClass().getName().contains(
0390:                        "OracleDatastore")) {
0391:                    propertyType = Types.STRUCT;
0392:                }
0393:
0394:                TableRelation[] relations = pt.getTableRelations();
0395:                insertProperty(propertyColumn, dbGeometry, propertyType,
0396:                        relations, featureRow, targetSrsCode);
0397:            }
0398:
0399:            /**
0400:             * Inserts the given simple property (stored in feature table or in related table).
0401:             * 
0402:             * @param propertyColumn
0403:             * @param propertyValue
0404:             * @param propertyType
0405:             * @param featureRow
0406:             * @throws TransactionException
0407:             */
0408:            private void insertProperty(String propertyColumn,
0409:                    Object propertyValue, int propertyType,
0410:                    TableRelation[] relations, InsertRow featureRow)
0411:                    throws TransactionException {
0412:
0413:                if (relations == null || relations.length == 0) {
0414:                    // property is stored in feature table
0415:                    featureRow.setColumn(propertyColumn, propertyValue,
0416:                            propertyType, false);
0417:                } else {
0418:                    // property is stored in related table
0419:                    if (relations.length > 1) {
0420:                        throw new TransactionException(Messages
0421:                                .getMessage("DATASTORE_SIMPLE_PROPERTY_JOIN"));
0422:                    }
0423:
0424:                    if (!relations[0].isFromFK()) {
0425:                        // fk is in property table
0426:                        MappingField[] pkFields = relations[0].getFromFields();
0427:                        MappingField[] fkFields = relations[0].getToFields();
0428:
0429:                        for (int i = 0; i < pkFields.length; i++) {
0430:                            InsertField pkField = featureRow
0431:                                    .getColumn(pkFields[i].getField());
0432:                            if (pkField == null) {
0433:                                String msg = Messages.getMessage(
0434:                                        "DATASTORE_NO_FK_VALUE", pkField
0435:                                                .getColumnName(), pkFields[i]
0436:                                                .getTable());
0437:                                throw new TransactionException(msg);
0438:                            }
0439:                            int pkColumnType = pkField.getSQLType();
0440:                            int fkColumnType = fkFields[i].getType();
0441:                            if (pkColumnType != fkColumnType) {
0442:                                String fkType = "" + fkColumnType;
0443:                                String pkType = "" + pkColumnType;
0444:                                try {
0445:                                    fkType = Types
0446:                                            .getTypeNameForSQLTypeCode(fkColumnType);
0447:                                    pkType = Types
0448:                                            .getTypeNameForSQLTypeCode(pkColumnType);
0449:                                } catch (UnknownTypeException e) {
0450:                                    LOG.logError(e.getMessage(), e);
0451:                                }
0452:                                Object[] params = new Object[] {
0453:                                        relations[0].getToTable(),
0454:                                        fkFields[i].getField(), fkType,
0455:                                        featureRow.getTable(),
0456:                                        pkFields[i].getField(), pkType };
0457:                                String msg = Messages
0458:                                        .getMessage(
0459:                                                "DATASTORE_FK_PK_TYPE_MISMATCH",
0460:                                                params);
0461:                                throw new TransactionException(msg);
0462:                            }
0463:                            InsertRow insertRow = new InsertRow(relations[0]
0464:                                    .getToTable());
0465:                            insertRow.linkColumn(fkFields[i].getField(),
0466:                                    pkField);
0467:                            insertRow.setColumn(propertyColumn, propertyValue,
0468:                                    propertyType, false);
0469:                            this .insertRows.add(insertRow);
0470:                        }
0471:                    } else {
0472:                        // fk is in feature table
0473:                        MappingField[] pkFields = relations[0].getToFields();
0474:                        MappingField[] fkFields = relations[0].getFromFields();
0475:
0476:                        // generate necessary primary key value
0477:                        InsertField pkField = null;
0478:                        try {
0479:                            Object pk = null;
0480:                            // TODO remove hack!!!
0481:                            if (relations[0].getIdGenerator() instanceof  ParentIDGenerator) {
0482:                                InsertField field = featureRow.getColumn("ID");
0483:                                if (field == null) {
0484:                                    throw new TransactionException(
0485:                                            "No value for ID available!");
0486:                                }
0487:                                pk = field.getValue();
0488:                            } else {
0489:                                pk = relations[0].getNewPK(this .dsTa);
0490:                            }
0491:                            InsertRow insertRow = findOrCreateRow(relations[0]
0492:                                    .getToTable(), pkFields[0].getField(), pk);
0493:                            pkField = insertRow.setColumn(pkFields[0]
0494:                                    .getField(), pk, pkFields[0].getType(),
0495:                                    true);
0496:                            insertRow.setColumn(propertyColumn, propertyValue,
0497:                                    propertyType, false);
0498:                        } catch (IdGenerationException e) {
0499:                            throw new TransactionException(e.getMessage(), e);
0500:                        }
0501:                        featureRow.linkColumn(fkFields[0].getField(), pkField);
0502:                    }
0503:                }
0504:            }
0505:
0506:            /**
0507:             * Inserts the given geometry property (stored in feature table or in related table).
0508:             * 
0509:             * @param propertyColumn
0510:             * @param propertyValue
0511:             * @param propertyType
0512:             * @param featureRow
0513:             * @throws TransactionException
0514:             */
0515:            private void insertProperty(String propertyColumn,
0516:                    Object propertyValue, int propertyType,
0517:                    TableRelation[] relations, InsertRow featureRow,
0518:                    int targetSrsCode) throws TransactionException {
0519:
0520:                if (relations == null || relations.length == 0) {
0521:                    // property is stored in feature table
0522:                    featureRow.setGeometryColumn(propertyColumn, propertyValue,
0523:                            propertyType, false, targetSrsCode);
0524:                } else {
0525:                    // property is stored in related table
0526:                    if (relations.length > 1) {
0527:                        throw new TransactionException(Messages
0528:                                .getMessage("DATASTORE_SIMPLE_PROPERTY_JOIN"));
0529:                    }
0530:
0531:                    if (!relations[0].isFromFK()) {
0532:                        // fk is in property table
0533:                        MappingField[] pkFields = relations[0].getFromFields();
0534:                        MappingField[] fkFields = relations[0].getToFields();
0535:
0536:                        for (int i = 0; i < pkFields.length; i++) {
0537:                            InsertField pkField = featureRow
0538:                                    .getColumn(pkFields[i].getField());
0539:                            if (pkField == null) {
0540:                                String msg = Messages.getMessage(
0541:                                        "DATASTORE_NO_FK_VALUE", pkField
0542:                                                .getColumnName(), pkFields[i]
0543:                                                .getTable());
0544:                                throw new TransactionException(msg);
0545:                            }
0546:                            int pkColumnType = pkField.getSQLType();
0547:                            int fkColumnType = fkFields[i].getType();
0548:                            if (pkColumnType != fkColumnType) {
0549:                                String fkType = "" + fkColumnType;
0550:                                String pkType = "" + pkColumnType;
0551:                                try {
0552:                                    fkType = Types
0553:                                            .getTypeNameForSQLTypeCode(fkColumnType);
0554:                                    pkType = Types
0555:                                            .getTypeNameForSQLTypeCode(pkColumnType);
0556:                                } catch (UnknownTypeException e) {
0557:                                    LOG.logError(e.getMessage(), e);
0558:                                }
0559:                                Object[] params = new Object[] {
0560:                                        relations[0].getToTable(),
0561:                                        fkFields[i].getField(), fkType,
0562:                                        featureRow.getTable(),
0563:                                        pkFields[i].getField(), pkType };
0564:                                String msg = Messages
0565:                                        .getMessage(
0566:                                                "DATASTORE_FK_PK_TYPE_MISMATCH",
0567:                                                params);
0568:                                throw new TransactionException(msg);
0569:                            }
0570:                            InsertRow insertRow = new InsertRow(relations[0]
0571:                                    .getToTable());
0572:                            insertRow.linkColumn(fkFields[i].getField(),
0573:                                    pkField);
0574:                            insertRow.setGeometryColumn(propertyColumn,
0575:                                    propertyValue, propertyType, false,
0576:                                    targetSrsCode);
0577:                            this .insertRows.add(insertRow);
0578:                        }
0579:                    } else {
0580:                        // fk is in feature table
0581:                        MappingField[] pkFields = relations[0].getToFields();
0582:                        MappingField[] fkFields = relations[0].getFromFields();
0583:
0584:                        // generate necessary primary key value
0585:                        InsertField pkField = null;
0586:                        try {
0587:                            Object pk = null;
0588:                            // TODO remove hack!!!
0589:                            if (relations[0].getIdGenerator() instanceof  ParentIDGenerator) {
0590:                                InsertField field = featureRow.getColumn("ID");
0591:                                if (field == null) {
0592:                                    throw new TransactionException(
0593:                                            "No value for ID available!");
0594:                                }
0595:                                pk = field.getValue();
0596:                            } else {
0597:                                pk = relations[0].getNewPK(this .dsTa);
0598:                            }
0599:                            InsertRow insertRow = findOrCreateRow(relations[0]
0600:                                    .getToTable(), pkFields[0].getField(), pk);
0601:                            pkField = insertRow.setColumn(pkFields[0]
0602:                                    .getField(), pk, pkFields[0].getType(),
0603:                                    true);
0604:                            insertRow.setGeometryColumn(propertyColumn,
0605:                                    propertyValue, propertyType, false,
0606:                                    targetSrsCode);
0607:                        } catch (IdGenerationException e) {
0608:                            throw new TransactionException(e.getMessage(), e);
0609:                        }
0610:                        featureRow.linkColumn(fkFields[0].getField(), pkField);
0611:                    }
0612:                }
0613:            }
0614:
0615:            /**
0616:             * Inserts the given feature property.
0617:             * 
0618:             * @param pt
0619:             * @param property
0620:             * @param featureRow
0621:             * @throws TransactionException
0622:             */
0623:            private void insertProperty(MappedFeaturePropertyType pt,
0624:                    FeatureProperty property, InsertRow featureRow)
0625:                    throws TransactionException {
0626:
0627:                // find (concrete) subfeature type for the given property instance
0628:                MappedFeatureType propertyFeatureType = pt
0629:                        .getFeatureTypeReference().getFeatureType();
0630:                MappedFeatureType[] substitutions = propertyFeatureType
0631:                        .getConcreteSubstitutions();
0632:                Feature subFeature = (Feature) property.getValue();
0633:                MappedFeatureType subFeatureType = null;
0634:                for (int i = 0; i < substitutions.length; i++) {
0635:                    if (substitutions[i].getName().equals(subFeature.getName())) {
0636:                        subFeatureType = substitutions[i];
0637:                        break;
0638:                    }
0639:                }
0640:                if (subFeatureType == null) {
0641:                    String msg = Messages
0642:                            .getMessage("DATASTORE_FEATURE_NOT_SUBSTITUTABLE",
0643:                                    propertyFeatureType.getName(), subFeature
0644:                                            .getName());
0645:                    throw new TransactionException(msg);
0646:                }
0647:                boolean needsDisambiguation = propertyFeatureType
0648:                        .hasSeveralImplementations();
0649:
0650:                TableRelation[] relations = pt.getTableRelations();
0651:                if (relations == null || relations.length < 1) {
0652:                    throw new TransactionException(
0653:                            "Invalid feature property definition, feature property "
0654:                                    + "mappings must use at least one 'TableRelation' element.");
0655:                }
0656:
0657:                // workaround for links to dummy InsertRows (of already stored features)
0658:                boolean cutLink = subFeature.getId().startsWith(
0659:                        FeatureIdAssigner.EXISTS_MARKER);
0660:                InsertRow subFeatureRow = null;
0661:                if (cutLink) {
0662:                    try {
0663:                        Object fidValue = FeatureId.removeFIDPrefix(subFeature
0664:                                .getId().substring(1), subFeatureType
0665:                                .getGMLId());
0666:                        subFeatureRow = new FeatureRow(subFeatureType
0667:                                .getTable());
0668:                        // add column value for fid (primary key)
0669:                        String fidColumn = subFeatureType.getGMLId()
0670:                                .getIdFields()[0].getField();
0671:                        subFeatureRow.setColumn(fidColumn, fidValue,
0672:                                subFeatureType.getGMLId().getIdFields()[0]
0673:                                        .getType(), true);
0674:                    } catch (DatastoreException e) {
0675:                        throw new TransactionException(e);
0676:                    }
0677:                } else {
0678:                    // insert sub feature (if it is not already stored)
0679:                    subFeatureRow = insertFeature(subFeature);
0680:                }
0681:
0682:                if (relations.length == 1) {
0683:                    if (relations[0].isFromFK()) {
0684:                        // fk is in feature table
0685:                        MappingField[] pkFields = relations[0].getToFields();
0686:                        MappingField[] fkFields = relations[0].getFromFields();
0687:
0688:                        for (int i = 0; i < pkFields.length; i++) {
0689:                            InsertField pkField = subFeatureRow
0690:                                    .getColumn(pkFields[i].getField());
0691:                            if (pkField == null) {
0692:                                String msg = Messages.getMessage(
0693:                                        "DATASTORE_NO_FK_VALUE", pkField
0694:                                                .getColumnName(), pkField
0695:                                                .getTable());
0696:                                throw new TransactionException(msg);
0697:                            }
0698:                            int pkColumnType = pkField.getSQLType();
0699:                            int fkColumnType = fkFields[i].getType();
0700:                            if (pkColumnType != fkColumnType) {
0701:                                String fkType = "" + fkColumnType;
0702:                                String pkType = "" + pkColumnType;
0703:                                try {
0704:                                    fkType = Types
0705:                                            .getTypeNameForSQLTypeCode(fkColumnType);
0706:                                    pkType = Types
0707:                                            .getTypeNameForSQLTypeCode(pkColumnType);
0708:                                } catch (UnknownTypeException e) {
0709:                                    LOG.logError(e.getMessage(), e);
0710:                                }
0711:                                Object[] params = new Object[] {
0712:                                        featureRow.getTable(),
0713:                                        fkFields[i].getField(), fkType,
0714:                                        subFeatureRow.getTable(),
0715:                                        pkFields[i].getField(), pkType };
0716:                                String msg = Messages
0717:                                        .getMessage(
0718:                                                "DATASTORE_FK_PK_TYPE_MISMATCH",
0719:                                                params);
0720:                                throw new TransactionException(msg);
0721:                            }
0722:
0723:                            if (!cutLink) {
0724:                                featureRow.linkColumn(fkFields[i].getField(),
0725:                                        pkField);
0726:                            } else {
0727:                                featureRow.setColumn(fkFields[i].getField(),
0728:                                        pkField.getValue(), pkField
0729:                                                .getSQLType(), false);
0730:                            }
0731:                        }
0732:
0733:                        if (needsDisambiguation) {
0734:                            String typeField = FT_PREFIX
0735:                                    + relations[0].getFromFields()[0]
0736:                                            .getField();
0737:                            featureRow.setColumn(typeField, subFeatureType
0738:                                    .getName().getLocalName(), Types.VARCHAR,
0739:                                    false);
0740:                        }
0741:                    } else {
0742:                        // fk is in subfeature table
0743:                        MappingField[] pkFields = relations[0].getFromFields();
0744:                        MappingField[] fkFields = relations[0].getToFields();
0745:
0746:                        if (pkFields[0] != null) {
0747:                            LOG.logDebug("Getting column "
0748:                                    + pkFields[0].getField() + "from table: "
0749:                                    + pkFields[0].getTable()
0750:                                    + " of the featureRow: "
0751:                                    + featureRow.getTable());
0752:                        }
0753:
0754:                        InsertField pkField = featureRow.getColumn(pkFields[0]
0755:                                .getField());
0756:
0757:                        if (pkField == null) {
0758:                            String msg = null;
0759:
0760:                            if (pkFields[0] != null) {
0761:                                msg = Messages.getMessage(
0762:                                        "DATASTORE_NO_FK_VALUE", pkFields[0]
0763:                                                .getField(), pkFields[0]
0764:                                                .getTable());
0765:                            } else {
0766:                                if (relations[0] != null) {
0767:                                    msg = Messages
0768:                                            .getMessage(
0769:                                                    "DATASTORE_NO_FK_VALUE",
0770:                                                    "unknown primary keys in 'from'-fields",
0771:                                                    relations[0].getFromTable());
0772:                                } else {
0773:                                    msg = Messages
0774:                                            .getMessage(
0775:                                                    "DATASTORE_NO_FK_VALUE",
0776:                                                    "unknown primary keys in 'from'-fields",
0777:                                                    "unknown 'from'-table");
0778:                                }
0779:                            }
0780:
0781:                            throw new TransactionException(msg);
0782:                        }
0783:                        int pkColumnType = pkField.getSQLType();
0784:                        int fkColumnType = fkFields[0].getType();
0785:                        if (pkColumnType != fkColumnType) {
0786:                            String fkType = "" + fkColumnType;
0787:                            String pkType = "" + pkColumnType;
0788:                            try {
0789:                                fkType = Types
0790:                                        .getTypeNameForSQLTypeCode(fkColumnType);
0791:                                pkType = Types
0792:                                        .getTypeNameForSQLTypeCode(pkColumnType);
0793:                            } catch (UnknownTypeException e) {
0794:                                LOG.logError(e.getMessage(), e);
0795:                            }
0796:                            Object[] params = new Object[] {
0797:                                    subFeatureRow.getTable(),
0798:                                    fkFields[0].getField(), fkType,
0799:                                    featureRow.getTable(),
0800:                                    pkField.getColumnName(), pkType };
0801:                            String msg = Messages.getMessage(
0802:                                    "DATASTORE_FK_PK_TYPE_MISMATCH", params);
0803:                            throw new TransactionException(msg);
0804:                        }
0805:
0806:                        if (!cutLink) {
0807:                            subFeatureRow.linkColumn(fkFields[0].getField(),
0808:                                    pkField);
0809:                        } else {
0810:                            subFeatureRow.setColumn(fkFields[0].getField(),
0811:                                    pkField.getValue(), pkField.getSQLType(),
0812:                                    false);
0813:                        }
0814:                    }
0815:                } else if (relations.length == 2) {
0816:
0817:                    // insert into join table
0818:                    String joinTable = relations[0].getToTable();
0819:                    MappingField[] leftKeyFields = relations[0].getToFields();
0820:                    MappingField[] rightKeyFields = relations[1]
0821:                            .getFromFields();
0822:
0823:                    InsertRow jtRow = new InsertRow(joinTable);
0824:                    if (needsDisambiguation) {
0825:                        jtRow.setColumn(FT_COLUMN, subFeatureType.getName()
0826:                                .getLocalName(), Types.VARCHAR, false);
0827:                    }
0828:
0829:                    if (!relations[0].isFromFK()) {
0830:                        // left key field in join table is fk
0831:                        MappingField[] pkFields = relations[0].getFromFields();
0832:                        InsertField pkField = featureRow.getColumn(pkFields[0]
0833:                                .getField());
0834:                        if (pkField == null) {
0835:                            String columnName = null;
0836:                            if (pkFields[0] != null) {
0837:                                columnName = pkFields[0].getField();
0838:                            } else {
0839:                                columnName = "unknown primary keys in 'from'-fields";
0840:                            }
0841:                            throw new TransactionException(
0842:                                    "Insertion of feature property using join table failed: "
0843:                                            + "no value for join table key column '"
0844:                                            + columnName + "'.");
0845:                        }
0846:                        jtRow.linkColumn(leftKeyFields[0].getField(), pkField);
0847:                    } else {
0848:                        // left key field in join table is pk
0849:                        MappingField[] pkFields = relations[0].getToFields();
0850:                        // generate necessary primary key value
0851:                        InsertField pkField = null;
0852:                        try {
0853:                            Object pk = relations[0].getNewPK(this .dsTa);
0854:                            pkField = jtRow.setColumn(pkFields[0].getField(),
0855:                                    pk, pkFields[0].getType(), true);
0856:                        } catch (IdGenerationException e) {
0857:                            throw new TransactionException(e.getMessage(), e);
0858:                        }
0859:                        featureRow.linkColumn(relations[0].getFromFields()[0]
0860:                                .getField(), pkField);
0861:                    }
0862:
0863:                    if (relations[1].isFromFK()) {
0864:                        // right key field in join table is fk
0865:                        MappingField[] pkFields = relations[1].getToFields();
0866:                        InsertField pkField = subFeatureRow
0867:                                .getColumn(pkFields[0].getField());
0868:                        if (pkField == null) {
0869:                            throw new TransactionException(
0870:                                    "Insertion of feature property using join table failed: "
0871:                                            + "no value for join table key column '"
0872:                                            + pkField.getColumnName() + "'.");
0873:                        }
0874:                        if (!cutLink) {
0875:                            jtRow.linkColumn(rightKeyFields[0].getField(),
0876:                                    pkField);
0877:                        } else {
0878:                            jtRow.setColumn(rightKeyFields[0].getField(),
0879:                                    pkField.getValue(), pkField.getSQLType(),
0880:                                    false);
0881:                        }
0882:                    } else {
0883:                        // right key field in join table is pk
0884:                        MappingField[] pkFields = relations[1].getFromFields();
0885:                        // generate necessary primary key value
0886:                        InsertField pkField = null;
0887:                        try {
0888:                            Object pk = relations[1].getNewPK(this .dsTa);
0889:                            pkField = jtRow.setColumn(pkFields[0].getField(),
0890:                                    pk, pkFields[0].getType(), true);
0891:                        } catch (IdGenerationException e) {
0892:                            throw new TransactionException(e.getMessage(), e);
0893:                        }
0894:                        if (!cutLink) {
0895:                            subFeatureRow.linkColumn(
0896:                                    relations[1].getToFields()[0].getField(),
0897:                                    pkField);
0898:                        }
0899:                    }
0900:                    this .insertRows.add(jtRow);
0901:                } else {
0902:                    throw new TransactionException(
0903:                            "Insertion of feature properties stored in related tables "
0904:                                    + "connected via more than one join table is not supported.");
0905:                }
0906:            }
0907:
0908:            /**
0909:             * Checks whether the feature that corresponds to the given FeatureRow is already stored in the
0910:             * database.
0911:             * 
0912:             * @param featureRow
0913:             * @return true, if feature is already stored, false otherwise
0914:             * @throws DatastoreException
0915:             */
0916:            private boolean doesFeatureExist(FeatureRow featureRow)
0917:                    throws DatastoreException {
0918:
0919:                boolean exists = false;
0920:
0921:                InsertField pkField = featureRow.getPKColumn();
0922:
0923:                StatementBuffer query = buildFeatureSelect(pkField
0924:                        .getColumnName(), pkField.getSQLType(), pkField
0925:                        .getValue(), featureRow.getTable());
0926:                LOG.logDebug("Feature existence query: '" + query + "'");
0927:
0928:                PreparedStatement stmt = null;
0929:                ResultSet rs = null;
0930:                try {
0931:                    stmt = this .datastore.prepareStatement(this .conn, query);
0932:                    rs = stmt.executeQuery();
0933:                    if (rs.next()) {
0934:                        exists = true;
0935:                    }
0936:                    if (rs.next()) {
0937:                        String msg = Messages.getMessage(
0938:                                "DATASTORE_FEATURE_QUERY_MORE_THAN_ONE_RESULT",
0939:                                query.getQueryString());
0940:                        LOG.logError(msg);
0941:                        throw new TransactionException(msg);
0942:                    }
0943:                } catch (SQLException e) {
0944:                    throw new TransactionException(e);
0945:                } finally {
0946:                    try {
0947:                        if (rs != null) {
0948:                            rs.close();
0949:                        }
0950:                    } catch (SQLException e) {
0951:                        throw new TransactionException(e);
0952:                    } finally {
0953:                        if (stmt != null) {
0954:                            try {
0955:                                stmt.close();
0956:                            } catch (SQLException e) {
0957:                                throw new TransactionException(e);
0958:                            }
0959:                        }
0960:                    }
0961:                }
0962:                return exists;
0963:            }
0964:
0965:            /**
0966:             * Builds a SELECT statement that checks for the existence of a feature with the given id.
0967:             * 
0968:             * @param fidColumn
0969:             * @param typeCode
0970:             * @param fidValue
0971:             * @param table
0972:             * @return the statement
0973:             */
0974:            private StatementBuffer buildFeatureSelect(String fidColumn,
0975:                    int typeCode, Object fidValue, String table) {
0976:
0977:                StatementBuffer query = new StatementBuffer();
0978:                query.append("SELECT * FROM ");
0979:                query.append(table);
0980:                query.append(" WHERE ");
0981:
0982:                // append feature id constraints
0983:                query.append(fidColumn);
0984:                query.append("=?");
0985:                query.addArgument(fidValue, typeCode);
0986:                return query;
0987:            }
0988:
0989:            private InsertRow findOrCreateRow(String table, String pkColumn,
0990:                    Object value) {
0991:                Iterator<InsertRow> rowIter = this .insertRows.iterator();
0992:                boolean found = false;
0993:                InsertRow row = null;
0994:                while (rowIter.hasNext()) {
0995:                    row = rowIter.next();
0996:                    if (row.getTable().equals(table)) {
0997:                        InsertField field = row.getColumn(pkColumn);
0998:                        if (value.equals(field.getValue())) {
0999:                            found = true;
1000:                            LOG.logDebug("Found matching row " + row);
1001:                            break;
1002:                        }
1003:                    }
1004:                }
1005:                if (!found) {
1006:                    row = new InsertRow(table);
1007:                    this .insertRows.add(row);
1008:                }
1009:                return row;
1010:            }
1011:
1012:            private String getPropertyValue(FeatureProperty property) {
1013:                Object value = property.getValue();
1014:                StringBuffer sb = new StringBuffer();
1015:                if (value instanceof  Object[]) {
1016:                    Object[] objects = (Object[]) value;
1017:                    for (int i = 0; i < objects.length; i++) {
1018:                        sb.append(objects[i]);
1019:                    }
1020:                } else {
1021:                    sb.append(value);
1022:                }
1023:                return sb.toString();
1024:            }
1025:
1026:            /**
1027:             * Transforms the given <code>List</code> of <code>InsertRows</code> into SQL INSERT
1028:             * statements and executes them using the underlying JDBC connection.
1029:             * 
1030:             * @param inserts
1031:             * @throws DatastoreException
1032:             */
1033:            private void executeInserts(List<InsertRow> inserts)
1034:                    throws DatastoreException {
1035:
1036:                PreparedStatement stmt = null;
1037:
1038:                for (InsertRow row : inserts) {
1039:                    if (row instanceof  FeatureRow) {
1040:                        if (doesFeatureExist((FeatureRow) row)) {
1041:                            LOG
1042:                                    .logDebug("Skipping feature row. Already present in db.");
1043:                            continue;
1044:                        }
1045:                    }
1046:                    try {
1047:                        stmt = null;
1048:                        StatementBuffer insert = createStatementBuffer(row);
1049:                        LOG.logDebug(insert.toString());
1050:                        stmt = this .datastore.prepareStatement(this .conn,
1051:                                insert);
1052:                        stmt.execute();
1053:                    } catch (SQLException e) {
1054:                        String msg = "Error performing insert: "
1055:                                + e.getMessage();
1056:                        LOG.logError(msg, e);
1057:                        throw new TransactionException(msg, e);
1058:                    } finally {
1059:                        if (stmt != null) {
1060:                            try {
1061:                                stmt.close();
1062:                            } catch (SQLException e) {
1063:                                String msg = "Error closing statement: "
1064:                                        + e.getMessage();
1065:                                LOG.logError(msg, e);
1066:                            }
1067:                        }
1068:                    }
1069:                }
1070:            }
1071:
1072:            private StatementBuffer createStatementBuffer(InsertRow row)
1073:                    throws DatastoreException {
1074:                StatementBuffer insert = new StatementBuffer();
1075:                insert.append("INSERT INTO ");
1076:                insert.append(row.table);
1077:                insert.append(" (");
1078:                Iterator<InsertField> columnsIter = row.getColumns().iterator();
1079:                while (columnsIter.hasNext()) {
1080:                    insert.append(columnsIter.next().getColumnName());
1081:                    if (columnsIter.hasNext()) {
1082:                        insert.append(',');
1083:                    }
1084:                }
1085:                insert.append(") VALUES(");
1086:                columnsIter = row.getColumns().iterator();
1087:                while (columnsIter.hasNext()) {
1088:                    String placeHolder = "?";
1089:                    InsertField field = columnsIter.next();
1090:                    if (field instanceof  InsertGeometryField) {
1091:                        int targetSrsCode = ((InsertGeometryField) field)
1092:                                .getTargetSrsCode();
1093:                        if (targetSrsCode != -1) {
1094:                            placeHolder = this .datastore.buildSRSTransformCall(
1095:                                    "?", targetSrsCode);
1096:                        }
1097:                    }
1098:                    insert.append(placeHolder);
1099:                    insert.addArgument(field.getValue(), field.getSQLType());
1100:                    if (columnsIter.hasNext()) {
1101:                        insert.append(',');
1102:                    }
1103:                }
1104:                insert.append(")");
1105:                return insert;
1106:            }
1107:
1108:            /**
1109:             * Merges the given <code>InsertRow</code>s by eliminating rows that have identical content
1110:             * (except for their primary keys).
1111:             * <p>
1112:             * This only applies to non-FeatureRows: there are never two FeatureRows that may be treated as
1113:             * identical, because unique feature ids have been assigned to them before.
1114:             * 
1115:             * @see FeatureIdAssigner
1116:             * 
1117:             * @param insertRows
1118:             * @return merged List of InsertRows
1119:             */
1120:            private List<InsertRow> mergeInsertRows(List<InsertRow> insertRows) {
1121:
1122:                List<InsertRow> result = new ArrayList<InsertRow>();
1123:
1124:                // keys: table names, values: inserts into the table
1125:                Map<String, Collection<InsertRow>> tableMap = new HashMap<String, Collection<InsertRow>>();
1126:
1127:                // build table lookup map
1128:                Iterator<InsertRow> iter = insertRows.iterator();
1129:                while (iter.hasNext()) {
1130:                    InsertRow insertRow = iter.next();
1131:                    Collection<InsertRow> tableInserts = tableMap.get(insertRow
1132:                            .getTable());
1133:                    if (tableInserts == null) {
1134:                        tableInserts = new ArrayList<InsertRow>();
1135:                        tableMap.put(insertRow.getTable(), tableInserts);
1136:                    }
1137:                    tableInserts.add(insertRow);
1138:                }
1139:
1140:                iter = insertRows.iterator();
1141:                while (iter.hasNext()) {
1142:                    InsertRow insertRow = iter.next();
1143:                    boolean insert = true;
1144:                    if (!(insertRow instanceof  FeatureRow)) {
1145:                        Collection<InsertRow> tableInserts = tableMap
1146:                                .get(insertRow.getTable());
1147:                        Iterator<InsertRow> candidatesIter = tableInserts
1148:                                .iterator();
1149:                        while (candidatesIter.hasNext()) {
1150:                            InsertRow candidate = candidatesIter.next();
1151:                            if (insertRow != candidate) {
1152:                                if (compareInsertRows(insertRow, candidate)) {
1153:                                    LOG.logDebug("Removing InsertRow: "
1154:                                            + insertRow.hashCode() + " "
1155:                                            + insertRow + " - duplicate of: "
1156:                                            + candidate);
1157:                                    replaceInsertRow(insertRow, candidate);
1158:                                    insert = false;
1159:                                    tableInserts.remove(insertRow);
1160:                                    break;
1161:                                }
1162:                            }
1163:                        }
1164:                    }
1165:                    if (insert) {
1166:                        result.add(insertRow);
1167:                    }
1168:                }
1169:                return result;
1170:            }
1171:
1172:            private boolean compareInsertRows(InsertRow row1, InsertRow row2) {
1173:                Collection<InsertField> fields1 = row1.getColumns();
1174:                Iterator<InsertField> iter = fields1.iterator();
1175:                while (iter.hasNext()) {
1176:                    InsertField field1 = iter.next();
1177:                    if (!field1.isPK()) {
1178:                        InsertField field2 = row2.getColumn(field1
1179:                                .getColumnName());
1180:                        Object value1 = field1.getValue();
1181:                        Object value2 = null;
1182:                        if (field2 != null)
1183:                            value2 = field2.getValue();
1184:                        if (value1 == null) {
1185:                            if (value2 == null) {
1186:                                continue;
1187:                            }
1188:                            return false;
1189:                        }
1190:                        try {
1191:                            if (!value1.equals(value2)) {
1192:                                return false;
1193:                            }
1194:                        } catch (NullPointerException e) {
1195:                            LOG
1196:                                    .logWarning("A null pointer exception occurred while comparing features/attributes. Assuming they're not equal...");
1197:                            return false;
1198:                        }
1199:                    }
1200:                }
1201:                return true;
1202:            }
1203:
1204:            private void replaceInsertRow(InsertRow oldRow, InsertRow newRow) {
1205:
1206:                Collection<InsertField> oldFields = oldRow.getColumns();
1207:                for (InsertField field : oldFields) {
1208:                    InsertField toField = field.getReferencedField();
1209:                    if (toField != null) {
1210:                        LOG.logDebug("Removing reference to field '" + toField
1211:                                + "'");
1212:                        toField.removeReferencingField(field);
1213:                    }
1214:                }
1215:
1216:                Collection<InsertField> referencingFields = oldRow
1217:                        .getReferencingFields();
1218:                for (InsertField fromField : referencingFields) {
1219:                    LOG.logDebug("Replacing reference for field '" + fromField
1220:                            + "'");
1221:                    InsertField field = newRow.getColumn(fromField
1222:                            .getReferencedField().getColumnName());
1223:                    LOG.logDebug("" + field);
1224:                    fromField.relinkField(field);
1225:                }
1226:            }
1227:        }
www__._j__av___a__2__s.c_o___m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.