Statistics
| Revision:

root / org.gvsig.geotools.proj / trunk / org.gvsig.geotools.proj / org.gvsig.geotools.proj.catalog.impl / src / main / java / org / gvsig / geotools / proj / catalog / GtCRSCatalogManager.java @ 867

History | View | Annotate | Download (22.9 KB)

1
package org.gvsig.geotools.proj.catalog;
2

    
3
import java.io.File;
4
import java.sql.Connection;
5
import java.sql.PreparedStatement;
6
import java.sql.ResultSet;
7
import java.sql.SQLException;
8
import java.text.ParseException;
9
import java.util.ArrayList;
10
import java.util.Arrays;
11
import java.util.Collection;
12
import java.util.Collections;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.Set;
17
import java.util.regex.Pattern;
18

    
19
import javax.sql.DataSource;
20

    
21
import org.geotools.factory.FactoryFinder;
22
import org.geotools.factory.FactoryNotFoundException;
23
import org.geotools.factory.Hints;
24
import org.geotools.metadata.iso.citation.Citations;
25
import org.geotools.referencing.CRS;
26
import org.geotools.referencing.CRS.AxisOrder;
27
import org.geotools.referencing.ReferencingFactoryFinder;
28
import org.geotools.referencing.factory.AbstractAuthorityFactory;
29
import org.geotools.referencing.factory.BufferedAuthorityFactory;
30
import org.geotools.referencing.factory.epsg.HsqlEpsgDatabase;
31
import org.geotools.referencing.factory.epsg.ThreadedEpsgFactory;
32
import org.geotools.referencing.wkt.MathTransformParser;
33
import org.geotools.referencing.wkt.Parser;
34
import org.geotools.resources.i18n.ErrorKeys;
35
import org.geotools.resources.i18n.Errors;
36
import org.gvsig.geotools.proj.catalog.extent.DefaultExtent;
37
import org.gvsig.geotools.proj.catalog.extent.DefaultGeographicBoundingBox;
38
import org.gvsig.geotools.proj.catalog.extent.DefaultVerticalExtent;
39
import org.gvsig.geotools.proj.catalog.utils.GtUtils;
40
import org.gvsig.geotools.proj.catalog.utils.WKTUtils;
41
import org.gvsig.proj.catalog.CRSCatalogManager;
42
import org.gvsig.proj.catalog.CRSDefinition;
43
import org.gvsig.proj.catalog.CRSType;
44
import org.gvsig.proj.catalog.TextSerialization;
45
import org.gvsig.proj.catalog.TextSerialization.Format;
46
import org.gvsig.proj.catalog.TransformationDefinition;
47
import org.gvsig.proj.catalog.exception.CoordinateReferenceSystemException;
48
import org.gvsig.proj.catalog.exception.UnsupportedCoordinateReferenceSystemException;
49
import org.gvsig.proj.catalog.exception.UnsupportedFormatException;
50
import org.gvsig.proj.catalog.exception.UnsupportedTransformationException;
51
import org.gvsig.proj.catalog.extent.Extent;
52
import org.gvsig.proj.catalog.extent.GeographicBoundingBox;
53
import org.gvsig.proj.catalog.extent.VerticalExtent;
54
import org.opengis.referencing.AuthorityFactory;
55
import org.opengis.referencing.FactoryException;
56
import org.opengis.referencing.NoSuchAuthorityCodeException;
57
import org.opengis.referencing.crs.CRSAuthorityFactory;
58
import org.opengis.referencing.crs.CRSFactory;
59
import org.opengis.referencing.crs.CompoundCRS;
60
import org.opengis.referencing.crs.CoordinateReferenceSystem;
61
import org.opengis.referencing.crs.GeocentricCRS;
62
import org.opengis.referencing.crs.GeographicCRS;
63
import org.opengis.referencing.cs.CartesianCS;
64
import org.opengis.referencing.cs.CoordinateSystem;
65
import org.opengis.referencing.cs.EllipsoidalCS;
66
import org.opengis.referencing.cs.SphericalCS;
67
import org.opengis.referencing.cs.VerticalCS;
68
import org.opengis.referencing.datum.EngineeringDatum;
69
import org.opengis.referencing.datum.GeodeticDatum;
70
import org.opengis.referencing.datum.VerticalDatum;
71
import org.opengis.referencing.operation.Conversion;
72
import org.opengis.referencing.operation.CoordinateOperation;
73
import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
74
import org.opengis.referencing.operation.CoordinateOperationFactory;
75
import org.opengis.referencing.operation.MathTransform;
76
import org.opengis.referencing.operation.Projection;
77

    
78
public class GtCRSCatalogManager implements CRSCatalogManager {
79
        private static final String EPSG_DB_SUBFOLDER = "epsg";        
80
        private static final List<TextSerialization.Format> SUPPORTED_FORMATS = Arrays.asList(TextSerialization.Format.WKT1);
81
        private static final List<String> supportedAuthorities = Collections.unmodifiableList(Arrays.asList("EPSG", "ESRI", "USER"));        
82

    
83
        public GtCRSCatalogManager() {
84
                
85
        }
86

    
87
        @Override
88
        public List<String> getAuthorityNames() {
89
                return supportedAuthorities;
90
                //return new ArrayList<String>(CRS.getSupportedAuthorities(true));
91
        }
92
        
93
        protected String toCode(String authorityName, String relCode) {
94
                return authorityName + ":" + relCode;
95
        }
96

    
97
        @Override
98
        public List<String> getCodes() {
99
                ArrayList<String> codes = new ArrayList<String>();
100
                Set<String> authorities = CRS.getSupportedAuthorities(true);
101
                for (String auth: authorities) {
102
                        CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory(auth, null);
103
                        try {
104
                                for (String code: factory.getAuthorityCodes(CoordinateReferenceSystem.class)) {
105
                                        codes.add(toCode(auth, code));
106
                                }
107
                        } catch (FactoryException | FactoryNotFoundException e) {
108
                                // TODO Auto-generated catch block
109
                                e.printStackTrace();
110
                        }
111
                }
112
                return codes;
113
        }
114

    
115
        @Override
116
        public List<String> getCodes(String authorityName) {
117
                // FIXME handle other authorities
118
                ArrayList<String> codes = new ArrayList<String>();
119

    
120
                if ("EPSG".equals(authorityName)) {
121
                        try {
122
                                CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory(authorityName, null);
123
                                for (String code: factory.getAuthorityCodes(CoordinateReferenceSystem.class)) {
124
                                        codes.add(toCode(authorityName, code));
125
                                }
126

    
127
                        } catch (FactoryException | FactoryNotFoundException e) {
128
                                // TODO Auto-generated catch block
129
                                e.printStackTrace();
130
                        }
131
                }
132
                return codes;
133
        }
134

    
135
        @Override
136
        public List<String> search(String searchString) {
137
                // FIXME handle other authorities
138
                return searchEpsg(searchString, null, null);
139
        }
140

    
141
        @Override
142
        public List<String> search(String authority, String searchString) {
143
                // FIXME handle other authorities
144
                if (authority.equals("EPSG")) {
145
                        return searchEpsg(searchString, null, null);
146
                }
147
                return Collections.emptyList();
148
        }
149
        
150
        @Override
151
        public List<String> search(String authority, String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) {
152
                // FIXME handle other authorities
153
                if (authority.equals("EPSG")) {
154
                        return searchEpsg(searchString, includeTypes, excludeTypes);
155
                }
156
                return Collections.emptyList();
157
        }
158

    
159
        
160
        protected List<String> searchEpsg(String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) {
161
                // FIXME handle other authorities
162
                CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null);
163
                if (factory instanceof ThreadedEpsgFactory) {
164
                        ThreadedEpsgFactory epsgFactory = (ThreadedEpsgFactory) factory;
165
                        try {
166
                                DataSource ds = epsgFactory.getDataSource();
167
                                Connection c = ds.getConnection();
168
                                return searchEpsg(searchString, c, includeTypes, excludeTypes);
169
                        } catch (SQLException e) {
170
                                // TODO Auto-generated catch block
171
                                e.printStackTrace();
172
                        }
173
                }
174
                return Collections.EMPTY_LIST;
175
        }
