001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/feature/GMLFeatureCollectionDocument.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 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: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 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", nsContext, null ); 154 155 ElementList el = XMLTools.getChildElements( element ); 156 List<Feature> list = new ArrayList<Feature>( el.getLength() ); 157 158 for ( int i = 0; i < el.getLength(); i++ ) { 159 Feature member = null; 160 Element propertyElement = el.item( i ); 161 String propertyName = propertyElement.getNodeName(); 162 163 if ( !propertyName.endsWith( "boundedBy" ) && !propertyName.endsWith( "name" ) 164 && !propertyName.endsWith( "description" ) ) { 165 // the first child of a feature member must always be a feature 166 Element featureElement = XMLTools.getChildElements( el.item( i ) ).item( 0 ); 167 if ( featureElement == null ) { 168 // check if feature content is xlinked 169 // TODO remove this ugly hack 170 Text xlinkHref = (Text) XMLTools.getNode( propertyElement, "@xlink:href/text()", nsContext ); 171 if ( xlinkHref == null ) { 172 String msg = Messages.format( "ERROR_INVALID_FEATURE_PROPERTY", propertyName ); 173 throw new XMLParsingException( msg ); 174 } 175 String href = xlinkHref.getData(); 176 if ( !href.startsWith( "#" ) ) { 177 String msg = Messages.format( "ERROR_EXTERNAL_XLINK_NOT_SUPPORTED", href ); 178 throw new XMLParsingException( msg ); 179 } 180 String fid = href.substring( 1 ); 181 this.xlinkedMembers.add( fid ); 182 } else { 183 try { 184 member = parseFeature( featureElement, srsName ); 185 list.add( member ); 186 } catch ( Exception e ) { 187 throw new XMLParsingException( "Error creating feature instance from element '" 188 + featureElement.getLocalName() + "': " + e.getMessage(), e ); 189 } 190 } 191 } 192 } 193 194 Feature[] features = list.toArray( new Feature[list.size()] ); 195 FeatureCollection fc = FeatureFactory.createFeatureCollection( fcId, features ); 196 String nof = element.getAttribute( "numberOfFeatures" ); 197 if ( nof == null ) { 198 nof = "" + features.length; 199 } 200 fc.setAttribute( "numberOfFeatures", nof ); 201 return fc; 202 } 203 }