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    }