176
        
177
        private boolean isExcluded(CRSType type,  CRSType[] excludeTypes) {
178
                for (CRSType excluded: excludeTypes) {
179
                        if (type.equals(excluded)) {
180
                                return true;
181
                        }
182
            }
183
                return false;
184
        }
185
        
186
    public synchronized List<String> searchEpsg(String searchString, Connection conn,
187
                    CRSType[] includeTypes, CRSType[] excludeTypes) throws SQLException
188
    {
189
            ArrayList<String> codes = new ArrayList<String>();
190
            
191
            if (searchString == null) {
192
                    searchString = "";
193
            }
194
            else if (searchString.startsWith("EPSG:")) {
195
                    searchString = searchString.substring(5);
196
            }
197
            searchString = "%" + searchString.toLowerCase() + "%";
198
            StringBuilder builder = new StringBuilder("SELECT COORD_REF_SYS_CODE,"
199
                +       " COORD_REF_SYS_NAME,"
200
                +       " AREA_OF_USE_CODE,"
201
                +       " CRS_SCOPE,"
202
                +       " REMARKS,"
203
                +       " COORD_REF_SYS_KIND,"
204
                +       " COORD_SYS_CODE,"       // Null for CompoundCRS
205
                +       " DATUM_CODE,"           // Null for ProjectedCRS
206
                +       " SOURCE_GEOGCRS_CODE,"  // For ProjectedCRS
207
                +       " PROJECTION_CONV_CODE," // For ProjectedCRS
208
                +       " CMPD_HORIZCRS_CODE,"   // For CompoundCRS only
209
                +       " CMPD_VERTCRS_CODE,"     // For CompoundCRS only
210
                +       " DEPRECATED"
211
                + " FROM epsg_coordinatereferencesystem"
212
                + " WHERE DEPRECATED = 0 AND (COORD_REF_SYS_CODE LIKE ? OR LCASE(COORD_REF_SYS_NAME) LIKE ?"
213
                + " OR LCASE(REMARKS) LIKE ?"
214
                + " OR LCASE(CRS_SCOPE) LIKE ?)");
215
            
216
            if (includeTypes != null) {
217
                    boolean first = true;
218
                    builder.append(" AND (");
219
                    for (CRSType type: includeTypes) {
220
                            if (first) {
221
                                    first = false;
222
                                    builder.append("COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'");
223
                            }
224
                            else {
225
                                    builder.append(" OR COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'");
226
                            }
227
                    }
228
                    builder.append(")");
229
            }
230
            if (excludeTypes != null) {
231
                    boolean first = true;
232
                    builder.append(" AND NOT(");
233
                    for (CRSType type: excludeTypes) {
234
                            if (first) {
235
                                    first = false;
236
                                    builder.append("COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'");
237
                            }
238
                            else {
239
                                    builder.append(" OR COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'");
240
                            }
241
                    }
242
                    builder.append(")");
243
            }
244
                    
245
        try {
246
            // FIXME: JOIN query with area of use. Maybe also with  COORD_SYS_CODE to search for coord sys name
247
            final PreparedStatement stmt;
248
            stmt = conn.prepareStatement(builder.toString());
249
            stmt.setString(1, searchString);
250
            stmt.setString(2, searchString);
251
            stmt.setString(3, searchString);
252
            stmt.setString(4, searchString);
253
            ResultSet result = stmt.executeQuery();
254
            while (result.next()) {
255
                final String epsg    = result.getString(1);//getString(result, 1, code);
256
                final String name    = result.getString(2);//getString(result, 2, code);
257
                final String area    = result.getString(3);
258
                final String scope   = result.getString(4);
259
                final String remarks = result.getString(5);
260
                final String kind = result.getString(6);
261

    
262
                final String csCode  = result.getString(7);
263
                final String dmCode    = result.getString( 8); // geographic
264
                final String geoCode = result.getString(9);
265
                final String opCode  = result.getString(10);
266
                // vertical:
267
                final String code1 = result.getString(11);
268
                final String code2 = result.getString(12);
269
                codes.add("EPSG:"+epsg);
270
            }
271
            result.close();
272
        } catch (SQLException exception) {
273
            throw exception;
274
        }
275
        conn.close();
276
        return codes;
277
    }
