    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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: 23198 $, $Date: 2010-03-23 08:40:31 +0100 (Di, 23. Mär 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    }