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 }