278

    
279
        @Override
280
        public DefaultCRSDefinition getCRSDefinition(String code) throws UnsupportedCoordinateReferenceSystemException {
281
                CoordinateReferenceSystem crs;
282
                CoordinateReferenceSystem internalCrs;
283
                try {
284
                        crs = CRS.decode(code, false);
285
                        if (CRS.getAxisOrder(crs) == AxisOrder.NORTH_EAST) {
286
                                internalCrs = CRS.decode(code, true);
287
                        }
288
                        else {
289
                                internalCrs = crs;
290
                        }
291
                        return new DefaultCRSDefinition(crs, internalCrs, null);
292
                }  catch (NoSuchAuthorityCodeException e) {
293
                        throw new UnsupportedCoordinateReferenceSystemException(code, e);
294
                } catch (FactoryException e) {
295
                        throw new UnsupportedCoordinateReferenceSystemException(code, e);
296
                }
297
        }
298
        
299
        public DefaultCRSDefinition getCRSDefinition(CoordinateReferenceSystem crs) throws UnsupportedCoordinateReferenceSystemException {
300
                return new DefaultCRSDefinition(crs);
301
        }
302

    
303
        @Override
304
        public CRSDefinition getCompoundCRS(CRSDefinition... crsList) throws UnsupportedCoordinateReferenceSystemException {
305
                ArrayList<CoordinateReferenceSystem> components = new ArrayList<CoordinateReferenceSystem>();
306
                for (CRSDefinition def: crsList) {
307
                        if (def instanceof DefaultCRSDefinition) {
308
                                components.add(((DefaultCRSDefinition)def).getInternalCRS());        
309
                        }
310
                        else {
311
                                def = parseCRSDefinition(def.toWKT());
312
                        }
313
                }
314
            CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
315
                CoordinateReferenceSystem compoundCRS;
316
                try {
317
                    Map<String, String> properties = new HashMap<String, String>();
318
                    crsFactory.createCompoundCRS(properties, components.toArray(new CoordinateReferenceSystem[components.size()]));
319
                        compoundCRS = crsFactory.createCompoundCRS(properties, components.toArray(new CoordinateReferenceSystem[components.size()]));;
320
                        return new DefaultCRSDefinition(compoundCRS);
321
                } catch (FactoryException e) {
322
                        throw new UnsupportedCoordinateReferenceSystemException(e);
323
                }
324
        }
