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 **************************************************************************************************/