001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/crs/configuration/deegree/DeegreeCRSProvider.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.deegree;
038    
039    import java.io.ByteArrayOutputStream;
040    import java.io.PrintWriter;
041    import java.io.UnsupportedEncodingException;
042    import java.lang.reflect.Constructor;
043    import java.lang.reflect.InvocationTargetException;
044    import java.util.LinkedList;
045    import java.util.List;
046    import java.util.Properties;
047    
048    import org.deegree.crs.Identifiable;
049    import org.deegree.crs.configuration.AbstractCRSProvider;
050    import org.deegree.crs.coordinatesystems.CoordinateSystem;
051    import org.deegree.crs.exceptions.CRSConfigurationException;
052    import org.deegree.crs.projections.Projection;
053    import org.deegree.crs.transformations.Transformation;
054    import org.deegree.framework.log.ILogger;
055    import org.deegree.framework.log.LoggerFactory;
056    import org.deegree.framework.util.CharsetUtils;
057    import org.deegree.framework.xml.NamespaceContext;
058    import org.deegree.framework.xml.XMLParsingException;
059    import org.deegree.framework.xml.XMLTools;
060    import org.deegree.i18n.Messages;
061    import org.deegree.ogcbase.CommonNamespaces;
062    import org.w3c.dom.Element;
063    
064    /**
065     * The <code>DeegreeCRSProvider</code> reads the deegree crs-config (based on it's own xml-schema) and creates the
066     * CRS's (and their datums, conversion info's, ellipsoids and projections) if requested.
067     * <p>
068     * Attention, although urn's are case-sensitive, the deegreeCRSProvider is not. All incoming id's are toLowerCased!
069     * </p>
070     * <h2>Automatic loading of projection/transformation classes</h2>
071     * It is possible to create your own projection/transformation classes, which can be automatically loaded.
072     * <p>
073     * You can achieve this loading by supplying the <b><code>class</code></b> attribute to a
074     * <code>crs:projectedCRS/crs:projection</code> or <code>crs:coordinateSystem/crs:transformation</code> element in
075     * the 'deegree-crs-configuration.xml'. This attribute must contain the full class name (with package), e.g.
076     * &lt;crs:projection class='my.package.and.projection.Implementation'&gt;
077     * </p>
078     * Because the loading is done with reflections your classes must sustain following criteria:
079     * <h3>Projections</h3>
080     * <ol>
081     * <li>It must be a sub class of {@link org.deegree.crs.projections.Projection}</li>
082     * <li>A constructor with following signature must be supplied: <br/> <code>
083     * public MyProjection( <br/>
084     * &emsp;&emsp;&emsp;&emsp;{@link org.deegree.crs.coordinatesystems.GeographicCRS} underlyingCRS,<br/>
085     * &emsp;&emsp;&emsp;&emsp;double falseNorthing,<br/>
086     * &emsp;&emsp;&emsp;&emsp;double falseEasting,<br/>
087     * &emsp;&emsp;&emsp;&emsp;javax.vecmath.Point2d naturalOrigin,<br/>
088     * &emsp;&emsp;&emsp;&emsp;{@link org.deegree.crs.components.Unit} units,<br/>
089     * &emsp;&emsp;&emsp;&emsp;double scale,<br/>
090     * &emsp;&emsp;&emsp;&emsp;java.util.List&lt;org.w3c.dom.Element&gt; yourProjectionElements<br/>
091     * );<br/>
092     * </code>
093     * <p>
094     * The first six parameters are common to all projections (for an explanation of their meaning take a look at
095     * {@link Projection}). The last list, will contain all xml-dom elements you supplied in the deegree configuration
096     * (child elements of the crs:projection/crs:MyProjection), thus relieving you of the parsing of the
097     * deegree-crs-configuration.xml document.
098     * </p>
099     * </li>
100     * </ol>
101     * <h3>Transformations</h3>
102     * <ol>
103     * <li>It must be a sub class of {@link org.deegree.crs.transformations.polynomial.PolynomialTransformation}</li>
104     * <li>A constructor with following signature must be supplied: <br/> <code>
105     * public MyTransformation( <br/>
106     * &emsp;&emsp;&emsp;&emsp;java.util.list&lt;Double&gt; aValues,<br/>
107     * &emsp;&emsp;&emsp;&emsp;java.util.list&lt;Double&gt; bValues,<br/>
108     * &emsp;&emsp;&emsp;&emsp;{@link org.deegree.crs.coordinatesystems.CoordinateSystem} targetCRS,<br/>
109     * &emsp;&emsp;&emsp;&emsp;java.util.List&lt;org.w3c.dom.Element&gt; yourTransformationElements<br/>
110     * );<br/>
111     * </code>
112     * <p>
113     * The first three parameters are common to all polynomial values (for an explanation of their meaning take a look at
114     * {@link org.deegree.crs.transformations.polynomial.PolynomialTransformation}). Again, the last list, will contain all
115     * xml-dom elements you supplied in the deegree configuration (child elements of the
116     * crs:transformation/crs:MyTransformation), thus relieving you of the parsing of the deegree-crs-configuration.xml
117     * document.
118     * </p>
119     * </li>
120     * </ol>
121     * 
122     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
123     * 
124     * @author last edited by: $Author: lbuesching $
125     * 
126     * @version $Revision: 27765 $, $Date: 2010-11-04 07:50:32 +0100 (Do, 04 Nov 2010) $
127     * 
128     */
129    
130    public class DeegreeCRSProvider extends AbstractCRSProvider<Element> {
131    
132        private static ILogger LOG = LoggerFactory.getLogger( DeegreeCRSProvider.class );
133    
134        private CRSExporter exporter;
135    
136        /**
137         * The namespaces used in deegree.
138         */
139        private static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
140    
141        /**
142         * The prefix to use.
143         */
144        private final static String PRE = CommonNamespaces.CRS_PREFIX + ":";
145    
146        // /**
147        // * The EPSG-Database defines only 48 different ellipsoids, set to 60, will --probably-- result in no collisions.
148        // */
149        // private final Map<String, Ellipsoid> ellipsoids = new HashMap<String, Ellipsoid>( 60 * 5 );
150        //
151        // /**
152        // * The EPSG-Database defines over 400 different Geodetic Datums, set to 450, will --probably-- result in no
153        // * collisions.
154        // */
155        // private final Map<String, GeodeticDatum> datums = new HashMap<String, GeodeticDatum>( 450 * 5 );
156        //
157        // /**
158        // * The EPSG-Database defines over 1100 different CoordinateTransformations, set to 1200, will --probably-- result
159        // in
160        // * no collisions.
161        // */
162        // private final Map<String, Helmert> conversionInfos = new HashMap<String, Helmert>( 1200 * 5 );
163        //
164        // /**
165        // * Theoretically infinite prime meridians could be defined, let's set it to a more practical number of 42.
166        // */
167        // private final Map<String, PrimeMeridian> primeMeridians = new HashMap<String, PrimeMeridian>( 42 * 5 );
168        //
169        // /**
170        // * The EPSG-Database defines over 2960 different ProjectedCRS's, set to 3500, will --probably-- result in no
171        // * collisions.
172        // */
173        // private final Map<String, ProjectedCRS> projectedCRSs = new HashMap<String, ProjectedCRS>( 3500 * 5 );
174        //
175        // /**
176        // * The EPSG-Database defines over 490 different GeographicCRS's (geodetic), set to 600, will --probably-- result
177        // in
178        // * no collisions.
179        // */
180        // private final Map<String, GeographicCRS> geographicCRSs = new HashMap<String, GeographicCRS>( 600 * 5 );
181        //
182        // /**
183        // * The EPSG-Database defines ???
184        // */
185        // private final Map<String, CompoundCRS> compoundCRSs = new HashMap<String, CompoundCRS>( 600 * 5 );
186        //
187        // /**
188        // * The EPSG-Database doesn't define GeocentricCRS's, set to 30, will --probably-- result in no collisions.
189        // */
190        // private final Map<String, GeocentricCRS> geocentricCRSs = new HashMap<String, GeocentricCRS>( 30 );
191        //
192        // private final List<GeocentricCRS> cachedGeocentricCRSs = new LinkedList<GeocentricCRS>();
193        //
194        // private final Map<String, String> doubleGeocentricCRSs = new HashMap<String, String>( 5000 );
195        //
196        // private final List<CompoundCRS> cachedCompoundCRSs = new LinkedList<CompoundCRS>();
197        //
198        // private final Map<String, String> doubleCompoundCRSs = new HashMap<String, String>( 5000 );
199        //
200        // private final List<GeographicCRS> cachedGeoCRSs = new LinkedList<GeographicCRS>();
201        //
202        // private final Map<String, String> doubleGeos = new HashMap<String, String>( 5000 );
203        //
204        // private final List<ProjectedCRS> cachedProjCRSs = new LinkedList<ProjectedCRS>();
205        //
206        // private final Map<String, String> doubleProjCRS = new HashMap<String, String>( 3000 );
207        //
208        // private final List<GeodeticDatum> cachedDatums = new LinkedList<GeodeticDatum>();
209        //
210        // private final Map<String, String> doubleDatums = new HashMap<String, String>( 3000 );
211        //
212        // private final List<Helmert> cachedToWGS = new LinkedList<Helmert>();
213        //
214        // private final Map<String, String> doubleToWGS = new HashMap<String, String>( 3000 );
215        //
216        // private final List<Ellipsoid> cachedEllipsoids = new LinkedList<Ellipsoid>();
217        //
218        // private final Map<String, String> doubleEllipsoids = new HashMap<String, String>( 3000 );
219        //
220        // private final List<PrimeMeridian> cachedMeridians = new LinkedList<PrimeMeridian>();
221        //
222        // private final Map<String, String> doubleMeridians = new HashMap<String, String>( 3000 );
223        //
224        // private final Map<String, String> doubleProjections = new HashMap<String, String>( 3000 );
225    
226        // /**
227        // * The root element of the deegree - crs - configuration.
228        // */
229        // private Element rootElement;
230    
231        // private boolean checkForDoubleDefinition = false;
232    
233        /**
234         * @param properties
235         *            containing information about the crs resource class and the file location of the crs configuration. If
236         *            either is null the default mechanism is using the {@link CRSParser} and the
237         *            deegree-crs-configuration.xml
238         * @throws CRSConfigurationException
239         *             if the give file or the default-crs-configuration.xml file could not be loaded.
240         */
241        public DeegreeCRSProvider( Properties properties ) throws CRSConfigurationException {
242            super( properties, CRSParser.class, null );
243            if ( getResolver() == null ) {
244                CRSParser versionedParser = new CRSParser( this, new Properties( properties ) );
245                String version = versionedParser.getVersion();
246                if ( !"".equals( version ) ) {
247                    version = version.trim().replaceAll( "\\.", "_" );
248                    String className = "org.deegree.crs.configuration.deegree.CRSParser_" + version;
249                    try {
250                        Class<?> tClass = Class.forName( className );
251                        tClass.asSubclass( CRSParser.class );
252                        LOG.logDebug( "Trying to load configured CRS provider from classname: " + className );
253                        Constructor<?> constructor = tClass.getConstructor( this.getClass(), Properties.class,
254                                                                            Element.class );
255                        if ( constructor == null ) {
256                            LOG.logError( "No constructor ( " + this.getClass() + ", Properties.class) found in class:"
257                                          + className );
258                        } else {
259                            versionedParser = (CRSParser) constructor.newInstance( this, new Properties( properties ),
260                                                                                   versionedParser.getRootElement() );
261                        }
262                        className = "org.deegree.crs.configuration.deegree.CRSExporter_" + version;
263                        try {
264                            tClass = Class.forName( className );
265                            tClass.asSubclass( CRSExporter.class );
266                            constructor = tClass.getConstructor( Properties.class );
267                            LOG.logDebug( "Trying to load configured CRS exporter for version: " + version
268                                          + " from classname: " + className );
269                        } catch ( ClassNotFoundException e ) {
270                            LOG.logDebug( "Could not load the exporter for version 1, using fallback mechanism." );
271                            constructor = null;
272                        }
273    
274                        if ( constructor == null ) {
275                            exporter = new CRSExporter( new Properties( properties ) );
276                            LOG.logDebug( "No constructor ( Properties.class ) found in class:" + className );
277                        } else {
278                            versionedParser = (CRSParser) constructor.newInstance( new Properties( properties ) );
279                        }
280                    } catch ( InstantiationException e ) {
281                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ) );
282                    } catch ( IllegalAccessException e ) {
283                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
284                    } catch ( ClassNotFoundException e ) {
285                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
286                    } catch ( SecurityException e ) {
287                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
288                    } catch ( NoSuchMethodException e ) {
289                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
290                    } catch ( IllegalArgumentException e ) {
291                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
292                    } catch ( InvocationTargetException e ) {
293                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, e.getMessage() ), e );
294                    } catch ( Throwable t ) {
295                        LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", className, t.getMessage() ), t );
296                    }
297                } else {
298                    exporter = new CRSExporter( new Properties( properties ) );
299                }
300                setResolver( versionedParser );
301            }
302        }
303    
304        public boolean canExport() {
305            return exporter != null;
306        }
307    
308        public void export( StringBuilder sb, List<CoordinateSystem> crsToExport ) {
309            if ( exporter == null ) {
310                throw new UnsupportedOperationException( "Exporting is not supported for this deegree-crs version" );
311            }
312            ByteArrayOutputStream out = new ByteArrayOutputStream();
313            PrintWriter writer = new PrintWriter( out );
314            exporter.export( writer, crsToExport );
315    
316            try {
317                sb.append( out.toString( CharsetUtils.getSystemCharset() ) );
318            } catch ( UnsupportedEncodingException e ) {
319                LOG.logError( e );
320            }
321    
322        }
323    
324        /**
325         * @return the casted resolver of the super class.
326         */
327        @Override
328        public CRSParser getResolver() {
329            return (CRSParser) super.getResolver();
330        }
331    
332        public List<String[]> getSortedAvailableCRSIds()
333                                throws CRSConfigurationException {
334            List<Element> allCRSs = new LinkedList<Element>();
335            List<String[]> result = new LinkedList<String[]>();
336    
337            try {
338                allCRSs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geographicCRS",
339                                                      nsContext ) );
340                allCRSs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "projectedCRS",
341                                                      nsContext ) );
342                allCRSs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geocentricCRS",
343                                                      nsContext ) );
344                allCRSs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "compoundCRS", nsContext ) );
345                for ( Element crs : allCRSs ) {
346                    if ( crs != null ) {
347                        result.add( XMLTools.getNodesAsStrings( crs, PRE + "id", nsContext ) );
348                    }
349                }
350            } catch ( XMLParsingException e ) {
351                throw new CRSConfigurationException(
352                                                     Messages.getMessage( "CRS_CONFIG_GET_ALL_ELEMENT_IDS", e.getMessage() ),
353                                                     e );
354            }
355            return result;
356        }
357    
358        public List<String> getAvailableCRSIds()
359                                throws CRSConfigurationException {
360            List<Element> allCRSIDs = new LinkedList<Element>();
361    
362            try {
363                allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geographicCRS/" + PRE
364                                                                                        + "id", nsContext ) );
365                allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "projectedCRS/" + PRE
366                                                                                        + "id", nsContext ) );
367                allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geocentricCRS/" + PRE
368                                                                                        + "id", nsContext ) );
369                allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "compoundCRS/" + PRE
370                                                                                        + "id", nsContext ) );
371            } catch ( XMLParsingException e ) {
372                throw new CRSConfigurationException(
373                                                     Messages.getMessage( "CRS_CONFIG_GET_ALL_ELEMENT_IDS", e.getMessage() ),
374                                                     e );
375            }
376            List<String> result = new LinkedList<String>();
377            for ( Element crs : allCRSIDs ) {
378                if ( crs != null ) {
379                    result.add( XMLTools.getStringValue( crs ) );
380                }
381            }
382            return result;
383        }
384    
385        public List<CoordinateSystem> getAvailableCRSs()
386                                throws CRSConfigurationException {
387            List<CoordinateSystem> allSystems = new LinkedList<CoordinateSystem>();
388            if ( getResolver().getRootElement() != null ) {
389                List<Element> allCRSIDs = new LinkedList<Element>();
390    
391                try {
392                    allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geographicCRS/"
393                                                                                            + PRE + "id", nsContext ) );
394                    allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "projectedCRS/"
395                                                                                            + PRE + "id", nsContext ) );
396                    allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "geocentricCRS/"
397                                                                                            + PRE + "id", nsContext ) );
398                    allCRSIDs.addAll( XMLTools.getElements( getResolver().getRootElement(), "//" + PRE + "compoundCRS/"
399                                                                                            + PRE + "id", nsContext ) );
400                } catch ( XMLParsingException e ) {
401                    throw new CRSConfigurationException( Messages.getMessage( "CRS_CONFIG_GET_ALL_ELEMENT_IDS",
402                                                                              e.getMessage() ), e );
403                }
404                final int total = allCRSIDs.size();
405                int count = 0;
406                int percentage = (int) Math.round( total / 100.d );
407                int number = 0;
408                System.out.println( "Trying to create a total of " + total + " coordinate systems." );
409                for ( Element crsID : allCRSIDs ) {
410                    if ( crsID != null ) {
411                        String id = crsID.getTextContent();
412                        if ( id != null && !"".equals( id.trim() ) ) {
413                            if ( count++ % percentage == 0 ) {
414                                System.out.print( "\r" + ( number ) + ( ( number++ < 10 ) ? "  " : " " ) + "% created" );
415                            }
416                            allSystems.add( getCRSByID( id ) );
417                        }
418                    }
419                }
420                System.out.println();
421                // if ( checkForDoubleDefinition ) {
422                // allSystems.addAll( cachedGeoCRSs );
423                // allSystems.addAll( cachedProjCRSs );
424                // allSystems.addAll( cachedGeocentricCRSs );
425                // allSystems.addAll( cachedCompoundCRSs );
426                // StringBuilder cachedGeos = new StringBuilder( "Cached Geographic coordinatesystems (" );
427                // cachedGeos.append( cachedGeoCRSs.size() ).append( "):\n" );
428                // for ( GeographicCRS geo : cachedGeoCRSs ) {
429                // cachedGeos.append( geo.getIdentifier() ).append( "\n" );
430                // }
431                // System.out.println( cachedGeos.toString() );
432                // if ( !doubleGeos.isEmpty() ) {
433                // Set<String> keys = doubleGeos.keySet();
434                // LOG.logInfo( "Following geographic crs's could probably be mapped on eachother" );
435                // for ( String key : keys ) {
436                // LOG.logInfo( key + " : " + doubleGeos.get( key ) );
437                // }
438                // }
439                // if ( !doubleProjCRS.isEmpty() ) {
440                // Set<String> keys = doubleProjCRS.keySet();
441                // LOG.logInfo( "Following projected crs's could probably be mapped on eachother" );
442                // for ( String key : keys ) {
443                // LOG.logInfo( key + " : " + doubleProjCRS.get( key ) );
444                // }
445                //
446                // }
447                // if ( !doubleGeocentricCRSs.isEmpty() ) {
448                // Set<String> keys = doubleGeocentricCRSs.keySet();
449                // LOG.logInfo( "Following geocentric crs's could probably be mapped on eachother" );
450                // for ( String key : keys ) {
451                // LOG.logInfo( key + " : " + doubleGeocentricCRSs.get( key ) );
452                // }
453                // }
454                //
455                // if ( !doubleProjections.isEmpty() ) {
456                // Set<String> keys = doubleProjections.keySet();
457                // LOG.logInfo( "Following projections could probably be mapped on eachother" );
458                // for ( String key : keys ) {
459                // LOG.logInfo( key + " : " + doubleProjections.get( key ) );
460                // }
461                // }
462                // if ( !doubleDatums.isEmpty() ) {
463                // Set<String> keys = doubleDatums.keySet();
464                // LOG.logInfo( "Following datums could probably be mapped on eachother" );
465                // for ( String key : keys ) {
466                // LOG.logInfo( key + " : " + doubleDatums.get( key ) );
467                // }
468                // }
469                // if ( !doubleToWGS.isEmpty() ) {
470                // Set<String> keys = doubleToWGS.keySet();
471                // LOG.logInfo( "Following wgs conversion infos could probably be mapped on eachother" );
472                // for ( String key : keys ) {
473                // LOG.logInfo( key + " : " + doubleToWGS.get( key ) );
474                // }
475                // }
476                // if ( !doubleEllipsoids.isEmpty() ) {
477                // Set<String> keys = doubleEllipsoids.keySet();
478                // LOG.logInfo( "Following ellipsoids could probably be mapped on eachother" );
479                // for ( String key : keys ) {
480                // LOG.logInfo( key + " : " + doubleEllipsoids.get( key ) );
481                // }
482                // }
483                // if ( !doubleMeridians.isEmpty() ) {
484                // Set<String> keys = doubleEllipsoids.keySet();
485                // LOG.logInfo( "Following prime meridians could probably be mapped on eachother" );
486                // for ( String key : keys ) {
487                // LOG.logInfo( key + " : " + doubleMeridians.get( key ) );
488                // }
489                // }
490                // } else {
491                // Collection<CompoundCRS> cCRSs = compoundCRSs.values();
492                // for ( String key : compoundCRSs.keySet() ) {
493                // CompoundCRS crs = compoundCRSs.get( key );
494                // if ( !allSystems.contains( crs ) ) {
495                // allSystems.add( crs );
496                // }
497                // }
498                // for ( String key : geographicCRSs.keySet() ) {
499                // GeographicCRS crs = geographicCRSs.get( key );
500                // if ( !allSystems.contains( crs ) ) {
501                // allSystems.add( crs );
502                // }
503                // }
504                // for ( String key : geocentricCRSs.keySet() ) {
505                // GeocentricCRS crs = geocentricCRSs.get( key );
506                // if ( !allSystems.contains( crs ) ) {
507                // allSystems.add( crs );
508                // }
509                // }
510                // for ( String key : projectedCRSs.keySet() ) {
511                // ProjectedCRS crs = projectedCRSs.get( key );
512                // if ( !allSystems.contains( crs ) ) {
513                // allSystems.add( crs );
514                // }
515                // }
516                // }
517    
518            } else {
519                LOG.logDebug( "The root element is null, is this correct behaviour?" );
520            }
521            return allSystems;
522        }
523    
524        public Identifiable getIdentifiable( String id )
525                                throws CRSConfigurationException {
526            Identifiable result = getCachedIdentifiable( id );
527            if ( result == null ) {
528                result = getResolver().parseIdentifiableObject( id );
529            }
530            return result;
531        }
532    
533        @Override
534        protected CoordinateSystem parseCoordinateSystem( Element crsDefinition )
535                                throws CRSConfigurationException {
536            return getResolver().parseCoordinateSystem( crsDefinition );
537        }
538    
539        @Override
540        public Transformation parseTransformation( Element transformationDefinition )
541                                throws CRSConfigurationException {
542            return getResolver().parseTransformation( transformationDefinition );
543    
544        }
545    
546        public Transformation getTransformation( CoordinateSystem sourceCRS, CoordinateSystem targetCRS )
547                                throws CRSConfigurationException {
548            return getResolver().getTransformation( sourceCRS, targetCRS );
549        }
550    
551        public List<Transformation> getTransformations() {
552            throw new UnsupportedOperationException(
553                                                     "Parsing of transformations is not applicable for deegree configuration files yet." );
554        }
555    }