325
        
326
        /**
327
         * Removes axis definition from a WKT string
328
         * 
329
         * @param wktDef
330
         * @return A WKT string without any axis definition
331
         */
332
        private static String removeWktAxis(String wktDef) {
333
                return WKTUtils.removeAxisDefinition(wktDef);
334
        }
335
        
336
        @Override
337
        public DefaultCRSDefinition parseCRSDefinition(String def) throws UnsupportedCoordinateReferenceSystemException {
338
                CoordinateReferenceSystem crs;
339
                CoordinateReferenceSystem internalCrs;
340
                try {
341
                        crs = CRS.parseWKT(def);
342
                        if (CRS.getAxisOrder(crs)==AxisOrder.NORTH_EAST) {
343
                                String id = GtUtils.getIdentifier(crs);
344
                                if (id != null && id.startsWith("EPSG:")) { //FIXME: could this also work for other authorities such as ESRI?
345
                                        internalCrs = CRS.decode(id, true);
346
                                }
347
                                else {
348
                                        // Hack: remove the axis from the WKT. It could be better to try to derive a CRS with default axis order, but I don't see the way for non EPSG CRSs 
349
                                        internalCrs = CRS.parseWKT(removeWktAxis(def));
350
                                }
351
                        }
352
                        else {
353
                                internalCrs = crs;
354
                        }
355
                } catch (NoSuchAuthorityCodeException e) {
356
                        throw new UnsupportedCoordinateReferenceSystemException(def, e);
357
                } catch (FactoryException e) {
358
                        throw new UnsupportedCoordinateReferenceSystemException(def, e);
359
                }
360
                return new DefaultCRSDefinition(crs, internalCrs, def);
361
        }
