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


0001:        //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/feature/GMLFeatureAdapter.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.model.feature;
0044:
0045:        import java.io.ByteArrayInputStream;
0046:        import java.io.ByteArrayOutputStream;
0047:        import java.io.IOException;
0048:        import java.io.OutputStream;
0049:        import java.io.OutputStreamWriter;
0050:        import java.io.PrintWriter;
0051:        import java.math.BigDecimal;
0052:        import java.net.URI;
0053:        import java.sql.Timestamp;
0054:        import java.util.Calendar;
0055:        import java.util.Date;
0056:        import java.util.HashMap;
0057:        import java.util.HashSet;
0058:        import java.util.Iterator;
0059:        import java.util.Map;
0060:        import java.util.Set;
0061:
0062:        import org.deegree.datatypes.QualifiedName;
0063:        import org.deegree.datatypes.Types;
0064:        import org.deegree.framework.log.ILogger;
0065:        import org.deegree.framework.log.LoggerFactory;
0066:        import org.deegree.framework.util.CharsetUtils;
0067:        import org.deegree.framework.util.StringTools;
0068:        import org.deegree.framework.util.TimeTools;
0069:        import org.deegree.framework.xml.DOMPrinter;
0070:        import org.deegree.framework.xml.XMLException;
0071:        import org.deegree.framework.xml.XMLFragment;
0072:        import org.deegree.framework.xml.XMLTools;
0073:        import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
0074:        import org.deegree.io.datastore.schema.MappedFeatureType;
0075:        import org.deegree.model.feature.schema.FeatureType;
0076:        import org.deegree.model.feature.schema.PropertyType;
0077:        import org.deegree.model.spatialschema.Envelope;
0078:        import org.deegree.model.spatialschema.GMLGeometryAdapter;
0079:        import org.deegree.model.spatialschema.Geometry;
0080:        import org.deegree.model.spatialschema.GeometryException;
0081:        import org.deegree.ogcbase.CommonNamespaces;
0082:        import org.w3c.dom.Element;
0083:        import org.xml.sax.SAXException;
0084:
0085:        /**
0086:         * Exports feature instances to their GML representation.
0087:         * <p>
0088:         * Has support for XLink output and to disable XLink output (which is generally not feasible).
0089:         * <p>
0090:         * Also responsible for "xlinking" features: if a feature occurs several times in a feature collection, it must be
0091:         * exported only once - all other occurences must use xlink-attributes in the surrounding property element to reference
0092:         * the feature.
0093:         * 
0094:         * TODO Handle FeatureCollections like ordinary Features (needs changes in feature model).
0095:         * 
0096:         * TODO Separate cycle check (for suppressXLinkOutput).
0097:         * 
0098:         * TODO Use a more straight-forward approach to export DOM representations.
0099:         * 
0100:         * TODO Handle multiple application schemas (in xsi:schemaLocation attribute).
0101:         * 
0102:         * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
0103:         * @author last edited by: $Author: rbezema $
0104:         * 
0105:         * @version $Revision: 10123 $, $Date: 2008-02-18 09:44:53 -0800 (Mon, 18 Feb 2008) $
0106:         */
0107:        public class GMLFeatureAdapter {
0108:
0109:            private static final ILogger LOG = LoggerFactory
0110:                    .getLogger(GMLFeatureAdapter.class);
0111:
0112:            private static final String WFS_SCHEMA_BINDING = "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd";
0113:
0114:            // values: feature ids of already exported features (for XLinks)
0115:            private Set<String> exportedFeatures = new HashSet<String>();
0116:
0117:            // values: feature ids of all (sub-) features in a feature (to find cyclic features)
0118:            private Set<String> localFeatures = new HashSet<String>();
0119:
0120:            private boolean suppressXLinkOutput;
0121:
0122:            private String schemaURL;
0123:
0124:            // marks if namespace bindings have been appended already
0125:            private boolean nsBindingsExported;
0126:
0127:            /**
0128:             * Creates a new <code>GMLFeatureAdapter</code> instance with enabled XLink output.
0129:             */
0130:            public GMLFeatureAdapter() {
0131:                this .suppressXLinkOutput = false;
0132:            }
0133:
0134:            /**
0135:             * Creates a new <code>GMLFeatureAdapter</code> instance with enabled XLink output and schema reference.
0136:             * 
0137:             * @param schemaURL
0138:             *            URL of schema document (used as xsi:schemaLocation attribute in XML output)
0139:             */
0140:            public GMLFeatureAdapter(String schemaURL) {
0141:                this .suppressXLinkOutput = false;
0142:                if (schemaURL != null) {
0143:                    this .schemaURL = StringTools.replace(schemaURL, "&",
0144:                            "&amp;", true);
0145:                }
0146:            }
0147:
0148:            /**
0149:             * Creates a new instance <code>GMLFeatureAdapter</code> with configurable XLink output.
0150:             * 
0151:             * @param suppressXLinkOutput
0152:             *            set to true, if no XLinks shall be used
0153:             */
0154:            public GMLFeatureAdapter(boolean suppressXLinkOutput) {
0155:                this .suppressXLinkOutput = suppressXLinkOutput;
0156:            }
0157:
0158:            /**
0159:             * Creates a new instance <code>GMLFeatureAdapter</code> with configurable XLink output.
0160:             * 
0161:             * @param suppressXLinkOutput
0162:             *            set to true, if no XLinks shall be used
0163:             * @param schemaURL
0164:             *            URL of schema document (used as xsi:schemaLocation attribute in XML output)
0165:             */
0166:            public GMLFeatureAdapter(boolean suppressXLinkOutput,
0167:                    String schemaURL) {
0168:                this .suppressXLinkOutput = suppressXLinkOutput;
0169:                if (schemaURL != null) {
0170:                    this .schemaURL = StringTools.replace(schemaURL, "&",
0171:                            "&amp;", true);
0172:                }
0173:            }
0174:
0175:            /**
0176:             * Appends the DOM representation of the given feature to the also given <code>Node</code>.
0177:             * <p>
0178:             * TODO do this a better way (append nodes directly without serializing to string and parsing it again)
0179:             * 
0180:             * @param root
0181:             * @param feature
0182:             * @throws FeatureException
0183:             * @throws IOException
0184:             * @throws SAXException
0185:             */
0186:            public void append(Element root, Feature feature)
0187:                    throws FeatureException, IOException, SAXException {
0188:
0189:                GMLFeatureDocument doc = export(feature);
0190:                XMLTools.insertNodeInto(doc.getRootElement(), root);
0191:            }
0192:
0193:            /**
0194:             * Export a <code>Feature</code> to it's XML representation.
0195:             * 
0196:             * @param feature
0197:             *            feature to export
0198:             * @return XML representation of feature
0199:             * @throws IOException
0200:             * @throws FeatureException
0201:             * @throws XMLException
0202:             * @throws SAXException
0203:             */
0204:            public GMLFeatureDocument export(Feature feature)
0205:                    throws IOException, FeatureException, XMLException,
0206:                    SAXException {
0207:
0208:                ByteArrayOutputStream bos = new ByteArrayOutputStream(20000);
0209:                export(feature, bos);
0210:                ByteArrayInputStream bis = new ByteArrayInputStream(bos
0211:                        .toByteArray());
0212:                bos.close();
0213:
0214:                GMLFeatureDocument doc = new GMLFeatureDocument();
0215:                doc.load(bis, XMLFragment.DEFAULT_URL);
0216:                return doc;
0217:            }
0218:
0219:            /**
0220:             * Appends the DOM representation of the given <code>FeatureCollection</code> to the also given <code>Node</code>.
0221:             * <p>
0222:             * TODO do this a better way (append nodes directly without serializing to string and parsing it again)
0223:             * 
0224:             * @param root
0225:             * @param fc
0226:             * @throws FeatureException
0227:             * @throws IOException
0228:             * @throws SAXException
0229:             */
0230:            public void append(Element root, FeatureCollection fc)
0231:                    throws FeatureException, IOException, SAXException {
0232:
0233:                GMLFeatureCollectionDocument doc = export(fc);
0234:                XMLTools.insertNodeInto(doc.getRootElement(), root);
0235:            }
0236:
0237:            /**
0238:             * Export a <code>FeatureCollection</code> to it's XML representation.
0239:             * 
0240:             * @param fc
0241:             *            feature collection
0242:             * @return XML representation of feature collection
0243:             * @throws IOException
0244:             * @throws FeatureException
0245:             * @throws XMLException
0246:             * @throws SAXException
0247:             */
0248:            public GMLFeatureCollectionDocument export(FeatureCollection fc)
0249:                    throws IOException, FeatureException, XMLException,
0250:                    SAXException {
0251:
0252:                ByteArrayOutputStream bos = new ByteArrayOutputStream(20000);
0253:                export(fc, bos);
0254:                ByteArrayInputStream bis = new ByteArrayInputStream(bos
0255:                        .toByteArray());
0256:                bos.close();
0257:
0258:                GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
0259:                doc.load(bis, XMLFragment.DEFAULT_URL);
0260:                return doc;
0261:            }
0262:
0263:            /**
0264:             * Exports an instance of a <code>FeatureCollection</code> to the passed <code>OutputStream</code> formatted as
0265:             * GML. Uses the deegree system character set for the XML header encoding information.
0266:             * 
0267:             * @param fc
0268:             *            feature collection to export
0269:             * @param os
0270:             *            output stream to write to
0271:             * 
0272:             * @throws IOException
0273:             * @throws FeatureException
0274:             */
0275:            public void export(FeatureCollection fc, OutputStream os)
0276:                    throws IOException, FeatureException {
0277:                export(fc, os, CharsetUtils.getSystemCharset());
0278:            }
0279:
0280:            /**
0281:             * Exports a <code>FeatureCollection</code> instance to the passed <code>OutputStream</code> formatted as GML.
0282:             * 
0283:             * @param fc
0284:             *            feature collection to export
0285:             * @param os
0286:             *            output stream to write to
0287:             * @param charsetName
0288:             *            name of the used charset/encoding (for the XML header)
0289:             * 
0290:             * @throws IOException
0291:             * @throws FeatureException
0292:             */
0293:            public void export(FeatureCollection fc, OutputStream os,
0294:                    String charsetName) throws IOException, FeatureException {
0295:
0296:                PrintWriter pw = new PrintWriter(new OutputStreamWriter(os,
0297:                        charsetName));
0298:                pw.println("<?xml version=\"1.0\" encoding=\"" + charsetName
0299:                        + "\"?>");
0300:                if (fc instanceof  FeatureTupleCollection) {
0301:                    exportTupleCollection((FeatureTupleCollection) fc, pw);
0302:                } else {
0303:                    exportRootCollection(fc, pw);
0304:                }
0305:                pw.close();
0306:            }
0307:
0308:            /**
0309:             * Exports a <code>FeatureCollection</code> instance to the passed <code>OutputStream</code> formatted as GML.
0310:             * 
0311:             * @param fc
0312:             *            feature collection to print/export
0313:             * @param pw
0314:             *            target of the printing/export
0315:             * @throws FeatureException
0316:             */
0317:            private void exportRootCollection(FeatureCollection fc,
0318:                    PrintWriter pw) throws FeatureException {
0319:
0320:                Set<Feature> additionalRootLevelFeatures = determineAdditionalRootLevelFeatures(fc);
0321:                if (this .suppressXLinkOutput
0322:                        && additionalRootLevelFeatures.size() > 0) {
0323:                    String msg = Messages.getString("ERROR_REFERENCE_TYPE");
0324:                    throw new FeatureException(msg);
0325:                }
0326:
0327:                if (fc.getId() != null && !"".equals(fc.getId())) {
0328:                    this .exportedFeatures.add(fc.getId());
0329:                }
0330:
0331:                // open the feature collection element
0332:                pw.print("<");
0333:                pw.print(fc.getName().getPrefixedName());
0334:
0335:                // hack to correct the "numberOfFeatures" attribute (can not be set in any case, because
0336:                // sometimes (resultType="hits") the collection contains no features at all -- but only the
0337:                // attribute "numberOfFeatures"
0338:                if (fc.size() > 0) {
0339:                    int hackedFeatureCount = fc.size()
0340:                            + additionalRootLevelFeatures.size();
0341:                    fc
0342:                            .setAttribute("numberOfFeatures", ""
0343:                                    + hackedFeatureCount);
0344:                }
0345:
0346:                Map<String, String> attributes = fc.getAttributes();
0347:                for (Iterator<String> iterator = attributes.keySet().iterator(); iterator
0348:                        .hasNext();) {
0349:                    String name = iterator.next();
0350:                    String value = attributes.get(name);
0351:                    pw.print(' ');
0352:                    pw.print(name);
0353:                    pw.print("='");
0354:                    pw.print(value);
0355:                    pw.print("'");
0356:                }
0357:
0358:                // determine and add namespace bindings
0359:                Map<String, URI> nsBindings = determineUsedNSBindings(fc);
0360:                if (LOG.getLevel() == ILogger.LOG_DEBUG) {
0361:                    LOG.logDebug(nsBindings.toString());
0362:                }
0363:                nsBindings.put("gml", CommonNamespaces.GMLNS);
0364:                nsBindings.put("xlink", CommonNamespaces.XLNNS);
0365:                if (this .schemaURL != null) {
0366:                    nsBindings.put("xsi", CommonNamespaces.XSINS);
0367:                }
0368:                appendNSBindings(nsBindings, pw);
0369:
0370:                // add schema reference (if available)
0371:                if (this .schemaURL != null && fc.size() > 0) {
0372:                    pw.print(" xsi:schemaLocation=\""
0373:                            + fc.getFeature(0).getName().getNamespace() + " ");
0374:                    pw.print(this .schemaURL + " ");
0375:                    pw.print(WFS_SCHEMA_BINDING + "\"");
0376:                }
0377:                pw.print('>');
0378:
0379:                Envelope env = null;
0380:                try {
0381:                    env = fc.getBoundedBy();
0382:                } catch (GeometryException e) {
0383:                    // omit gml:boundedBy-element if featureCollection contains features
0384:                    // with different SRS (and their envelopes cannot be merged)
0385:                }
0386:                if (env != null) {
0387:                    pw.print("<gml:boundedBy><gml:Envelope");
0388:                    if (env.getCoordinateSystem() != null) {
0389:                        pw.print(" srsName='"
0390:                                + env.getCoordinateSystem().getPrefixedName()
0391:                                + "'");
0392:                    }
0393:                    pw.print("><gml:pos srsDimension='2'>");
0394:                    pw.print(env.getMin().getX());
0395:                    pw.print(' ');
0396:                    pw.print(env.getMin().getY());
0397:                    pw.print("</gml:pos><gml:pos srsDimension='2'>");
0398:                    pw.print(env.getMax().getX());
0399:                    pw.print(' ');
0400:                    pw.print(env.getMax().getY());
0401:                    pw.print("</gml:pos></gml:Envelope></gml:boundedBy>");
0402:                }
0403:
0404:                // export all contained features
0405:                for (int i = 0; i < fc.size(); i++) {
0406:                    Feature feature = fc.getFeature(i);
0407:                    String fid = feature.getId();
0408:                    if (fid != null && !fid.equals("")
0409:                            && this .exportedFeatures.contains(fid)
0410:                            && !this .suppressXLinkOutput) {
0411:                        pw.print("<gml:featureMember xlink:href=\"#");
0412:                        pw.print(fid);
0413:                        pw.print("\"/>");
0414:                    } else {
0415:                        pw.print("<gml:featureMember>");
0416:                        export(feature, pw);
0417:                        pw.print("</gml:featureMember>");
0418:                    }
0419:                }
0420:
0421:                // export all additional root level features
0422:                for (Feature feature : additionalRootLevelFeatures) {
0423:                    String fid = feature.getId();
0424:                    if (fid != null && !fid.equals("")
0425:                            && this .exportedFeatures.contains(fid)) {
0426:                        pw.print("<gml:featureMember xlink:href=\"#");
0427:                        pw.print(fid);
0428:                        pw.print("\"/>");
0429:                    } else {
0430:                        pw.print("<gml:featureMember>");
0431:                        export(feature, pw);
0432:                        pw.print("</gml:featureMember>");
0433:                    }
0434:                }
0435:
0436:                // close the feature collection element
0437:                pw.print("</");
0438:                pw.print(fc.getName().getPrefixedName());
0439:                pw.print('>');
0440:            }
0441:
0442:            /**
0443:             * Determines features that don't originally belong to the root level of the given <code>FeatureCollection</code>,
0444:             * but which need to be put there in the output, because they are subfeatures inside of properties that have the
0445:             * content type "gml:ReferenceType".
0446:             * 
0447:             * @param fc
0448:             * @return features to be added to the root level
0449:             */
0450:            private Set<Feature> determineAdditionalRootLevelFeatures(
0451:                    FeatureCollection fc) {
0452:
0453:                Set<Feature> rootFeatures = new HashSet<Feature>(fc.size());
0454:                for (int i = 0; i < fc.size(); i++) {
0455:                    rootFeatures.add(fc.getFeature(i));
0456:                }
0457:                Set<Feature> additionalRootFeatures = new HashSet<Feature>();
0458:                Set<Feature> checkedFeatures = new HashSet<Feature>();
0459:                for (int i = 0; i < fc.size(); i++) {
0460:                    Feature feature = fc.getFeature(i);
0461:                    determineAdditionalRootLevelFeatures(feature,
0462:                            additionalRootFeatures, rootFeatures,
0463:                            checkedFeatures);
0464:                }
0465:                return additionalRootFeatures;
0466:            }
0467:
0468:            /**
0469:             * Determines features that don't originally belong to the root level of the given <code>FeatureCollection</code>,
0470:             * but which need to be put there in the output, because they are subfeatures inside of properties that have the
0471:             * content type "gml:ReferenceType".
0472:             * 
0473:             * @param fc
0474:             * @param additionalFeatures
0475:             *            to be added to the root level
0476:             * @param rootFeatures
0477:             *            to be added to the root level
0478:             * @param checkedFeatures
0479:             *            features that have already been checked
0480:             */
0481:            private void determineAdditionalRootLevelFeatures(Feature feature,
0482:                    Set<Feature> additionalFeatures, Set<Feature> rootFeatures,
0483:                    Set<Feature> checkedFeatures) {
0484:                for (FeatureProperty property : feature.getProperties()) {
0485:                    Object value = property.getValue();
0486:                    if (value instanceof  Feature) {
0487:                        Feature subFeature = (Feature) value;
0488:                        if (!checkedFeatures.contains(subFeature)) {
0489:                            if (feature.getFeatureType() != null
0490:                                    && feature.getFeatureType() instanceof  MappedFeatureType) {
0491:                                MappedFeatureType ft = (MappedFeatureType) feature
0492:                                        .getFeatureType();
0493:                                MappedFeaturePropertyType pt = (MappedFeaturePropertyType) ft
0494:                                        .getProperty(property.getName());
0495:                                assert pt != null;
0496:                                if (pt.isReferenceType()
0497:                                        && !rootFeatures.contains(subFeature)) {
0498:                                    additionalFeatures.add((Feature) value);
0499:                                }
0500:                            }
0501:                            checkedFeatures.add(subFeature);
0502:                            determineAdditionalRootLevelFeatures(subFeature,
0503:                                    additionalFeatures, rootFeatures,
0504:                                    checkedFeatures);
0505:                        }
0506:                    }
0507:                }
0508:            }
0509:
0510:            /**
0511:             * Exports a {@link FeatureTupleCollection} instance to the passed {@link OutputStream} formatted as GML.
0512:             * 
0513:             * @param fc
0514:             *            feature tuple collection to print/export
0515:             * @param pw
0516:             *            target of the printing/export
0517:             * @throws FeatureException
0518:             */
0519:            private void exportTupleCollection(FeatureTupleCollection fc,
0520:                    PrintWriter pw) throws FeatureException {
0521:
0522:                if (fc.getId() != null && !"".equals(fc.getId())) {
0523:                    this .exportedFeatures.add(fc.getId());
0524:                }
0525:
0526:                // open the feature collection element
0527:                pw.print("<");
0528:                pw.print(fc.getName().getPrefixedName());
0529:
0530:                Map<String, String> attributes = fc.getAttributes();
0531:                for (Iterator<String> iterator = attributes.keySet().iterator(); iterator
0532:                        .hasNext();) {
0533:                    String name = iterator.next();
0534:                    String value = attributes.get(name);
0535:                    pw.print(' ');
0536:                    pw.print(name);
0537:                    pw.print("='");
0538:                    pw.print(value);
0539:                    pw.print("'");
0540:                }
0541:
0542:                // determine and add namespace bindings
0543:                Map<String, URI> nsBindings = determineUsedNSBindings(fc);
0544:                nsBindings.put("gml", CommonNamespaces.GMLNS);
0545:                nsBindings.put("xlink", CommonNamespaces.XLNNS);
0546:                if (this .schemaURL != null) {
0547:                    nsBindings.put("xsi", CommonNamespaces.XSINS);
0548:                }
0549:                appendNSBindings(nsBindings, pw);
0550:
0551:                // add schema reference (if available)
0552:                if (this .schemaURL != null && fc.size() > 0) {
0553:                    pw.print(" xsi:schemaLocation=\""
0554:                            + fc.getTuple(0)[0].getName().getNamespace() + " ");
0555:                    pw.print(this .schemaURL + " ");
0556:                    pw.print(WFS_SCHEMA_BINDING + "\"");
0557:                }
0558:                pw.print('>');
0559:
0560:                Envelope env = null;
0561:                try {
0562:                    env = fc.getBoundedBy();
0563:                } catch (GeometryException e) {
0564:                    // omit gml:boundedBy-element if featureCollection contains features
0565:                    // with different SRS (and their envelopes cannot be merged)
0566:                }
0567:                if (env != null) {
0568:                    pw.print("<gml:boundedBy><gml:Envelope");
0569:                    if (env.getCoordinateSystem() != null) {
0570:                        pw.print(" srsName='"
0571:                                + env.getCoordinateSystem().getPrefixedName()
0572:                                + "'");
0573:                    }
0574:                    pw.print("><gml:pos srsDimension='2'>");
0575:                    pw.print(env.getMin().getX());
0576:                    pw.print(' ');
0577:                    pw.print(env.getMin().getY());
0578:                    pw.print("</gml:pos><gml:pos srsDimension='2'>");
0579:                    pw.print(env.getMax().getX());
0580:                    pw.print(' ');
0581:                    pw.print(env.getMax().getY());
0582:                    pw.print("</gml:pos></gml:Envelope></gml:boundedBy>");
0583:                }
0584:
0585:                // export all contained feature tuples
0586:                for (int i = 0; i < fc.numTuples(); i++) {
0587:                    Feature[] features = fc.getTuple(i);
0588:                    pw.print("<gml:featureTuple>");
0589:                    for (Feature feature : features) {
0590:                        export(feature, pw);
0591:                    }
0592:                    pw.print("</gml:featureTuple>");
0593:                }
0594:
0595:                // close the feature collection element
0596:                pw.print("</");
0597:                pw.print(fc.getName().getPrefixedName());
0598:                pw.print('>');
0599:            }
0600:
0601:            /**
0602:             * Determines the namespace bindings that are used in the feature collection.
0603:             * <p>
0604:             * NOTE: Currently only the bindings for the feature collection's root element and the contained features are
0605:             * considered. If a subfeature uses another bindings, this binding will be missing in the XML.
0606:             * 
0607:             * @param fc
0608:             *            feature collection
0609:             * @return the namespace bindings.
0610:             */
0611:            private Map<String, URI> determineUsedNSBindings(
0612:                    FeatureCollection fc) {
0613:
0614:                Map<String, URI> nsBindings = new HashMap<String, URI>();
0615:
0616:                // process feature collection element
0617:                QualifiedName name = fc.getName();
0618:                nsBindings.put(name.getPrefix(), name.getNamespace());
0619:
0620:                if (fc instanceof  FeatureTupleCollection) {
0621:                    // process contained feature tuples
0622:                    FeatureTupleCollection ftc = (FeatureTupleCollection) fc;
0623:                    for (int i = 0; i < ftc.numTuples(); i++) {
0624:                        Feature[] features = ftc.getTuple(i);
0625:                        for (Feature feature : features) {
0626:                            name = feature.getName();
0627:                            nsBindings.put(name.getPrefix(), name
0628:                                    .getNamespace());
0629:                        }
0630:                    }
0631:                } else {
0632:                    // process contained features
0633:                    // for ( int i = 0; i < fc.size(); i++ ) {
0634:                    // name = fc.getFeature( i ).getName();
0635:                    // nsBindings.put( name.getPrefix(), name.getNamespace() );
0636:                    // }
0637:                    for (int i = 0; i < fc.size(); i++) {
0638:                        Feature feature = fc.getFeature(i);
0639:                        if (feature != null) {
0640:                            nsBindings = determineUsedNSBindings(feature,
0641:                                    nsBindings);
0642:                        }
0643:                    }
0644:                }
0645:
0646:                return nsBindings;
0647:            }
0648:
0649:            /**
0650:             * Determines the namespace bindings that are used in the feature and it's properties
0651:             * 
0652:             * @param feature
0653:             *            feature
0654:             * @param nsBindings
0655:             *            to add to.
0656:             * @return the namespace bindings
0657:             */
0658:            private Map<String, URI> determineUsedNSBindings(Feature feature,
0659:                    Map<String, URI> nsBindings) {
0660:                if (nsBindings == null) {
0661:                    nsBindings = new HashMap<String, URI>();
0662:                }
0663:                if (feature != null) {
0664:                    // process feature element
0665:                    QualifiedName qName = feature.getName();
0666:                    if (qName != null) {
0667:                        String prefix = qName.getPrefix();
0668:                        URI ns = qName.getNamespace();
0669:                        if (ns != null && !"".equals(ns.toASCIIString().trim())) {
0670:                            LOG.logDebug("Adding qName: " + qName);
0671:                            nsBindings.put(prefix, ns);
0672:                        }
0673:                    }
0674:
0675:                    // now check for properties which use a namespace
0676:                    FeatureProperty[] featureProperties = feature
0677:                            .getProperties();
0678:                    if (featureProperties != null) {
0679:                        for (FeatureProperty fp : featureProperties) {
0680:                            if (fp != null) {
0681:                                QualifiedName fpName = fp.getName();
0682:                                if (fpName != null) {
0683:                                    String prefix = fpName.getPrefix();
0684:                                    if (prefix != null
0685:                                            && !"".equals(prefix.trim())) {
0686:                                        if (nsBindings.get(prefix) == null) {
0687:                                            URI ns = fpName.getNamespace();
0688:                                            if (ns != null
0689:                                                    && !"".equals(ns
0690:                                                            .toASCIIString()
0691:                                                            .trim())) {
0692:                                                LOG.logDebug("Adding qname: "
0693:                                                        + fpName);
0694:                                                nsBindings.put(prefix, ns);
0695:                                            }
0696:                                        }
0697:                                    }
0698:                                }
0699:                                // Object value = fp.getValue();
0700:                                // if ( value instanceof Feature ) {
0701:                                // determineUsedNSBindings( (Feature) value, nsBindings );
0702:                                // }
0703:                            }
0704:                        }
0705:                    }
0706:                }
0707:
0708:                return nsBindings;
0709:            }
0710:
0711:            /**
0712:             * Determines the namespace bindings that are used in the feature.
0713:             * <p>
0714:             * NOTE: Currently only the bindings for the feature's root element and the contained features are considered. If a
0715:             * subfeature uses another bindings, this binding will be missing in the XML.
0716:             * 
0717:             * @param fc
0718:             *            feature
0719:             * @return the namespace bindings
0720:             */
0721:            private Map<String, URI> determineUsedNSBindings(Feature feature) {
0722:
0723:                // reset the counter.
0724:                Map<String, URI> nsBindings = new HashMap<String, URI>();
0725:
0726:                return determineUsedNSBindings(feature, nsBindings);
0727:                // // process feature element
0728:                // QualifiedName name = feature.getName();
0729:                // nsBindings.put( name.getPrefix(), name.getNamespace() );
0730:
0731:            }
0732:
0733:            /**
0734:             * Appends the given namespace bindings to the PrintWriter.
0735:             * 
0736:             * @param bindings
0737:             *            namespace bindings to append
0738:             * @param pw
0739:             *            PrintWriter to write to
0740:             */
0741:            private void appendNSBindings(Map<String, URI> bindings,
0742:                    PrintWriter pw) {
0743:
0744:                Iterator<String> prefixIter = bindings.keySet().iterator();
0745:                while (prefixIter.hasNext()) {
0746:                    String prefix = prefixIter.next();
0747:                    URI nsURI = bindings.get(prefix);
0748:                    if (prefix == null) {
0749:                        pw.print(" xmlns=\"");
0750:                        pw.print(nsURI);
0751:                        pw.print('\"');
0752:                    } else {
0753:                        pw.print(" xmlns:");
0754:                        pw.print(prefix);
0755:                        pw.print("=\"");
0756:                        pw.print(nsURI);
0757:                        pw.print('\"');
0758:                    }
0759:                }
0760:                // if more then one default namespaces were defined, each feature must (re)-determine the default ns.
0761:                this .nsBindingsExported = true;// ( defaultNamespaceCounter == 0 );
0762:            }
0763:
0764:            /**
0765:             * Exports an instance of a <code>Feature</code> to the passed <code>OutputStream</code> formatted as GML. Uses
0766:             * the deegree system character set for the XML header encoding information.
0767:             * 
0768:             * @param feature
0769:             *            feature to export
0770:             * @param os
0771:             *            output stream to write to
0772:             * 
0773:             * @throws IOException
0774:             * @throws FeatureException
0775:             */
0776:            public void export(Feature feature, OutputStream os)
0777:                    throws IOException, FeatureException {
0778:                export(feature, os, CharsetUtils.getSystemCharset());
0779:            }
0780:
0781:            /**
0782:             * Exports a <code>Feature</code> instance to the passed <code>OutputStream</code> formatted as GML.
0783:             * 
0784:             * @param feature
0785:             *            feature to export
0786:             * @param os
0787:             *            output stream to write to
0788:             * @param charsetName
0789:             *            name of the used charset/encoding (for the XML header)
0790:             * @throws IOException
0791:             * @throws FeatureException
0792:             */
0793:            public void export(Feature feature, OutputStream os,
0794:                    String charsetName) throws IOException, FeatureException {
0795:
0796:                PrintWriter pw = new PrintWriter(new OutputStreamWriter(os,
0797:                        charsetName));
0798:                pw.println("<?xml version=\"1.0\" encoding=\"" + charsetName
0799:                        + "\"?>");
0800:                export(feature, pw);
0801:                pw.close();
0802:            }
0803:
0804:            /**
0805:             * Exports a <code>Feature</code> instance to the passed <code>PrintWriter</code> as GML.
0806:             * 
0807:             * @param feature
0808:             *            feature to export
0809:             * @param pw
0810:             *            PrintWriter to write to
0811:             * @throws FeatureException
0812:             */
0813:            private void export(Feature feature, PrintWriter pw)
0814:                    throws FeatureException {
0815:
0816:                QualifiedName ftName = feature.getName();
0817:                String fid = feature.getId();
0818:
0819:                if (this .suppressXLinkOutput && fid != null && !"".equals(fid)) {
0820:                    if (this .localFeatures.contains(fid)) {
0821:                        String msg = Messages
0822:                                .format("ERROR_CYLIC_FEATURE", fid);
0823:                        throw new FeatureException(msg);
0824:                    }
0825:                    this .localFeatures.add(fid);
0826:                }
0827:
0828:                // open feature element (add gml:id attribute if feature has an id)
0829:                pw.print('<');
0830:                pw.print(ftName.getPrefixedName());
0831:                if (fid != null) {
0832:                    this .exportedFeatures.add(fid);
0833:                    pw.print(" gml:id=\"");
0834:                    pw.print(fid);
0835:                    pw.print('\"');
0836:                }
0837:
0838:                // determine and add namespace bindings
0839:
0840:                if (!this .nsBindingsExported) {
0841:
0842:                    Map<String, URI> nsBindings = determineUsedNSBindings(feature);
0843:                    nsBindings.put("gml", CommonNamespaces.GMLNS);
0844:                    nsBindings.put("xlink", CommonNamespaces.XLNNS);
0845:                    if (this .schemaURL != null) {
0846:                        nsBindings.put("xsi", CommonNamespaces.XSINS);
0847:                    }
0848:                    appendNSBindings(nsBindings, pw);
0849:                }
0850:
0851:                pw.print('>');
0852:
0853:                try {
0854:                    Envelope env = null;
0855:                    if ((env = feature.getBoundedBy()) != null) {
0856:                        pw.print("<gml:boundedBy><gml:Envelope");
0857:                        if (env.getCoordinateSystem() != null) {
0858:                            pw.print(" srsName='"
0859:                                    + env.getCoordinateSystem()
0860:                                            .getPrefixedName() + "'");
0861:                        }
0862:                        pw.print("><gml:pos srsDimension='2'>");
0863:                        pw.print(env.getMin().getX());
0864:                        pw.print(' ');
0865:                        pw.print(env.getMin().getY());
0866:                        pw.print("</gml:pos><gml:pos srsDimension=\"2\">");
0867:                        pw.print(env.getMax().getX());
0868:                        pw.print(' ');
0869:                        pw.print(env.getMax().getY());
0870:                        pw.print("</gml:pos></gml:Envelope></gml:boundedBy>");
0871:                    }
0872:                } catch (GeometryException e) {
0873:                    LOG.logError(e.getMessage(), e);
0874:                }
0875:
0876:                // export all properties of the feature
0877:                FeatureProperty[] properties = feature.getProperties();
0878:                for (int i = 0; i < properties.length; i++) {
0879:                    if (properties[i] != null
0880:                            && properties[i].getValue() != null) {
0881:                        exportProperty(feature, properties[i], pw);
0882:                    }
0883:                }
0884:
0885:                // close feature element
0886:                pw.print("</");
0887:                pw.print(ftName.getPrefixedName());
0888:                pw.println('>');
0889:
0890:                if (this .suppressXLinkOutput || fid != null) {
0891:                    this .localFeatures.remove(fid);
0892:                }
0893:            }
0894:
0895:            /**
0896:             * Exports a <code>FeatureProperty</code> instance to the passed <code>PrintWriter</code> as GML.
0897:             * 
0898:             * @param feature
0899:             *            feature that the property belongs to
0900:             * @param property
0901:             *            property to export
0902:             * @param pw
0903:             *            PrintWriter to write to
0904:             * @throws FeatureException
0905:             */
0906:            private void exportProperty(Feature feature,
0907:                    FeatureProperty property, PrintWriter pw)
0908:                    throws FeatureException {
0909:
0910:                QualifiedName propertyName = property.getName();
0911:                Object value = property.getValue();
0912:
0913:                if (value instanceof  Feature) {
0914:                    Feature subfeature = (Feature) value;
0915:
0916:                    boolean isReferenceType = false;
0917:                    if (feature.getFeatureType() != null
0918:                            && feature.getFeatureType() instanceof  MappedFeatureType) {
0919:                        MappedFeatureType ft = (MappedFeatureType) feature
0920:                                .getFeatureType();
0921:                        MappedFeaturePropertyType pt = (MappedFeaturePropertyType) ft
0922:                                .getProperty(property.getName());
0923:                        assert pt != null;
0924:                        isReferenceType = pt.isReferenceType();
0925:                    }
0926:
0927:                    if (isReferenceType
0928:                            || (exportedFeatures.contains(subfeature.getId()) && !this .suppressXLinkOutput)) {
0929:                        pw.print('<');
0930:                        pw.print(propertyName.getPrefixedName());
0931:                        pw.print(" xlink:href=\"#");
0932:                        pw.print(subfeature.getId());
0933:                        pw.print("\"/>");
0934:                    } else {
0935:                        pw.print('<');
0936:                        pw.print(propertyName.getPrefixedName());
0937:                        pw.print('>');
0938:                        exportPropertyValue(subfeature, pw);
0939:                        pw.print("</");
0940:                        pw.print(propertyName.getPrefixedName());
0941:                        pw.print('>');
0942:                    }
0943:                } else {
0944:                    pw.print('<');
0945:                    pw.print(propertyName.getPrefixedName());
0946:                    pw.print('>');
0947:                    if (value != null) {
0948:                        FeatureType ft = feature.getFeatureType();
0949:                        PropertyType pt = ft.getProperty(property.getName());
0950:                        if (pt.getType() == Types.ANYTYPE) {
0951:                            pw.print(value);
0952:                        } else {
0953:                            exportPropertyValue(value, pw);
0954:                        }
0955:                    }
0956:                    pw.print("</");
0957:                    pw.print(propertyName.getPrefixedName());
0958:                    pw.print('>');
0959:                }
0960:            }
0961:
0962:            /**
0963:             * Exports the value of a property to the passed <code>PrintWriter</code> as GML.
0964:             * 
0965:             * TODO make available and use property type information to determine correct output format (e.g. xs:date, xs:time,
0966:             * xs:dateTime are all represented using Date objects and cannot be differentiated at the moment)
0967:             * 
0968:             * @param value
0969:             *            property value to export
0970:             * @param pw
0971:             *            PrintWriter to write to
0972:             * @throws FeatureException
0973:             */
0974:            private void exportPropertyValue(Object value, PrintWriter pw)
0975:                    throws FeatureException {
0976:                if (value instanceof  Feature) {
0977:                    export((Feature) value, pw);
0978:                } else if (value instanceof  Feature[]) {
0979:                    Feature[] features = (Feature[]) value;
0980:                    for (int i = 0; i < features.length; i++) {
0981:                        export(features[i], pw);
0982:                    }
0983:                } else if (value instanceof  Envelope) {
0984:                    exportEnvelope((Envelope) value, pw);
0985:                } else if (value instanceof  FeatureCollection) {
0986:                    export((FeatureCollection) value, pw);
0987:                } else if (value instanceof  Geometry) {
0988:                    exportGeometry((Geometry) value, pw);
0989:                } else if (value instanceof  Date) {
0990:
0991:                    // TODO: use (currently unavailable) property type information to determine correct
0992:                    // output format (e.g. xs:date, xs:time, xs:dateTime are all represented using Date
0993:                    // objects and cannot be differentiated at the moment)
0994:
0995:                    // pw.print( ( (Date) value ).toString() );
0996:                    pw.print(TimeTools.getISOFormattedTime((Date) value));
0997:                } else if (value instanceof  Calendar) {
0998:                    pw.print(TimeTools.getISOFormattedTime((Calendar) value));
0999:                } else if (value instanceof  Timestamp) {
1000:                    pw.print(TimeTools.getISOFormattedTime((Timestamp) value));
1001:                } else if (value instanceof  java.sql.Date) {
1002:                    pw.print(TimeTools
1003:                            .getISOFormattedTime((java.sql.Date) value));
1004:                } else if (value instanceof  Integer || value instanceof  Long
1005:                        || value instanceof  Float || value instanceof  Double
1006:                        || value instanceof  BigDecimal) {
1007:                    pw.print(value.toString());
1008:                } else if (value instanceof  String) {
1009:                    StringBuffer sb = DOMPrinter.validateCDATA((String) value);
1010:                    pw.print(sb);
1011:                } else if (value instanceof  Boolean) {
1012:                    pw.print(value);
1013:                } else {
1014:                    LOG.logInfo("Unhandled property class '" + value.getClass()
1015:                            + "' in GMLFeatureAdapter.");
1016:                    StringBuffer sb = DOMPrinter
1017:                            .validateCDATA(value.toString());
1018:                    pw.print(sb);
1019:                }
1020:            }
1021:
1022:            /**
1023:             * prints the passed geometry to the also passed PrintWriter formatted as GML
1024:             * 
1025:             * @param geo
1026:             *            geometry to print/extport
1027:             * @param pw
1028:             *            target of the printing/export
1029:             * @throws FeatureException
1030:             */
1031:            private void exportGeometry(Geometry geo, PrintWriter pw)
1032:                    throws FeatureException {
1033:                try {
1034:                    pw.print(GMLGeometryAdapter.export(geo));
1035:                } catch (Exception e) {
1036:                    LOG.logError("", e);
1037:                    throw new FeatureException(
1038:                            "Could not export geometry to GML: "
1039:                                    + e.getMessage(), e);
1040:                }
1041:            }
1042:
1043:            /**
1044:             * prints the passed geometry to the also passed PrintWriter formatted as GML
1045:             * 
1046:             * @param geo
1047:             *            geometry to print/extport
1048:             * @param pw
1049:             *            target of the printing/export
1050:             * @throws FeatureException
1051:             */
1052:            private void exportEnvelope(Envelope geo, PrintWriter pw)
1053:                    throws FeatureException {
1054:                try {
1055:                    pw.print(GMLGeometryAdapter.exportAsBox(geo));
1056:                } catch (Exception e) {
1057:                    throw new FeatureException(
1058:                            "Could not export envelope to GML: "
1059:                                    + e.getMessage(), e);
1060:                }
1061:            }
1062:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.