001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/crs/configuration/gml/GMLFileResource.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036
037 package org.deegree.crs.configuration.gml;
038
039 import java.io.IOException;
040 import java.util.ArrayList;
041 import java.util.Arrays;
042 import java.util.HashMap;
043 import java.util.LinkedList;
044 import java.util.List;
045 import java.util.Map;
046 import java.util.Properties;
047
048 import org.deegree.crs.configuration.resources.XMLFileResource;
049 import org.deegree.crs.coordinatesystems.CompoundCRS;
050 import org.deegree.crs.coordinatesystems.CoordinateSystem;
051 import org.deegree.crs.coordinatesystems.GeographicCRS;
052 import org.deegree.crs.coordinatesystems.ProjectedCRS;
053 import org.deegree.crs.exceptions.CRSConfigurationException;
054 import org.deegree.crs.transformations.Transformation;
055 import org.deegree.crs.transformations.coordinate.CRSTransformation;
056 import org.deegree.crs.transformations.coordinate.ConcatenatedTransform;
057 import org.deegree.crs.transformations.helmert.Helmert;
058 import org.deegree.framework.log.ILogger;
059 import org.deegree.framework.log.LoggerFactory;
060 import org.deegree.framework.xml.XMLParsingException;
061 import org.deegree.framework.xml.XMLTools;
062 import org.deegree.i18n.Messages;
063 import org.deegree.ogcbase.CommonNamespaces;
064 import org.w3c.dom.Element;
065
066 /**
067 * The <code>GMLFileResource</code> provides easy access to a gml3.2. dictionary file, which can be used together with
068 * the {@link GMLCRSProvider}.
069 *
070 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
071 *
072 * @author last edited by: $Author: lbuesching $
073 *
074 * @version $Revision: 27765 $, $Date: 2010-11-04 07:50:32 +0100 (Do, 04 Nov 2010) $
075 *
076 */
077 public class GMLFileResource extends XMLFileResource implements GMLResource {
078
079 /**
080 *
081 */
082 private static final long serialVersionUID = -4389365894942107300L;
083
084 private static ILogger LOG = LoggerFactory.getLogger( GMLFileResource.class );
085
086 private static final String PRE = CommonNamespaces.GML3_2_PREFIX + ":";
087
088 private static final String ID_XPATH = "//" + PRE + "dictionaryEntry/*[" + PRE + "identifier='";
089
090 private static final String OR_CONTAINS_NAMES = " or " + PRE + "name='";
091
092 private static final String TRANSFORM_XPATH = "/" + PRE + "Dictionary/" + PRE + "dictionaryEntry/" + PRE
093 + "Transformation";
094
095 private List<Element> transformations;
096
097 private Map<CoordinateSystem, Helmert> cachedWGS84Transformations;
098
099 /**
100 * @param provider
101 * @param properties
102 */
103 public GMLFileResource( GMLCRSProvider provider, Properties properties ) {
104 super( provider, properties, "Dictionary", CommonNamespaces.GML3_2_NS.toASCIIString() );
105 try {
106 transformations = XMLTools.getElements( getRootElement(), TRANSFORM_XPATH, nsContext );
107
108 } catch ( XMLParsingException e ) {
109 LOG.logError( e.getLocalizedMessage(), e );
110 }
111 cachedWGS84Transformations = new HashMap<CoordinateSystem, Helmert>();
112 }
113
114 public Helmert getWGS84Transformation( GeographicCRS sourceCRS ) {
115 if ( sourceCRS == null ) {
116 return null;
117 }
118 if ( LOG.isDebug() ) {
119 LOG.logDebug( "Searching for wgs84 transformation for given sourceCRS: "
120 + Arrays.toString( sourceCRS.getIdentifiers() ) );
121 }
122 Helmert result = cachedWGS84Transformations.get( sourceCRS );
123 if ( result == null ) {
124 Transformation parsedTransformation = getTransformation( sourceCRS, null );
125 if ( parsedTransformation instanceof Helmert ) {
126 LOG.logDebug( "Found an helmert transformation for sourceCRS: "
127 + Arrays.toString( sourceCRS.getIdentifiers() ) );
128 result = (Helmert) parsedTransformation;
129 } else {
130 if ( parsedTransformation instanceof CRSTransformation ) {
131 CoordinateSystem target = ( (CRSTransformation) parsedTransformation ).getTargetCRS();
132 GeographicCRS t = null;
133 if ( LOG.isDebug() ) {
134 LOG.logDebug( "Found crstransformation for sourceCRS: "
135 + Arrays.toString( sourceCRS.getIdentifiers() ) + " and targetCRS: "
136 + Arrays.toString( target.getIdentifiers() )
137 + " will now use the targetCRS to find a Helmert transformation." );
138 }
139 if ( target.getType() == CoordinateSystem.COMPOUND_CRS ) {
140 if ( ( (CompoundCRS) target ).getUnderlyingCRS().getType() == CoordinateSystem.PROJECTED_CRS ) {
141 t = ( (ProjectedCRS) ( (CompoundCRS) target ).getUnderlyingCRS() ).getGeographicCRS();
142 } else if ( ( (CompoundCRS) target ).getUnderlyingCRS().getType() == CoordinateSystem.GEOGRAPHIC_CRS ) {
143 t = (GeographicCRS) target;
144 } else {
145 LOG.logWarning( "Wgs84 Transformation lookup is currently only supported for GeographicCRS-chains." );
146 }
147 } else if ( target.getType() == CoordinateSystem.PROJECTED_CRS ) {
148 t = ( (ProjectedCRS) target ).getGeographicCRS();
149 } else if ( target.getType() == CoordinateSystem.GEOGRAPHIC_CRS ) {
150 t = (GeographicCRS) target;
151 } else {
152 LOG.logWarning( "Wgs84 Transformation lookup is currently only supported for GeographicCRS-chains." );
153 }
154 if ( t != null ) {
155 if ( LOG.isDebug() ) {
156 LOG.logDebug( "Trying to resolve target to find a wgs84transformation for the 'targetCRS': "
157 + Arrays.toString( t.getIdentifiers() ) );
158 }
159 result = getWGS84Transformation( t );
160 }
161 } else {
162 LOG.logWarning( "The transformation is not an instance of CRSTransformation nor a Helmert, ignoring it." );
163 }
164 }
165 }
166
167 if ( result != null ) {
168 if ( LOG.isDebug() ) {
169 LOG.logDebug( "For the given crs: " + sourceCRS.getIdentifier()
170 + " following helmert transformation was found:\n" + result );
171
172 }
173
174 cachedWGS84Transformations.put( sourceCRS, result );
175 } else {
176 LOG.logInfo( "No helmert transformation found for the given crs: " + sourceCRS.getIdentifier() );
177 }
178 return result;
179 }
180
181 public Transformation getTransformation( CoordinateSystem sourceCRS, CoordinateSystem targetCRS ) {
182 if ( sourceCRS == null ) {
183 return null;
184 }
185 List<Element> toBeRemoved = new ArrayList<Element>( transformations.size() );
186 List<String> sourceIDs = Arrays.asList( sourceCRS.getIdentifiers() );
187 List<String> targetIDs = null;
188 if ( targetCRS != null ) {
189 targetIDs = Arrays.asList( targetCRS.getIdentifiers() );
190 } else {
191 targetIDs = new ArrayList<String>();
192 }
193 Transformation result = null;
194 for ( int i = 0; i < transformations.size() && result == null; ++i ) {
195 Element transElem = transformations.get( i );
196 if ( transElem != null ) {
197 try {
198 Element sourceCRSProp = XMLTools.getRequiredElement( transElem, PRE + "sourceCRS", nsContext );
199 String transformSourceID = null;
200 String transformTargetID = null;
201 if ( sourceCRSProp != null ) {
202 transformSourceID = sourceCRSProp.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(),
203 "href" );
204 if ( "".equals( transformSourceID ) ) {
205 transformSourceID = XMLTools.getRequiredNodeAsString( sourceCRSProp, "*[1]/" + PRE
206 + "identifier",
207 nsContext );
208 }
209 }
210 if ( targetCRS != null ) {
211 Element targetCRSProp = XMLTools.getRequiredElement( transElem, PRE + "targetCRS", nsContext );
212 if ( targetCRSProp != null ) {
213
214 transformTargetID = targetCRSProp.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(),
215 "href" );
216 if ( "".equals( transformTargetID ) ) {
217 transformTargetID = XMLTools.getRequiredNodeAsString( targetCRSProp, "*[1]/" + PRE
218 + "identifier",
219 nsContext );
220 }
221 }
222 }
223
224 if ( sourceIDs.contains( transformSourceID ) ) {
225 result = getProvider().parseTransformation( transElem );
226 if ( targetCRS == null ) {
227 // Trying to find a helmert transformation
228 LOG.logDebug( "Resolving a possible transformation." );
229 if ( result != null && !( result instanceof Helmert ) ) {
230 result = getTransformation( result.getTargetCRS(), null );
231 }
232 } else {
233 if ( !targetIDs.contains( transformTargetID ) ) {
234 LOG.logDebug( "Found a transformation with gml:id: "
235 + transElem.getAttributeNS( CommonNamespaces.GML3_2_NS.toASCIIString(),
236 "id" )
237 + ", but the target does not match the source crs, trying to build transformation chain." );
238 Transformation second = getTransformation( result.getTargetCRS(), targetCRS );
239 if ( second != null ) {
240 result = new ConcatenatedTransform( result, second );
241 } else {
242 LOG.logDebug( "The transformation with gml:id: "
243 + transElem.getAttributeNS(
244 CommonNamespaces.GML3_2_NS.toASCIIString(),
245 "id" )
246 + " is not the start of transformation chain, discarding it. " );
247 result = null;
248 }
249 }
250 }
251 }
252
253 } catch ( XMLParsingException e ) {
254 toBeRemoved.add( transElem );
255 LOG.logWarning( "No source CRS id could be found in this transformation(gml:id): "
256 + transElem.getAttributeNS( CommonNamespaces.GML3_2_NS.toASCIIString(), "id" )
257 + " this is not correct, removing transformation from cache." );
258 LOG.logWarning( e.getMessage() );
259 }
260 }
261 if ( toBeRemoved.size() > 0 ) {
262 transformations.removeAll( toBeRemoved );
263 }
264 }
265 return result;
266 }
267
268 public Element getURIAsType( String uri )
269 throws IOException {
270 Element result = null;
271 try {
272 result = XMLTools.getElement( getRootElement(), ID_XPATH + uri + "'" + OR_CONTAINS_NAMES + uri + "']",
273 nsContext );
274 } catch ( XMLParsingException e ) {
275 LOG.logError( e );
276 }
277 return result;
278 }
279
280 /*
281 * (non-Javadoc)
282 *
283 * @see org.deegree.crs.configuration.gml.GMLResource#getAvailableCRSIds()
284 */
285 public List<String> getAvailableCRSIds() {
286 List<Element> crsIDs = new LinkedList<Element>();
287 try {
288 crsIDs.addAll( XMLTools.getElements( getRootElement(), ID_XPATH, nsContext ) );
289 } catch ( XMLParsingException e ) {
290 throw new CRSConfigurationException(
291 Messages.getMessage( "CRS_CONFIG_GET_ALL_ELEMENT_IDS", e.getMessage() ),
292 e );
293 }
294
295 List<String> result = new ArrayList<String>();
296 for ( Element crs : crsIDs ) {
297 if ( crs != null ) {
298 result.add( XMLTools.getStringValue( crs ) );
299 }
300 }
301 return result;
302 }
303
304 /*
305 * (non-Javadoc)
306 *
307 * @see org.deegree.crs.configuration.gml.GMLResource#getAvailableCRSIds()
308 */
309 public List<String[]> getSortedAvailableCRSIds() {
310 List<Element> crsIDs = new LinkedList<Element>();
311 try {
312 crsIDs.addAll( XMLTools.getElements( getRootElement(), ID_XPATH, nsContext ) );
313 } catch ( XMLParsingException e ) {
314 throw new CRSConfigurationException(
315 Messages.getMessage( "CRS_CONFIG_GET_ALL_ELEMENT_IDS", e.getMessage() ),
316 e );
317 }
318
319 List<String[]> result = new ArrayList<String[]>();
320 for ( Element crs : crsIDs ) {
321 if ( crs != null ) {
322 result.add( new String[] { XMLTools.getStringValue( crs ) } );
323 }
324 }
325 return result;
326 }
327
328 public List<CoordinateSystem> getAvailableCRSs() {
329 throw new UnsupportedOperationException( "Retrieval of all crs is currently not supported." );
330 }
331
332 public List<Transformation> getTransformations() {
333 throw new UnsupportedOperationException( "Retrieval of all transformations is currently not supported." );
334 }
335 }