362
        
363

    
364
        @Override
365
        public DefaultCRSDefinition parseCRSDefinition(String def, Format format)
366
                        throws UnsupportedCoordinateReferenceSystemException, UnsupportedFormatException {
367
                if (SUPPORTED_FORMATS.contains(format)) {
368
                        parseCRSDefinition(def);
369
                }
370
                throw new UnsupportedFormatException(format);
371
        }
372
        
373
        @Override
374
        public TransformationDefinition getTransformationDefinition(String code)
375
                        throws UnsupportedTransformationException {
376
                try {
377
                        AuthorityFactory factory = ReferencingFactoryFinder.getCoordinateOperationAuthorityFactory(
378
                                        "EPSG",
379
                                        null);
380
                        CoordinateOperation op;
381
                        if (factory instanceof AbstractAuthorityFactory) {
382
                                op = ((AbstractAuthorityFactory)factory).createCoordinateOperation(code);
383
                        }
384
                        else {
385
                                Object obj;
386
                                // We need to check the returned object type, since AuthorityFactory.createObject()
387
                                // will not create a CoordinateOperatoin if there is a CRS that has the same code as the coordinate operation 
388
                                obj = factory.createObject(code);
389
                                if (obj instanceof CoordinateOperation) {
390
                                        // we have it
391
                                        op = (CoordinateOperation) obj;
392
                                }
393
                                else { // we found another object having the same code, sigh 
394
                                        throw new UnsupportedTransformationException(code);
395
                                }
396
                        }
397
                        return new DefaultTransformationDefinition(op,
398
                                        getCRSDefinition(op.getSourceCRS()), getCRSDefinition(op.getTargetCRS()));
399
                } catch (FactoryException | CoordinateReferenceSystemException e) {
400
                        throw new UnsupportedTransformationException(code, e);
401
                }
402
        }
403

    
404
        @Override
405
        public TransformationDefinition parseTransformationDefinition(String def, String sourceCRS, String targetCRS)
406
                        throws UnsupportedTransformationException, ParseException {
407
                DefaultCRSDefinition source;
408
                try {
409
                        source = parseCRSDefinition(sourceCRS);
410
                        DefaultCRSDefinition target = parseCRSDefinition(sourceCRS);
411
                        MathTransformParser parser = new MathTransformParser();
412
                        MathTransform mt = parser.parseMathTransform(def);
413
                        return new DefaultTransformationDefinition(mt, source, target);
414
                } catch (CoordinateReferenceSystemException e) {
415
                        throw new UnsupportedTransformationException(e);
416
                }
417
        }
418

    
419
        @Override
420
        public TransformationDefinition parseTransformationDefinition(String def, String sourceCRS, String targetCRS,
421
                        Format format) throws UnsupportedTransformationException, ParseException, UnsupportedFormatException {
422
                if (format==Format.WKT1) {
423
                        return parseTransformationDefinition(def, sourceCRS, targetCRS);
424
                }
425
                throw new UnsupportedFormatException(format);
426
        }
