001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/feature/GMLFeatureCollectionDocument.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2006 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstraße 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.model.feature; 044 045 import java.util.ArrayList; 046 import java.util.Collection; 047 import java.util.Iterator; 048 import java.util.List; 049 050 import org.deegree.framework.util.IDGenerator; 051 import org.deegree.framework.xml.ElementList; 052 import org.deegree.framework.xml.XMLParsingException; 053 import org.deegree.framework.xml.XMLTools; 054 import org.w3c.dom.Element; 055 import org.w3c.dom.Text; 056 057 /** 058 * Parser and wrapper class for GML feature collections. 059 * <p> 060 * Extends {@link GMLFeatureDocument}, as a feature collection is a feature in the GML type 061 * hierarchy. 062 * <p> 063 * 064 * TODO Remove hack for xlinked feature members (should be easy after fixing model package). 065 * 066 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a> 067 * @author last edited by: $Author: apoth $ 068 * 069 * @version $Revision: 6429 $, $Date: 2007-03-28 21:01:00 +0200 (Mi, 28 Mär 2007) $ 070 * 071 * @see GMLFeatureDocument 072 */ 073 public class GMLFeatureCollectionDocument extends GMLFeatureDocument { 074 075 private static final long serialVersionUID = -6923435144671685710L; 076 077 private Collection<String> xlinkedMembers = new ArrayList<String>(); 078 079 /** 080 * Creates a new instance of <code>GMLFeatureCollectionDocument</code>. 081 * <p> 082 * Simple types encountered during parsing are "guessed", i.e. the parser tries to convert the 083 * values to double, integer, calendar, etc. However, this may lead to unwanted results, e.g. a 084 * property value of "054604" is converted to "54604". 085 */ 086 public GMLFeatureCollectionDocument() { 087 super(); 088 } 089 090 /** 091 * Creates a new instance of <code>GMLFeatureCollectionDocument</code>. 092 * <p> 093 * 094 * @param guessSimpleTypes 095 * set to true, if simple types should be "guessed" during parsing 096 */ 097 public GMLFeatureCollectionDocument( boolean guessSimpleTypes ) { 098 super( guessSimpleTypes ); 099 } 100 101 /** 102 * Returns the object representation of the underlying feature collection document. 103 * 104 * @return object representation of the underlying feature collection document. 105 * @throws XMLParsingException 106 */ 107 public FeatureCollection parse() 108 throws XMLParsingException { 109 FeatureCollection fc = parse( this.getRootElement() ); 110 resolveXLinkReferences(); 111 addXLinkedMembers( fc ); 112 return fc; 113 } 114 115 /** 116 * Ugly hack that adds the "xlinked" feature members to the feature collection. 117 * 118 * TODO remove this 119 * 120 * @param fc 121 * @throws XMLParsingException 122 */ 123 private void addXLinkedMembers( FeatureCollection fc ) 124 throws XMLParsingException { 125 Iterator<String> iter = this.xlinkedMembers.iterator(); 126 while ( iter.hasNext() ) { 127 String fid = iter.next(); 128 Feature feature = this.featureMap.get( fid ); 129 if ( feature == null ) { 130 String msg = Messages.format( "ERROR_XLINK_NOT_RESOLVABLE", fid ); 131 throw new XMLParsingException( msg ); 132 } 133 fc.add( feature ); 134 } 135 } 136 137 /** 138 * Returns the object representation for the given feature collection element. 139 * 140 * @return object representation for the given feature collection element. 141 * @throws XMLParsingException 142 */ 143 private FeatureCollection parse( Element element ) 144 throws XMLParsingException { 145 146 String fcId = parseFeatureId( element ); 147 // generate id if necessary (use feature type name + a unique number as id) 148 if ( "".equals( fcId ) ) { 149 fcId = element.getLocalName(); 150 fcId += IDGenerator.getInstance().generateUniqueID(); 151 } 152 153 String srsName = XMLTools.getNodeAsString( element, "gml:boundedBy/*[1]/@srsName", 154 nsContext, null ); 155 156 ElementList el = XMLTools.getChildElements( element ); 157 List<Feature> list = new ArrayList<Feature>( el.getLength() ); 158 159 for ( int i = 0; i < el.getLength(); i++ ) { 160 Feature member = null; 161 Element propertyElement = el.item( i ); 162 String propertyName = propertyElement.getNodeName(); 163 164 if ( !propertyName.endsWith( "boundedBy" ) && !propertyName.endsWith( "name" ) 165 && !propertyName.endsWith( "description" ) ) { 166 // the first child of a feature member must always be a feature 167 Element featureElement = XMLTools.getChildElements( el.item( i ) ).item( 0 ); 168 if ( featureElement == null ) { 169 // check if feature content is xlinked 170 // TODO remove this ugly hack 171 Text xlinkHref = (Text) XMLTools.getNode( propertyElement, 172 "@xlink:href/text()", nsContext ); 173 if ( xlinkHref == null ) { 174 String msg = Messages.format( "ERROR_INVALID_FEATURE_PROPERTY", 175 propertyName ); 176 throw new XMLParsingException( msg ); 177 } 178 String href = xlinkHref.getData(); 179 if ( !href.startsWith( "#" ) ) { 180 String msg = Messages.format( "ERROR_EXTERNAL_XLINK_NOT_SUPPORTED", href ); 181 throw new XMLParsingException( msg ); 182 } 183 String fid = href.substring( 1 ); 184 this.xlinkedMembers.add( fid ); 185 } else { 186 try { 187 member = parseFeature( featureElement, srsName ); 188 list.add( member ); 189 } catch ( Exception e ) { 190 throw new XMLParsingException( 191 "Error creating feature instance from element '" 192 + featureElement.getLocalName() 193 + "': " 194 + e.getMessage() ); 195 } 196 } 197 } 198 } 199 200 Feature[] features = list.toArray( new Feature[list.size()] ); 201 FeatureCollection fc = FeatureFactory.createFeatureCollection( fcId, features ); 202 String nof = element.getAttribute( "numberOfFeatures" ); 203 if ( nof == null ) { 204 nof = "" + features.length; 205 } 206 fc.setAttribute( "numberOfFeatures", nof ); 207 return fc; 208 } 209 } 210 211 /*************************************************************************************************** 212 * <code> 213 Changes to this class. What the people have been up to: 214 $Log$ 215 Revision 1.14 2007/01/23 16:19:48 mschneider 216 Propagates the srsName attribute from the root envelope now. 217 218 Revision 1.13 2006/09/13 23:59:33 mschneider 219 Fixed exception chaining. 220 221 Revision 1.12 2006/08/31 15:00:26 mschneider 222 Added second constructor that allows to disable the guessing of simple types. Javadoc fixes. 223 224 Revision 1.11 2006/07/25 15:52:52 mschneider 225 gml:Id attribute is respected now (if present). 226 227 Revision 1.10 2006/06/04 17:21:52 poth 228 useage of deprecated methods replaced 229 230 Revision 1.9 2006/04/06 20:25:27 poth 231 *** empty log message *** 232 233 Revision 1.8 2006/04/04 20:39:42 poth 234 *** empty log message *** 235 236 Revision 1.7 2006/03/30 21:20:26 poth 237 *** empty log message *** 238 239 Revision 1.6 2006/03/09 12:55:40 mschneider 240 Improved javadoc. 241 242 Revision 1.5 2006/02/05 18:52:35 mschneider 243 Added hack to allow xlink featureMember properties. 244 245 Revision 1.4 2006/02/04 22:49:57 mschneider 246 Fixed imports. 247 248 Revision 1.3 2006/01/30 16:20:26 mschneider 249 Moved resolveXLinkReferences() here. 250 251 Revision 1.2 2006/01/20 18:13:47 mschneider 252 Moved parsing functionality from GMLFeatureAdapter here. 253 254 Revision 1.1 2006/01/19 16:18:14 mschneider 255 Initial version. 256 * </code> 257 **************************************************************************************************/