Source Code Cross Referenced for FeatureFetcher.java in  » GIS » deegree » org » deegree » io » datastore » sql » 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 
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/FeatureFetcher.java $
0002:        /*----------------    FILE HEADER  ------------------------------------------
0003:
0004:         This file is part of deegree.
0005:         Copyright (C) 2001-2008 by:
0006:         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;
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.HashSet;
0053:        import java.util.List;
0054:        import java.util.Map;
0055:        import java.util.Set;
0056:
0057:        import org.deegree.datatypes.QualifiedName;
0058:        import org.deegree.framework.log.ILogger;
0059:        import org.deegree.framework.log.LoggerFactory;
0060:        import org.deegree.framework.util.StringTools;
0061:        import org.deegree.i18n.Messages;
0062:        import org.deegree.io.datastore.DatastoreException;
0063:        import org.deegree.io.datastore.FeatureId;
0064:        import org.deegree.io.datastore.PropertyPathResolver;
0065:        import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
0066:        import org.deegree.io.datastore.schema.MappedFeatureType;
0067:        import org.deegree.io.datastore.schema.MappedGMLId;
0068:        import org.deegree.io.datastore.schema.MappedGeometryPropertyType;
0069:        import org.deegree.io.datastore.schema.MappedPropertyType;
0070:        import org.deegree.io.datastore.schema.MappedSimplePropertyType;
0071:        import org.deegree.io.datastore.schema.TableRelation;
0072:        import org.deegree.io.datastore.schema.content.ConstantContent;
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.SQLFunctionCall;
0076:        import org.deegree.io.datastore.schema.content.SimpleContent;
0077:        import org.deegree.model.crs.CRSFactory;
0078:        import org.deegree.model.crs.CoordinateSystem;
0079:        import org.deegree.model.crs.UnknownCRSException;
0080:        import org.deegree.model.feature.Feature;
0081:        import org.deegree.model.feature.FeatureFactory;
0082:        import org.deegree.model.feature.FeatureProperty;
0083:        import org.deegree.model.feature.schema.PropertyType;
0084:        import org.deegree.model.spatialschema.Geometry;
0085:        import org.deegree.ogcbase.PropertyPath;
0086:        import org.deegree.ogcwebservices.wfs.operation.Query;
0087:
0088:        /**
0089:         * The only implementation of this abstract class is the {@link QueryHandler} class.
0090:         * <p>
0091:         * While the {@link QueryHandler} class performs the initial SELECT, {@link FeatureFetcher} is responsible for any
0092:         * subsequent SELECTs that may be necessary.
0093:         * 
0094:         * @see QueryHandler
0095:         * 
0096:         * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
0097:         * @author last edited by: $Author: apoth $
0098:         * 
0099:         * @version $Revision: 9342 $, $Date: 2007-12-27 04:32:57 -0800 (Thu, 27 Dec 2007) $
0100:         */
0101:        abstract class FeatureFetcher extends AbstractRequestHandler {
0102:
0103:            private static final ILogger LOG = LoggerFactory
0104:                    .getLogger(FeatureFetcher.class);
0105:
0106:            // key: feature id of features that are generated or are in generation
0107:            protected Set<FeatureId> featuresInGeneration = new HashSet<FeatureId>();
0108:
0109:            // key: feature id value, value: Feature
0110:            protected Map<FeatureId, Feature> featureMap = new HashMap<FeatureId, Feature>(
0111:                    1000);
0112:
0113:            // key: feature id value, value: property instances that contain the feature
0114:            protected Map<FeatureId, List<FeatureProperty>> fidToPropertyMap = new HashMap<FeatureId, List<FeatureProperty>>();
0115:
0116:            // provides virtual content (constants, sql functions, ...)
0117:            protected VirtualContentProvider vcProvider;
0118:
0119:            protected Query query;
0120:
0121:            private CoordinateSystem queryCS;
0122:
0123:            // key: geometry field, value: function call that transforms it to the queried CS
0124:            private Map<MappingGeometryField, SQLFunctionCall> fieldToTransformCall = new HashMap<MappingGeometryField, SQLFunctionCall>();
0125:
0126:            FeatureFetcher(AbstractSQLDatastore datastore,
0127:                    TableAliasGenerator aliasGenerator, Connection conn,
0128:                    Query query) throws DatastoreException {
0129:                super (datastore, aliasGenerator, conn);
0130:                this .query = query;
0131:                if (this .query.getSrsName() != null) {
0132:                    try {
0133:                        this .queryCS = CRSFactory.create(this .query
0134:                                .getSrsName());
0135:                    } catch (UnknownCRSException e) {
0136:                        throw new DatastoreException(e.getMessage(), e);
0137:                    }
0138:                }
0139:            }
0140:
0141:            /**
0142:             * Builds a SELECT statement to fetch features / properties that are stored in a related table.
0143:             * 
0144:             * @param fetchContents
0145:             *            table columns / functions to fetch
0146:             * @param relations
0147:             *            table relations that lead to the table where the property is stored
0148:             * @param resultValues
0149:             *            all retrieved columns from one result set row
0150:             * @param resultPosMap
0151:             *            key class: SimpleContent, value class: Integer (this is the associated index in resultValues)
0152:             * @return the statement or null if the keys in resultValues contain NULL values
0153:             */
0154:            private StatementBuffer buildSubsequentSelect(
0155:                    List<List<SimpleContent>> fetchContents,
0156:                    TableRelation[] relations, Object[] resultValues,
0157:                    Map<SimpleContent, Integer> resultPosMap) {
0158:
0159:                this .aliasGenerator.reset();
0160:                String[] tableAliases = this .aliasGenerator
0161:                        .generateUniqueAliases(relations.length);
0162:
0163:                StatementBuffer query = new StatementBuffer();
0164:                query.append("SELECT ");
0165:                appendQualifiedContentList(query,
0166:                        tableAliases[tableAliases.length - 1], fetchContents);
0167:                query.append(" FROM ");
0168:                query.append(relations[0].getToTable());
0169:                query.append(" ");
0170:                query.append(tableAliases[0]);
0171:
0172:                // append joins
0173:                for (int i = 1; i < relations.length; i++) {
0174:                    query.append(" JOIN ");
0175:                    query.append(relations[i].getToTable());
0176:                    query.append(" ");
0177:                    query.append(tableAliases[i]);
0178:                    query.append(" ON ");
0179:                    MappingField[] fromFields = relations[i].getFromFields();
0180:                    MappingField[] toFields = relations[i].getToFields();
0181:                    for (int j = 0; j < fromFields.length; j++) {
0182:                        query.append(tableAliases[i - 1]);
0183:                        query.append('.');
0184:                        query.append(fromFields[j].getField());
0185:                        query.append('=');
0186:                        query.append(tableAliases[i]);
0187:                        query.append('.');
0188:                        query.append(toFields[j].getField());
0189:                    }
0190:                }
0191:
0192:                // append key constraints
0193:                query.append(" WHERE ");
0194:                MappingField[] fromFields = relations[0].getFromFields();
0195:                MappingField[] toFields = relations[0].getToFields();
0196:                for (int i = 0; i < fromFields.length; i++) {
0197:                    int resultPos = resultPosMap.get(fromFields[i]);
0198:                    Object keyValue = resultValues[resultPos];
0199:                    if (keyValue == null) {
0200:                        return null;
0201:                    }
0202:                    query.append(tableAliases[0]);
0203:                    query.append('.');
0204:                    query.append(toFields[i].getField());
0205:                    query.append("=?");
0206:                    query.addArgument(keyValue, toFields[i].getType());
0207:                    if (i != fromFields.length - 1) {
0208:                        query.append(" AND ");
0209:                    }
0210:                }
0211:                return query;
0212:            }
0213:
0214:            /**
0215:             * Builds a SELECT statement to fetch the feature ids and the (concrete) feature types of feature properties that
0216:             * are stored in a related table (currently limited to *one* join table).
0217:             * <p>
0218:             * This is only necessary for feature properties that contain feature types with more than one possible
0219:             * substitution.
0220:             * 
0221:             * @param relation1
0222:             *            first table relation that leads to the join table
0223:             * @param relation2
0224:             *            second table relation that leads to the table where the property is stored
0225:             * @param resultValues
0226:             *            all retrieved columns from one result set row
0227:             * @param mappingFieldMap
0228:             *            key class: MappingField, value class: Integer (this is the associated index in resultValues)
0229:             * @return the statement or null if the keys in resultValues contain NULL values
0230:             */
0231:            private StatementBuffer buildFeatureTypeSelect(
0232:                    TableRelation relation1, TableRelation relation2,
0233:                    Object[] resultValues, Map mappingFieldMap) {
0234:                StatementBuffer query = new StatementBuffer();
0235:                query.append("SELECT ");
0236:                // append feature type column
0237:                query.append(FT_COLUMN);
0238:                // append feature id columns
0239:                MappingField[] fidFields = relation2.getFromFields();
0240:                for (int i = 0; i < fidFields.length; i++) {
0241:                    query.append(',');
0242:                    query.append(fidFields[i].getField());
0243:                }
0244:                query.append(" FROM ");
0245:                query.append(relation1.getToTable());
0246:                query.append(" WHERE ");
0247:                // append key constraints
0248:                MappingField[] fromFields = relation1.getFromFields();
0249:                MappingField[] toFields = relation1.getToFields();
0250:                for (int i = 0; i < fromFields.length; i++) {
0251:                    Integer resultPos = (Integer) mappingFieldMap
0252:                            .get(fromFields[i]);
0253:                    Object keyValue = resultValues[resultPos.intValue()];
0254:                    if (keyValue == null) {
0255:                        return null;
0256:                    }
0257:                    query.append(toFields[i].getField());
0258:                    query.append("=?");
0259:                    query.addArgument(keyValue, toFields[i].getType());
0260:                    if (i != fromFields.length - 1) {
0261:                        query.append(" AND ");
0262:                    }
0263:                }
0264:                return query;
0265:            }
0266:
0267:            /**
0268:             * Builds a SELECT statement to fetch the feature id and the (concrete) feature type of a feature property that is
0269:             * stored in a related table (with the fk in the current table).
0270:             * <p>
0271:             * This is only necessary for feature properties that contain feature types with more than one possible
0272:             * substitution.
0273:             * 
0274:             * TODO: Select the FT_ column beforehand.
0275:             * 
0276:             * @param relation
0277:             *            table relation that leads to the subfeature table
0278:             * @param resultValues
0279:             *            all retrieved columns from one result set row
0280:             * @param mappingFieldMap
0281:             *            key class: MappingField, value class: Integer (this is the associated index in resultValues)
0282:             * @return the statement or null if the keys in resultValues contain NULL values
0283:             */
0284:            private StatementBuffer buildFeatureTypeSelect(
0285:                    TableRelation relation, Object[] resultValues,
0286:                    Map mappingFieldMap) {
0287:                StatementBuffer query = new StatementBuffer();
0288:                query.append("SELECT DISTINCT ");
0289:                // append feature type column
0290:                query
0291:                        .append(FT_PREFIX
0292:                                + relation.getFromFields()[0].getField());
0293:                // append feature id columns
0294:                MappingField[] fidFields = relation.getFromFields();
0295:                for (int i = 0; i < fidFields.length; i++) {
0296:                    query.append(',');
0297:                    query.append(fidFields[i].getField());
0298:                }
0299:                query.append(" FROM ");
0300:                query.append(relation.getFromTable());
0301:                query.append(" WHERE ");
0302:                // append key constraints
0303:                MappingField[] fromFields = relation.getFromFields();
0304:                for (int i = 0; i < fromFields.length; i++) {
0305:                    Integer resultPos = (Integer) mappingFieldMap
0306:                            .get(fromFields[i]);
0307:                    Object keyValue = resultValues[resultPos.intValue()];
0308:                    if (keyValue == null) {
0309:                        return null;
0310:                    }
0311:                    query.append(fromFields[i].getField());
0312:                    query.append("=?");
0313:                    query.addArgument(keyValue, fromFields[i].getType());
0314:                    if (i != fromFields.length - 1) {
0315:                        query.append(" AND ");
0316:                    }
0317:                }
0318:                return query;
0319:            }
0320:
0321:            /**
0322:             * Builds a SELECT statement that fetches one feature and it's properties.
0323:             * 
0324:             * @param fid
0325:             *            id of the feature to fetch
0326:             * @param table
0327:             *            root table of the feature
0328:             * @param fetchContents
0329:             * @return the statement or null if the keys in resultValues contain NULL values
0330:             */
0331:            private StatementBuffer buildFeatureSelect(FeatureId fid,
0332:                    String table, List<List<SimpleContent>> fetchContents) {
0333:
0334:                StatementBuffer query = new StatementBuffer();
0335:                query.append("SELECT ");
0336:                appendQualifiedContentList(query, table, fetchContents);
0337:                query.append(" FROM ");
0338:                query.append(table);
0339:                query.append(" WHERE ");
0340:
0341:                // append feature id constraints
0342:                MappingField[] fidFields = fid.getFidDefinition().getIdFields();
0343:                for (int i = 0; i < fidFields.length; i++) {
0344:                    query.append(fidFields[i].getField());
0345:                    query.append("=?");
0346:                    query.addArgument(fid.getValue(i), fidFields[i].getType());
0347:                    if (i != fidFields.length - 1) {
0348:                        query.append(" AND ");
0349:                    }
0350:                }
0351:                return query;
0352:            }
0353:
0354:            /**
0355:             * Extracts a feature from the values of a result set row.
0356:             * 
0357:             * @param fid
0358:             *            feature id of the feature
0359:             * @param requestedPropertyMap
0360:             *            requested <code>MappedPropertyType</code>s mapped to <code>Collection</code> of
0361:             *            <code>PropertyPath</code>s
0362:             * @param resultPosMap
0363:             *            key class: MappingField, value class: Integer (this is the associated index in resultValues)
0364:             * @param resultValues
0365:             *            all retrieved columns from one result set row
0366:             * @return the extracted feature
0367:             * @throws SQLException
0368:             *             if a JDBC related error occurs
0369:             * @throws DatastoreException
0370:             * @throws UnknownCRSException
0371:             */
0372:            protected Feature extractFeature(
0373:                    FeatureId fid,
0374:                    Map<MappedPropertyType, Collection<PropertyPath>> requestedPropertyMap,
0375:                    Map<SimpleContent, Integer> resultPosMap,
0376:                    Object[] resultValues) throws SQLException,
0377:                    DatastoreException, UnknownCRSException {
0378:
0379:                LOG.logDebug("id = " + fid.getAsString());
0380:
0381:                this .featuresInGeneration.add(fid);
0382:
0383:                // extract the requested properties of the feature
0384:                List<FeatureProperty> propertyList = new ArrayList<FeatureProperty>();
0385:                for (MappedPropertyType requestedProperty : requestedPropertyMap
0386:                        .keySet()) {
0387:                    Collection<PropertyPath> propertyPaths = requestedPropertyMap
0388:                            .get(requestedProperty);
0389:                    // PropertyPath[] requestingPaths = PropertyPathResolver.determineSubPropertyPaths
0390:                    // (requestedProperty, propertyPaths);
0391:                    Collection<FeatureProperty> props = extractProperties(
0392:                            requestedProperty, propertyPaths, resultPosMap,
0393:                            resultValues);
0394:                    propertyList.addAll(props);
0395:                }
0396:                FeatureProperty[] properties = propertyList
0397:                        .toArray(new FeatureProperty[propertyList.size()]);
0398:                Feature feature = FeatureFactory.createFeature(fid
0399:                        .getAsString(), fid.getFeatureType(), properties);
0400:
0401:                this .featureMap.put(fid, feature);
0402:                return feature;
0403:            }
0404:
0405:            /**
0406:             * Extracts the feature id from the values of a result set row.
0407:             * 
0408:             * @param ft
0409:             *            feature type for which the id shall be extracted
0410:             * @param mfMap
0411:             *            key class: MappingField, value class: Integer (this is the associated index in resultValues)
0412:             * @param resultValues
0413:             *            all retrieved columns from one result set row
0414:             * @return the feature id
0415:             * @throws DatastoreException
0416:             */
0417:            protected FeatureId extractFeatureId(MappedFeatureType ft,
0418:                    Map<SimpleContent, Integer> mfMap, Object[] resultValues)
0419:                    throws DatastoreException {
0420:                MappingField[] idFields = ft.getGMLId().getIdFields();
0421:                Object[] idValues = new Object[idFields.length];
0422:                for (int i = 0; i < idFields.length; i++) {
0423:                    Integer resultPos = mfMap.get(idFields[i]);
0424:                    Object idValue = resultValues[resultPos.intValue()];
0425:                    if (idValue == null) {
0426:                        String msg = Messages.getMessage(
0427:                                "DATASTORE_FEATURE_ID_NULL", ft.getTable(), ft
0428:                                        .getName(), idFields[i].getField());
0429:                        throw new DatastoreException(msg);
0430:                    }
0431:                    idValues[i] = idValue;
0432:                }
0433:                return new FeatureId(ft, idValues);
0434:            }
0435:
0436:            /**
0437:             * Extracts the properties of the given property type from the values of a result set row. If the property is stored
0438:             * in related table, only the key values are present in the result set row and more SELECTs are built and executed
0439:             * to build the property.
0440:             * <p>
0441:             * NOTE: If the property is not stored in a related table, only one FeatureProperty is returned, otherwise the
0442:             * number of properties depends on the multiplicity of the relation.
0443:             * 
0444:             * @param pt
0445:             *            the mapped property type to be extracted
0446:             * @param propertyPaths
0447:             *            property paths that refer to the property to be extracted
0448:             * @param resultPosMap
0449:             *            key class: SimpleContent, value class: Integer (this is the associated index in resultValues)
0450:             * @param resultValues
0451:             *            all retrieved columns from one result set row
0452:             * @return Collection of FeatureProperty instances
0453:             * @throws SQLException
0454:             *             if a JDBC related error occurs
0455:             * @throws DatastoreException
0456:             * @throws UnknownCRSException
0457:             */
0458:            private Collection<FeatureProperty> extractProperties(
0459:                    MappedPropertyType pt,
0460:                    Collection<PropertyPath> propertyPaths,
0461:                    Map<SimpleContent, Integer> resultPosMap,
0462:                    Object[] resultValues) throws SQLException,
0463:                    DatastoreException, UnknownCRSException {
0464:
0465:                Collection<FeatureProperty> result = null;
0466:
0467:                TableRelation[] tableRelations = pt.getTableRelations();
0468:                if (tableRelations != null && tableRelations.length != 0) {
0469:                    LOG.logDebug("Fetching related properties: '"
0470:                            + pt.getName() + "'...");
0471:                    result = fetchRelatedProperties(pt.getName(), pt,
0472:                            propertyPaths, resultPosMap, resultValues);
0473:                } else {
0474:                    Object propertyValue = null;
0475:                    if (pt instanceof  MappedSimplePropertyType) {
0476:                        SimpleContent content = ((MappedSimplePropertyType) pt)
0477:                                .getContent();
0478:                        if (content instanceof  MappingField) {
0479:                            Integer resultPos = resultPosMap.get(content);
0480:                            propertyValue = datastore.convertFromDBType(
0481:                                    resultValues[resultPos.intValue()], pt
0482:                                            .getType());
0483:                        } else if (content instanceof  ConstantContent) {
0484:                            propertyValue = ((ConstantContent) content)
0485:                                    .getValue();
0486:                        } else if (content instanceof  SQLFunctionCall) {
0487:                            Integer resultPos = resultPosMap.get(content);
0488:                            propertyValue = resultValues[resultPos.intValue()];
0489:                        }
0490:                    } else if (pt instanceof  MappedGeometryPropertyType) {
0491:                        MappingGeometryField field = ((MappedGeometryPropertyType) pt)
0492:                                .getMappingField();
0493:                        Integer resultPos = null;
0494:                        SQLFunctionCall transformCall = this .fieldToTransformCall
0495:                                .get(field);
0496:                        if (transformCall != null) {
0497:                            resultPos = resultPosMap.get(transformCall);
0498:                        } else {
0499:                            resultPos = resultPosMap.get(field);
0500:                        }
0501:                        propertyValue = resultValues[resultPos.intValue()];
0502:
0503:                        CoordinateSystem cs = ((MappedGeometryPropertyType) pt)
0504:                                .getCS();
0505:                        if (this .queryCS != null) {
0506:                            cs = this .queryCS;
0507:                        }
0508:                        propertyValue = this .datastore
0509:                                .convertDBToDeegreeGeometry(propertyValue, cs,
0510:                                        conn);
0511:                    } else {
0512:                        String msg = "Unsupported property type: '"
0513:                                + pt.getClass().getName()
0514:                                + "' in QueryHandler.extractProperties(). ";
0515:                        LOG.logError(msg);
0516:                        throw new IllegalArgumentException(msg);
0517:                    }
0518:                    FeatureProperty property = FeatureFactory
0519:                            .createFeatureProperty(pt.getName(), propertyValue);
0520:                    result = new ArrayList<FeatureProperty>();
0521:                    result.add(property);
0522:                }
0523:                return result;
0524:            }
0525:
0526:            /**
0527:             * Extracts a {@link FeatureId} from one result set row.
0528:             * 
0529:             * @param ft
0530:             * @param rs
0531:             * @param startIndex
0532:             * @return feature id from result set row
0533:             * @throws SQLException
0534:             */
0535:            private FeatureId extractFeatureId(MappedFeatureType ft,
0536:                    ResultSet rs, int startIndex) throws SQLException {
0537:                MappedGMLId gmlId = ft.getGMLId();
0538:                MappingField[] idFields = gmlId.getIdFields();
0539:
0540:                Object[] idValues = new Object[idFields.length];
0541:                for (int i = 0; i < idValues.length; i++) {
0542:                    idValues[i] = rs.getObject(i + startIndex);
0543:                }
0544:                return new FeatureId(ft, idValues);
0545:            }
0546:
0547:            /**
0548:             * Determines the columns / functions that have to be fetched from the table of the given {@link MappedFeatureType}
0549:             * and associates identical columns / functions to avoid that the same column / function is SELECTed more than once.
0550:             * <p>
0551:             * Identical columns are put into the same (inner) list.
0552:             * <p>
0553:             * The following {@link SimpleContent} instances of the {@link MappedFeatureType}s annotation are used to build the
0554:             * list:
0555:             * <ul>
0556:             * <li>MappingFields from the wfs:gmlId - annotation element of the feature type definition</li>
0557:             * <li>MappingFields in the annotations of the property element definitions; if the property's content is stored in
0558:             * a related table, the MappingFields used in the first wfs:Relation element's wfs:From element are considered</li>
0559:             * <li>SQLFunctionCalls in the annotations of the property element definitions; if the property's (derived) content
0560:             * is stored in a related table, the MappingFields used in the first wfs:Relation element's wfs:From element are
0561:             * considered</li>
0562:             * </ul>
0563:             * 
0564:             * @param ft
0565:             *            feature type for which the content list is built
0566:             * @param requestedProps
0567:             *            requested properties
0568:             * @return List of Lists (that contains SimpleContent instance that refer the same column)
0569:             * @throws DatastoreException
0570:             */
0571:            protected List<List<SimpleContent>> determineFetchContents(
0572:                    MappedFeatureType ft, PropertyType[] requestedProps)
0573:                    throws DatastoreException {
0574:
0575:                List<List<SimpleContent>> fetchList = new ArrayList<List<SimpleContent>>();
0576:
0577:                // helper lookup map (column names -> referencing MappingField instances)
0578:                Map<String, List<SimpleContent>> columnsMap = new HashMap<String, List<SimpleContent>>();
0579:
0580:                // add table columns that are necessary to build the feature's gml id
0581:                MappingField[] idFields = ft.getGMLId().getIdFields();
0582:                for (int i = 0; i < idFields.length; i++) {
0583:                    List<SimpleContent> mappingFieldList = columnsMap
0584:                            .get(idFields[i].getField());
0585:                    if (mappingFieldList == null) {
0586:                        mappingFieldList = new ArrayList<SimpleContent>();
0587:                    }
0588:                    mappingFieldList.add(idFields[i]);
0589:                    columnsMap.put(idFields[i].getField(), mappingFieldList);
0590:                }
0591:
0592:                // add columns that are necessary to build the requested feature properties
0593:                for (int i = 0; i < requestedProps.length; i++) {
0594:                    MappedPropertyType pt = (MappedPropertyType) requestedProps[i];
0595:                    TableRelation[] tableRelations = pt.getTableRelations();
0596:                    if (tableRelations != null && tableRelations.length != 0) {
0597:                        // if property is not stored in feature type's table, retrieve key fields of
0598:                        // the first relation's 'From' element
0599:                        MappingField[] fields = tableRelations[0]
0600:                                .getFromFields();
0601:                        for (int k = 0; k < fields.length; k++) {
0602:                            List<SimpleContent> list = columnsMap.get(fields[k]
0603:                                    .getField());
0604:                            if (list == null) {
0605:                                list = new ArrayList<SimpleContent>();
0606:                            }
0607:                            list.add(fields[k]);
0608:                            columnsMap.put(fields[k].getField(), list);
0609:                        }
0610:                        // if (content instanceof FeaturePropertyContent) {
0611:                        // if (tableRelations.length == 1) {
0612:                        // // if feature property contains an abstract feature type, retrieve
0613:                        // // feature type as well (stored in column named "FT_fk")
0614:                        // MappedFeatureType subFeatureType = ( (FeaturePropertyContent) content )
0615:                        // .getFeatureTypeReference().getFeatureType();
0616:                        // if (subFeatureType.isAbstract()) {
0617:                        // String typeColumn = FT_PREFIX + fields [0].getField();
0618:                        // columnsMap.put (typeColumn, new ArrayList ());
0619:                        // }
0620:                        // }
0621:                        // }
0622:                    } else {
0623:                        String column = null;
0624:                        SimpleContent content = null;
0625:                        if (pt instanceof  MappedSimplePropertyType) {
0626:                            content = ((MappedSimplePropertyType) pt)
0627:                                    .getContent();
0628:                            if (content instanceof  MappingField) {
0629:                                column = ((MappingField) content).getField();
0630:                            } else {
0631:                                // ignore virtual properties here (handled below)
0632:                                continue;
0633:                            }
0634:                        } else if (pt instanceof  MappedGeometryPropertyType) {
0635:                            content = determineFetchContent((MappedGeometryPropertyType) pt);
0636:                            column = ((MappedGeometryPropertyType) pt)
0637:                                    .getMappingField().getField();
0638:                        } else {
0639:                            assert false;
0640:                        }
0641:                        List<SimpleContent> contentList = columnsMap
0642:                                .get(column);
0643:                        if (contentList == null) {
0644:                            contentList = new ArrayList<SimpleContent>();
0645:                        }
0646:                        contentList.add(content);
0647:                        columnsMap.put(column, contentList);
0648:                    }
0649:                }
0650:
0651:                fetchList.addAll(columnsMap.values());
0652:
0653:                // add functions that are necessary to build the requested feature properties
0654:                for (int i = 0; i < requestedProps.length; i++) {
0655:                    MappedPropertyType pt = (MappedPropertyType) requestedProps[i];
0656:                    TableRelation[] tableRelations = pt.getTableRelations();
0657:                    if (tableRelations == null || tableRelations.length == 0) {
0658:                        if (pt instanceof  MappedSimplePropertyType) {
0659:                            SimpleContent content = ((MappedSimplePropertyType) pt)
0660:                                    .getContent();
0661:                            if (content instanceof  SQLFunctionCall) {
0662:                                List<SimpleContent> functionCallList = new ArrayList<SimpleContent>(
0663:                                        1);
0664:                                functionCallList.add(content);
0665:                                fetchList.add(functionCallList);
0666:                            } else {
0667:                                // ignore other content types here
0668:                                continue;
0669:                            }
0670:                        }
0671:                    }
0672:                }
0673:                return fetchList;
0674:            }
0675:
0676:            /**
0677:             * Determines a {@link SimpleContent} object that represents the queried {@link MappedGeometryProperty} in the
0678:             * requested SRS.
0679:             * <p>
0680:             * <ul>
0681:             * <li>If the query SRS is identical to the geometry field's SRS (and thus the SRS of the stored geometry, the
0682:             * corresponding {@link MappingGeometryField} is returned.</li>
0683:             * <li>If the query SRS differs from the geometry field's SRS (and thus the SRS of the stored geometry, an
0684:             * {@link SQLFunctionCall} is returned that refers to the stored geometry, but transforms it to the queried SRS.</li>
0685:             * </ul>
0686:             * 
0687:             * @param pt
0688:             *            geometry property
0689:             * @return a <code>SimpleContent</code> instance that represents the queried geometry property
0690:             * @throws DatastoreException
0691:             *             if the transform call cannot be generated
0692:             */
0693:            private SimpleContent determineFetchContent(
0694:                    MappedGeometryPropertyType pt) throws DatastoreException {
0695:
0696:                MappingGeometryField field = pt.getMappingField();
0697:                SimpleContent content = field;
0698:
0699:                String queriedSRS = this .datastore.checkTransformation(pt,
0700:                        this .query.getSrsName());
0701:                if (queriedSRS != null) {
0702:                    content = this .fieldToTransformCall.get(field);
0703:                    if (content == null) {
0704:                        content = this .datastore.buildSRSTransformCall(pt,
0705:                                queriedSRS);
0706:                        this .fieldToTransformCall.put(field,
0707:                                (SQLFunctionCall) content);
0708:                    }
0709:                }
0710:                return content;
0711:            }
0712:
0713:            /**
0714:             * Retrieves the feature with the given feature id.
0715:             * 
0716:             * @param fid
0717:             * @param requestedPaths
0718:             * @return the feature with the given type and feature id, may be null
0719:             * @throws SQLException
0720:             * @throws DatastoreException
0721:             * @throws UnknownCRSException
0722:             */
0723:            private Feature fetchFeature(FeatureId fid,
0724:                    PropertyPath[] requestedPaths) throws SQLException,
0725:                    DatastoreException, UnknownCRSException {
0726:
0727:                Feature feature = null;
0728:                MappedFeatureType ft = fid.getFeatureType();
0729:                // TODO what about aliases here?
0730:                Map<MappedPropertyType, Collection<PropertyPath>> requestedPropMap = PropertyPathResolver
0731:                        .determineFetchProperties(ft, null, requestedPaths);
0732:                MappedPropertyType[] requestedProps = requestedPropMap
0733:                        .keySet()
0734:                        .toArray(
0735:                                new MappedPropertyType[requestedPropMap.size()]);
0736:
0737:                if (requestedProps.length > 0) {
0738:
0739:                    // determine contents (fields / functions) that must be SELECTed from root table
0740:                    List<List<SimpleContent>> fetchContents = determineFetchContents(
0741:                            ft, requestedProps);
0742:                    Map<SimpleContent, Integer> resultPosMap = buildResultPosMap(fetchContents);
0743:
0744:                    // build feature query
0745:                    StatementBuffer query = buildFeatureSelect(fid, ft
0746:                            .getTable(), fetchContents);
0747:                    LOG.logDebug("Feature query: '" + query + "'");
0748:                    Object[] resultValues = new Object[fetchContents.size()];
0749:                    PreparedStatement stmt = null;
0750:                    ResultSet rs = null;
0751:                    try {
0752:                        stmt = this .datastore
0753:                                .prepareStatement(this .conn, query);
0754:                        rs = stmt.executeQuery();
0755:
0756:                        if (rs.next()) {
0757:                            // collect result values
0758:                            for (int i = 0; i < resultValues.length; i++) {
0759:                                resultValues[i] = rs.getObject(i + 1);
0760:                            }
0761:                            feature = extractFeature(fid, requestedPropMap,
0762:                                    resultPosMap, resultValues);
0763:                        } else {
0764:                            String msg = Messages.getMessage(
0765:                                    "DATASTORE_FEATURE_QUERY_NO_RESULT", query
0766:                                            .getQueryString());
0767:                            LOG.logError(msg);
0768:                            throw new DatastoreException(msg);
0769:                        }
0770:                        if (rs.next()) {
0771:                            String msg = Messages
0772:                                    .getMessage(
0773:                                            "DATASTORE_FEATURE_QUERY_MORE_THAN_ONE_RESULT",
0774:                                            query.getQueryString());
0775:                            LOG.logError(msg);
0776:                            throw new DatastoreException(msg);
0777:                        }
0778:                    } finally {
0779:                        try {
0780:                            if (rs != null) {
0781:                                rs.close();
0782:                            }
0783:                        } finally {
0784:                            if (stmt != null) {
0785:                                stmt.close();
0786:                            }
0787:                        }
0788:                    }
0789:                }
0790:                return feature;
0791:            }
0792:
0793:            /**
0794:             * 
0795:             * @param propertyName
0796:             * @param pt
0797:             * @param propertyPaths
0798:             *            property paths that refer to the property to be extracted
0799:             * @param resultPosMap
0800:             *            key class: MappingField, value class: Integer (this is the associated index in resultValues)
0801:             * @param resultValues
0802:             *            all retrieved columns from one result set row
0803:             * @return Collection of FeatureProperty instances
0804:             * @throws SQLException
0805:             *             if a JDBC related error occurs
0806:             * @throws DatastoreException
0807:             * @throws UnknownCRSException
0808:             */
0809:            private Collection<FeatureProperty> fetchRelatedProperties(
0810:                    QualifiedName propertyName, MappedPropertyType pt,
0811:                    Collection<PropertyPath> propertyPaths,
0812:                    Map<SimpleContent, Integer> resultPosMap,
0813:                    Object[] resultValues) throws SQLException,
0814:                    DatastoreException, UnknownCRSException {
0815:
0816:                Collection<FeatureProperty> result = new ArrayList<FeatureProperty>(
0817:                        100);
0818:                PreparedStatement stmt = null;
0819:                ResultSet rs = null;
0820:                try {
0821:                    if (pt instanceof  MappedSimplePropertyType) {
0822:                        SimpleContent content = ((MappedSimplePropertyType) pt)
0823:                                .getContent();
0824:
0825:                        // TODO check for invalid content types
0826:                        List<SimpleContent> fetchContents = new ArrayList<SimpleContent>(
0827:                                1);
0828:                        List<List<SimpleContent>> fetchContentsList = new ArrayList<List<SimpleContent>>(
0829:                                1);
0830:                        fetchContents.add(content);
0831:                        fetchContentsList.add(fetchContents);
0832:
0833:                        StatementBuffer query = buildSubsequentSelect(
0834:                                fetchContentsList, pt.getTableRelations(),
0835:                                resultValues, resultPosMap);
0836:                        LOG.logDebug("Subsequent query: '" + query + "'");
0837:                        if (query != null) {
0838:                            stmt = this .datastore.prepareStatement(this .conn,
0839:                                    query);
0840:                            rs = stmt.executeQuery();
0841:                            while (rs.next()) {
0842:                                Object propertyValue = datastore
0843:                                        .convertFromDBType(rs.getObject(1), pt
0844:                                                .getType());
0845:                                FeatureProperty property = FeatureFactory
0846:                                        .createFeatureProperty(propertyName,
0847:                                                propertyValue);
0848:                                result.add(property);
0849:                            }
0850:                        }
0851:
0852:                    } else if (pt instanceof  MappedGeometryPropertyType) {
0853:                        SimpleContent content = ((MappedGeometryPropertyType) pt)
0854:                                .getMappingField();
0855:                        CoordinateSystem cs = ((MappedGeometryPropertyType) pt)
0856:                                .getCS();
0857:
0858:                        if (this .queryCS != null) {
0859:                            cs = this .queryCS;
0860:                        }
0861:                        content = determineFetchContent((MappedGeometryPropertyType) pt);
0862:
0863:                        List<SimpleContent> fetchContents = new ArrayList<SimpleContent>(
0864:                                1);
0865:                        List<List<SimpleContent>> fetchContentsList = new ArrayList<List<SimpleContent>>(
0866:                                1);
0867:                        fetchContents.add(content);
0868:                        fetchContentsList.add(fetchContents);
0869:
0870:                        StatementBuffer query = buildSubsequentSelect(
0871:                                fetchContentsList, pt.getTableRelations(),
0872:                                resultValues, resultPosMap);
0873:                        LOG.logDebug("Subsequent query: '" + query + "'");
0874:                        if (query != null) {
0875:                            stmt = this .datastore.prepareStatement(this .conn,
0876:                                    query);
0877:                            rs = stmt.executeQuery();
0878:                            while (rs.next()) {
0879:                                Object value = rs.getObject(1);
0880:                                Geometry geometry = this .datastore
0881:                                        .convertDBToDeegreeGeometry(value, cs,
0882:                                                this .conn);
0883:                                FeatureProperty property = FeatureFactory
0884:                                        .createFeatureProperty(propertyName,
0885:                                                geometry);
0886:                                result.add(property);
0887:                            }
0888:                        }
0889:                    } else if (pt instanceof  MappedFeaturePropertyType) {
0890:                        MappedFeatureType ft = ((MappedFeaturePropertyType) pt)
0891:                                .getFeatureTypeReference().getFeatureType();
0892:                        MappedFeatureType[] substitutions = ft
0893:                                .getConcreteSubstitutions();
0894:                        if (substitutions.length > 1) {
0895:                            // if feature type has more than one concrete substitution, determine concrete
0896:                            // feature type first
0897:                            String msg = StringTools.concat(200,
0898:                                    "FeatureType '", ft.getName(),
0899:                                    "' has more than one concrete ",
0900:                                    "substitution. Need to determine ",
0901:                                    "feature type table first.");
0902:                            LOG.logDebug(msg);
0903:                            LOG.logDebug("Property: " + pt.getName());
0904:                            TableRelation[] tableRelations = pt
0905:                                    .getTableRelations();
0906:                            if (tableRelations.length == 2) {
0907:                                StatementBuffer query = buildFeatureTypeSelect(
0908:                                        tableRelations[0], tableRelations[1],
0909:                                        resultValues, resultPosMap);
0910:                                LOG.logDebug("Feature type (and id) query: '"
0911:                                        + query + "'");
0912:                                if (query != null) {
0913:                                    stmt = this .datastore.prepareStatement(
0914:                                            this .conn, query);
0915:                                    rs = stmt.executeQuery();
0916:                                    while (rs.next()) {
0917:                                        String featureTypeName = rs
0918:                                                .getString(1);
0919:                                        MappedFeatureType concreteFeatureType = ft
0920:                                                .getGMLSchema().getFeatureType(
0921:                                                        featureTypeName);
0922:                                        if (concreteFeatureType == null) {
0923:                                            msg = StringTools
0924:                                                    .concat(
0925:                                                            200,
0926:                                                            "Lookup of concrete feature type '",
0927:                                                            featureTypeName,
0928:                                                            "' failed: ",
0929:                                                            " Inconsistent featuretype column!?");
0930:                                            LOG.logError(msg);
0931:                                            throw new DatastoreException(msg);
0932:                                        }
0933:                                        FeatureId fid = extractFeatureId(
0934:                                                concreteFeatureType, rs, 2);
0935:                                        msg = StringTools
0936:                                                .concat(
0937:                                                        200,
0938:                                                        "Subfeature '",
0939:                                                        fid.getAsString(),
0940:                                                        "' has concrete feature type '",
0941:                                                        concreteFeatureType
0942:                                                                .getName(),
0943:                                                        "'.");
0944:                                        LOG.logDebug(msg);
0945:
0946:                                        if (!this .featuresInGeneration
0947:                                                .contains(fid)) {
0948:                                            PropertyPath[] subPropertyPaths = PropertyPathResolver
0949:                                                    .determineSubPropertyPaths(
0950:                                                            concreteFeatureType,
0951:                                                            propertyPaths);
0952:                                            Feature feature = fetchFeature(fid,
0953:                                                    subPropertyPaths);
0954:                                            if (feature != null) {
0955:                                                FeatureProperty property = FeatureFactory
0956:                                                        .createFeatureProperty(
0957:                                                                propertyName,
0958:                                                                feature);
0959:                                                result.add(property);
0960:                                            }
0961:                                        } else {
0962:                                            FeatureProperty property = FeatureFactory
0963:                                                    .createFeatureProperty(
0964:                                                            propertyName, null);
0965:                                            addToFidToPropertyMap(fid, property);
0966:                                            result.add(property);
0967:                                        }
0968:                                    }
0969:                                }
0970:                            } else if (tableRelations.length == 1) {
0971:                                StatementBuffer query = buildFeatureTypeSelect(
0972:                                        tableRelations[0], resultValues,
0973:                                        resultPosMap);
0974:                                LOG.logDebug("Feature type (and id) query: '"
0975:                                        + query + "'");
0976:                                if (query != null) {
0977:                                    stmt = this .datastore.prepareStatement(
0978:                                            this .conn, query);
0979:                                    rs = stmt.executeQuery();
0980:                                    while (rs.next()) {
0981:                                        String featureTypeName = rs
0982:                                                .getString(1);
0983:                                        MappedFeatureType concreteFeatureType = ft
0984:                                                .getGMLSchema().getFeatureType(
0985:                                                        featureTypeName);
0986:                                        if (concreteFeatureType == null) {
0987:                                            msg = StringTools
0988:                                                    .concat(
0989:                                                            200,
0990:                                                            "Lookup of concrete feature type '",
0991:                                                            featureTypeName,
0992:                                                            "' failed: ",
0993:                                                            " Inconsistent featuretype column!?");
0994:                                            LOG.logError(msg);
0995:                                            throw new DatastoreException(msg);
0996:                                        }
0997:
0998:                                        FeatureId fid = extractFeatureId(
0999:                                                concreteFeatureType, rs, 2);
1000:
1001:                                        msg = StringTools
1002:                                                .concat(
1003:                                                        200,
1004:                                                        "Subfeature '",
1005:                                                        fid.getAsString(),
1006:                                                        "' has concrete feature type '",
1007:                                                        concreteFeatureType
1008:                                                                .getName(),
1009:                                                        "'.");
1010:                                        LOG.logDebug(msg);
1011:
1012:                                        FeatureProperty property = null;
1013:                                        if (!this .featuresInGeneration
1014:                                                .contains(fid)) {
1015:                                            PropertyPath[] subPropertyPaths = PropertyPathResolver
1016:                                                    .determineSubPropertyPaths(
1017:                                                            concreteFeatureType,
1018:                                                            propertyPaths);
1019:                                            Feature feature = fetchFeature(fid,
1020:                                                    subPropertyPaths);
1021:                                            if (feature != null) {
1022:                                                property = FeatureFactory
1023:                                                        .createFeatureProperty(
1024:                                                                propertyName,
1025:                                                                feature);
1026:                                                result.add(property);
1027:                                            }
1028:
1029:                                        } else {
1030:                                            property = FeatureFactory
1031:                                                    .createFeatureProperty(
1032:                                                            propertyName, null);
1033:                                            addToFidToPropertyMap(fid, property);
1034:                                            result.add(property);
1035:                                        }
1036:                                    }
1037:                                }
1038:                            } else {
1039:                                msg = StringTools
1040:                                        .concat(
1041:                                                200,
1042:                                                "Querying of feature properties ",
1043:                                                "with a content type with more than one ",
1044:                                                "concrete substitution is not implemented for ",
1045:                                                tableRelations.length,
1046:                                                " TableRelations.");
1047:                                throw new DatastoreException(msg);
1048:                            }
1049:                        } else {
1050:                            // feature type is the only substitutable concrete feature type
1051:                            PropertyPath[] subPropertyPaths = PropertyPathResolver
1052:                                    .determineSubPropertyPaths(ft,
1053:                                            propertyPaths);
1054:                            // TODO aliases?
1055:                            Map<MappedPropertyType, Collection<PropertyPath>> requestedPropertiesMap = PropertyPathResolver
1056:                                    .determineFetchProperties(ft, null,
1057:                                            subPropertyPaths);
1058:                            MappedPropertyType[] requestedProperties = requestedPropertiesMap
1059:                                    .keySet()
1060:                                    .toArray(
1061:                                            new MappedPropertyType[requestedPropertiesMap
1062:                                                    .size()]);
1063:
1064:                            // determine contents (fields / functions) that needs to be SELECTed from
1065:                            // current table
1066:                            List<List<SimpleContent>> fetchContents = determineFetchContents(
1067:                                    ft, requestedProperties);
1068:                            Map<SimpleContent, Integer> newResultPosMap = buildResultPosMap(fetchContents);
1069:
1070:                            StatementBuffer query = buildSubsequentSelect(
1071:                                    fetchContents, pt.getTableRelations(),
1072:                                    resultValues, resultPosMap);
1073:                            LOG.logDebug("Subsequent query: '" + query + "'");
1074:
1075:                            if (query != null) {
1076:                                Object[] newResultValues = new Object[fetchContents
1077:                                        .size()];
1078:                                stmt = this .datastore.prepareStatement(
1079:                                        this .conn, query);
1080:                                rs = stmt.executeQuery();
1081:                                while (rs.next()) {
1082:                                    // cache result values
1083:                                    for (int i = 0; i < newResultValues.length; i++) {
1084:                                        newResultValues[i] = rs
1085:                                                .getObject(i + 1);
1086:                                    }
1087:                                    FeatureId fid = extractFeatureId(ft,
1088:                                            newResultPosMap, newResultValues);
1089:                                    FeatureProperty property = null;
1090:                                    if (!this .featuresInGeneration
1091:                                            .contains(fid)) {
1092:                                        Feature feature = extractFeature(fid,
1093:                                                requestedPropertiesMap,
1094:                                                newResultPosMap,
1095:                                                newResultValues);
1096:                                        property = FeatureFactory
1097:                                                .createFeatureProperty(
1098:                                                        propertyName, feature);
1099:                                    } else {
1100:                                        property = FeatureFactory
1101:                                                .createFeatureProperty(
1102:                                                        propertyName, null);
1103:                                        addToFidToPropertyMap(fid, property);
1104:                                    }
1105:                                    result.add(property);
1106:                                }
1107:                            }
1108:                        }
1109:                    } else {
1110:                        String msg = "Unsupported content type: '"
1111:                                + pt.getClass().getName()
1112:                                + "' in QueryHandler.fetchRelatedProperties().";
1113:                        throw new IllegalArgumentException(msg);
1114:                    }
1115:                } finally {
1116:                    try {
1117:                        if (rs != null) {
1118:                            rs.close();
1119:                        }
1120:                        if (stmt != null) {
1121:                            stmt.close();
1122:                        }
1123:                    } finally {
1124:                        if (stmt != null) {
1125:                            stmt.close();
1126:                        }
1127:                    }
1128:                }
1129:                return result;
1130:            }
1131:
1132:            private void addToFidToPropertyMap(FeatureId fid,
1133:                    FeatureProperty property) {
1134:                List<FeatureProperty> properties = this .fidToPropertyMap
1135:                        .get(fid);
1136:                if (properties == null) {
1137:                    properties = new ArrayList<FeatureProperty>();
1138:                    this .fidToPropertyMap.put(fid, properties);
1139:                }
1140:                properties.add(property);
1141:            }
1142:
1143:            protected void appendQualifiedContentList(StatementBuffer query,
1144:                    String tableAlias, List<List<SimpleContent>> fetchContents) {
1145:
1146:                for (int i = 0; i < fetchContents.size(); i++) {
1147:                    SimpleContent content = fetchContents.get(i).get(0);
1148:                    if (content instanceof  MappingField) {
1149:                        appendQualifiedColumn(query, tableAlias,
1150:                                ((MappingField) content).getField());
1151:                    } else if (content instanceof  SQLFunctionCall) {
1152:                        this .vcProvider.appendSQLFunctionCall(query,
1153:                                tableAlias, (SQLFunctionCall) content);
1154:                    } else {
1155:                        assert false;
1156:                    }
1157:                    if (i != fetchContents.size() - 1) {
1158:                        query.append(",");
1159:                    }
1160:                }
1161:            }
1162:
1163:            /**
1164:             * Builds a lookup map that allows to find the index (position in the {@link ResultSet}) by the
1165:             * {@link SimpleContent} instance that makes it necessary to fetch it.
1166:             * 
1167:             * @param fetchContents
1168:             * @return key: SimpleContent, value: Integer (position in ResultSet)
1169:             */
1170:            protected Map<SimpleContent, Integer> buildResultPosMap(
1171:                    List<List<SimpleContent>> fetchContents) {
1172:
1173:                Map<SimpleContent, Integer> resultPosMap = new HashMap<SimpleContent, Integer>();
1174:                for (int i = 0; i < fetchContents.size(); i++) {
1175:                    for (SimpleContent content : fetchContents.get(i)) {
1176:                        resultPosMap.put(content, i);
1177:                    }
1178:                }
1179:                return resultPosMap;
1180:            }
1181:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.