427
        
428
        @Override
429
        public DefaultTransformationDefinition parseTransformationDefinition(String def)
430
                        throws ParseException, CoordinateReferenceSystemException {
431
                // This implementation don't support this method because only WKT1 format is supported,
432
                // but try to parse to raise an indicative exception 
433
                MathTransformParser parser = new MathTransformParser();
434
                parser.parseMathTransform(def);
435
                throw new CoordinateReferenceSystemException("Not enough information to construct the transformation. WKT1 does not encode source and target CRSs");
436
        }
437

    
438
        @Override
439
        public DefaultTransformationDefinition parseTransformationDefinition(String def, Format format)
440
                        throws ParseException, CoordinateReferenceSystemException {
441
                if (SUPPORTED_FORMATS.contains(format)) {
442
                        parseTransformationDefinition(def);
443
                }
444
                throw new UnsupportedFormatException(format);
445
        }
446

    
447
        @Override
448
        public String registerCoordinateReferenceSystem(String wktDefinition, String description) {
449
                // TODO Auto-generated method stub
450
                return null;
451
        }
452

    
453
        @Override
454
        public String registerTransformation(String wktDefinition, String sourceCRS, String targetCRS, String description)
455
                        throws UnsupportedTransformationException, ParseException {
456
                // TODO Auto-generated method stub
457
                return null;
458
        }
459

    
460
        @Override
461
        public String registerCoordinateTransformationPVT(String sourceCRS, String targetCRS, String description,
462
                        float xTraslation, float yTraslation, float zTraslation, float xRotation, float yRotation, float zRotation,
463
                        float scaleDifference) {
464
                // TODO Auto-generated method stub
465
                return null;
466
        }
467

    
468
        @Override
469
        public String registerCoordinateTransformationCFR(String sourceCRS, String targetCRS, String description,
470
                        float xTraslation, float yTraslation, float zTraslation, float xRotation, float yRotation, float zRotation,
471
                        float scaleDifference) {
472
                // TODO Auto-generated method stub
473
                return null;
474
        }
475

    
476
        @Override
477
        public String registerCoordinateTransformation(String sourceCRS, String targetCRS, String description,
478
                        File ntv2Grid) {
479
                // TODO Auto-generated method stub
480
                return null;
481
        }
482

    
483
        @Override
484
        public List<TransformationDefinition> getCoordinateTransformations(CRSDefinition source, CRSDefinition target)
485
                        throws UnsupportedTransformationException {
486
                DefaultCRSDefinition sourceDef = (DefaultCRSDefinition) source;
487
                DefaultCRSDefinition targetDef = (DefaultCRSDefinition) target;
488
                ArrayList<TransformationDefinition> transforms = new ArrayList<TransformationDefinition>();
489
                try {
490
                        CoordinateReferenceSystem sourceCRS = sourceDef.getInternalCRS();
491
                        CoordinateReferenceSystem targetCRS = targetDef.getInternalCRS();
492
                CoordinateOperationFactory operationFactory = CRS.getCoordinateOperationFactory(false);
493
                Set<CoordinateOperation> ops = operationFactory.findOperations(sourceCRS, targetCRS);
494
                for (CoordinateOperation op: ops) {
495
                        if (GtUtils.getIdentifier(op) == null) {
496
                                CoordinateOperation defOp = GtUtils.getDefiningOperation(op);
497
                                if (GtUtils.getIdentifier(defOp) == null) {
498
                                        /**
499
                                         * When Geotools computes the inverse transformation, we loose the identifier, which
500
                                         * makes the transformation quite useless for the final users since they can't distinguish
501
                                         * it from any other operation. Therefore, we skip operations lacking an identifier, and
502
                                         * we'll add them later requesting the inverse operation. It is quite hacky but I can't see
503
                                         * a better approach
504
                                         */
505
                                        continue;
506
                                }
507
                        }
508
                        DefaultTransformationDefinition def = new DefaultTransformationDefinition(op, sourceDef, targetDef);
509
                        transforms.add(def);
510
                }
511
                
512
                // now we'll try the inverse transformation
513
                ops = operationFactory.findOperations(targetCRS, sourceCRS);
514
                for (CoordinateOperation op: ops) {
515
                        if (GtUtils.getIdentifier(op) == null) {
516
                                CoordinateOperation defOp = GtUtils.getDefiningOperation(op);
517
                                if (GtUtils.getIdentifier(defOp) == null) {
518
                                        continue;
519
                                }
520
                        }
521
                        DefaultTransformationDefinition def = new DefaultTransformationDefinition(op, sourceDef, targetDef);
522
                        transforms.add(def);
523
                }
524
                } catch (FactoryException e) {
525
                        // FIXME: we should log instead of raising an exception
526
                        throw new UnsupportedTransformationException(e);
527
                }
528
                return transforms;
529
        }
530

    
531
        @Override
532
        public List<TransformationDefinition> getCoordinateTransformations(String source, String target) throws UnsupportedTransformationException {
533
                try {
534
                        DefaultCRSDefinition sourceDef = getCRSDefinition(source);
535
                        DefaultCRSDefinition targetDef = getCRSDefinition(target);
536
                        return getCoordinateTransformations(sourceDef, targetDef);
537
                } catch (UnsupportedCoordinateReferenceSystemException e) {
538
                        // FIXME: we should log instead of raising an exception
539
                        throw new UnsupportedTransformationException(e);
540
                }
541
        }
542

    
543
        /**
544
         * Sets the path to the folder to be used by the library to load the CRS and
545
         * transformation definitions. The specified path must contain one or more subfolders,
546
         * containg the CRS and transformation database in the appropriate format:
547
         * <ul><li>for EPSG database: a "epsg" subfolder must exist, which contains a HSQL database
548
         * called "EPSG". The structure of this database must be the same used by Geotools,
549
         * which is essentially based in the EPSG data model.</li>
550
         * </ul>
551
         * 
552
         * This method only has effect when it is called before any other method in the manager
553
         * (before instantiating any CRS, transformation, etc). 
554
         * 
555
         * @param path The path to the folder containing the system CRS and transformation
556
         * definitions
557
         */
558
        @Override
559
        public void setSystemDataPath(File path) {
560
                System.setProperty(HsqlEpsgDatabase.DIRECTORY_KEY, path.getAbsolutePath() + "/" + EPSG_DB_SUBFOLDER);
561
        }
562

    
563
        @Override
564
        public void setUserDataPath(File path) {
565
                // TODO Auto-generated method stub
566
                
567
        }
568

    
569
        @Override
570
        public List<TextSerialization.Format> getSupportedFormats() {
571
                // TODO Auto-generated method stub
572
                return SUPPORTED_FORMATS;
573
        }
574

    
575
        @Override
576
        public GeographicBoundingBox createBoundingBox(double westBoundLongitude, double eastBoundLongitude,
577
                        double northBoundLatitude, double southBoundLatitude) {
578
                return new DefaultGeographicBoundingBox(westBoundLongitude, eastBoundLongitude, northBoundLatitude, southBoundLatitude);
579
        }
580

    
581
        @Override
582
        public VerticalExtent createVerticalExtent(CRSDefinition crs, double minValue, double maxValue) {
583
                return new DefaultVerticalExtent(crs, minValue, maxValue);
584
        }
585

    
586
        @Override
587
        public Extent createExtent(String description, 
588
                        Collection<GeographicBoundingBox> horizontalBoundingBoxList,
589
                        Collection<VerticalExtent> verticalBoundingBoxList) {
590
                return new DefaultExtent(description, horizontalBoundingBoxList, verticalBoundingBoxList);
591
        }
592
}