Revision 151

View differences:

trunk/org.gvsig.gdal/org.gvsig.gdal.app/org.gvsig.gdal.app.mainplugin/org.gvsig.gdal.app.mainplugin.common/src/main/java/org/gvsig/gdal/app/mainplugin/common/ogr2ogr.java
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  OpenGIS Simple Features Reference Implementation
5
 * Purpose:  Java port of a simple client for translating between formats.
6
 * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
7
 *
8
 * Port from ogr2ogr.cpp by Frank Warmerdam
9
 *
10
 ******************************************************************************
11
 * Copyright (c) 2009, Even Rouault
12
 * Copyright (c) 1999, Frank Warmerdam
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a
15
 * copy of this software and associated documentation files (the "Software"),
16
 * to deal in the Software without restriction, including without limitation
17
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18
 * and/or sell copies of the Software, and to permit persons to whom the
19
 * Software is furnished to do so, subject to the following conditions:
20
 *
21
 * The above copyright notice and this permission notice shall be included
22
 * in all copies or substantial portions of the Software.
23
 *
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30
 * DEALINGS IN THE SOFTWARE.
31
 ****************************************************************************/
32
package org.gvsig.gdal.app.mainplugin.common;
33

  
34
import java.io.File;
35
import java.util.Vector;
36
import java.util.Enumeration;
37
import java.util.StringTokenizer;
38

  
39
import org.gdal.gdal.gdal;
40
import org.gdal.gdal.ProgressCallback;
41
import org.gdal.gdal.TermProgressCallback;
42
import org.gdal.ogr.ogr;
43
import org.gdal.ogr.ogrConstants;
44
import org.gdal.ogr.Driver;
45
import org.gdal.ogr.DataSource;
46
import org.gdal.ogr.Layer;
47
import org.gdal.ogr.Feature;
48
import org.gdal.ogr.FeatureDefn;
49
import org.gdal.ogr.FieldDefn;
50
import org.gdal.ogr.Geometry;
51
import org.gdal.osr.SpatialReference;
52
import org.gdal.osr.CoordinateTransformation;
53

  
54
/* Note : this is the most direct port of ogr2ogr.cpp possible */
55
/* It could be made much more java'ish ! */
56

  
57
class GDALScaledProgress extends ProgressCallback
58
{
59
    private double pctMin;
60
    private double pctMax;
61
    private ProgressCallback mainCbk;
62

  
63
    public GDALScaledProgress(double pctMin, double pctMax,
64
                              ProgressCallback mainCbk)
65
    {
66
        this.pctMin = pctMin;
67
        this.pctMax = pctMax;
68
        this.mainCbk = mainCbk;
69
    }
70

  
71
    public int run(double dfComplete, String message)
72
    {
73
        return mainCbk.run(pctMin + dfComplete * (pctMax - pctMin), message);
74
    }
75
};
76

  
77

  
78
public class ogr2ogr
79
{
80
    static boolean bSkipFailures = false;
81
    static int nGroupTransactions = 200;
82
    static boolean bPreserveFID = false;
83
    static final int OGRNullFID = -1;
84
    static int nFIDToFetch = OGRNullFID;
85

  
86
    static class GeomOperation
87
    {
88
        private GeomOperation() {}
89
        public static GeomOperation NONE = new GeomOperation();
90
        public static GeomOperation SEGMENTIZE = new GeomOperation();
91
        public static GeomOperation SIMPLIFY_PRESERVE_TOPOLOGY = new GeomOperation();
92
    }
93

  
94
/************************************************************************/
95
/*                                main()                                */
96
/************************************************************************/
97

  
98
    public static void main(String[] args)
99
    {
100
        String pszFormat = "ESRI Shapefile";
101
        String pszDataSource = null;
102
        String pszDestDataSource = null;
103
        Vector papszLayers = new Vector();
104
        Vector papszDSCO = new Vector(), papszLCO = new Vector();
105
        boolean bTransform = false;
106
        boolean bAppend = false, bUpdate = false, bOverwrite = false;
107
        String pszOutputSRSDef = null;
108
        String pszSourceSRSDef = null;
109
        SpatialReference poOutputSRS = null;
110
        SpatialReference poSourceSRS = null;
111
        String pszNewLayerName = null;
112
        String pszWHERE = null;
113
        Geometry poSpatialFilter = null;
114
        String pszSelect;
115
        Vector papszSelFields = null;
116
        String pszSQLStatement = null;
117
        int    eGType = -2;
118
        GeomOperation eGeomOp = GeomOperation.NONE;
119
        double dfGeomOpParam = 0;
120
        Vector papszFieldTypesToString = new Vector();
121
        boolean bDisplayProgress = false;
122
        ProgressCallback pfnProgress = null;
123
        boolean  bClipSrc = false;
124
        Geometry poClipSrc = null;
125
        String pszClipSrcDS = null;
126
        String pszClipSrcSQL = null;
127
        String pszClipSrcLayer = null;
128
        String pszClipSrcWhere = null;
129
        Geometry poClipDst = null;
130
        String pszClipDstDS = null;
131
        String pszClipDstSQL = null;
132
        String pszClipDstLayer = null;
133
        String pszClipDstWhere = null;
134
        String pszSrcEncoding = null;
135
        String pszDstEncoding = null;
136
        boolean bExplodeCollections = false;
137
        String pszZField = null;
138

  
139
        ogr.DontUseExceptions();
140

  
141
    /* -------------------------------------------------------------------- */
142
    /*      Register format(s).                                             */
143
    /* -------------------------------------------------------------------- */
144
        if( ogr.GetDriverCount() == 0 )
145
            ogr.RegisterAll();
146

  
147
    /* -------------------------------------------------------------------- */
148
    /*      Processing command line arguments.                              */
149
    /* -------------------------------------------------------------------- */
150
        args = ogr.GeneralCmdLineProcessor( args );
151

  
152
        if( args.length < 2 )
153
        {
154
            Usage();
155
            System.exit( -1 );
156
        }
157

  
158
        for( int iArg = 0; iArg < args.length; iArg++ )
159
        {
160
            if( args[iArg].equalsIgnoreCase("-f") && iArg < args.length-1 )
161
            {
162
                pszFormat = args[++iArg];
163
            }
164
            else if( args[iArg].equalsIgnoreCase("-dsco") && iArg < args.length-1 )
165
            {
166
                papszDSCO.addElement(args[++iArg] );
167
            }
168
            else if( args[iArg].equalsIgnoreCase("-lco") && iArg < args.length-1 )
169
            {
170
                papszLCO.addElement(args[++iArg] );
171
            }
172
            else if( args[iArg].equalsIgnoreCase("-preserve_fid") )
173
            {
174
                bPreserveFID = true;
175
            }
176
            else if( args[iArg].length() >= 5 && args[iArg].substring(0, 5).equalsIgnoreCase("-skip") )
177
            {
178
                bSkipFailures = true;
179
                nGroupTransactions = 1; /* #2409 */
180
            }
181
            else if( args[iArg].equalsIgnoreCase("-append") )
182
            {
183
                bAppend = true;
184
                bUpdate = true;
185
            }
186
            else if( args[iArg].equalsIgnoreCase("-overwrite") )
187
            {
188
                bOverwrite = true;
189
                bUpdate = true;
190
            }
191
            else if( args[iArg].equalsIgnoreCase("-update") )
192
            {
193
                bUpdate = true;
194
            }
195
            else if( args[iArg].equalsIgnoreCase("-fid") && args[iArg+1] != null )
196
            {
197
                nFIDToFetch = Integer.parseInt(args[++iArg]);
198
            }
199
            else if( args[iArg].equalsIgnoreCase("-sql") && args[iArg+1] != null )
200
            {
201
                pszSQLStatement = args[++iArg];
202
            }
203
            else if( args[iArg].equalsIgnoreCase("-nln") && iArg < args.length-1 )
204
            {
205
                pszNewLayerName = args[++iArg];
206
            }
207
            else if( args[iArg].equalsIgnoreCase("-nlt") && iArg < args.length-1 )
208
            {
209
                if( args[iArg+1].equalsIgnoreCase("NONE") )
210
                    eGType = ogr.wkbNone;
211
                else if( args[iArg+1].equalsIgnoreCase("GEOMETRY") )
212
                    eGType = ogr.wkbUnknown;
213
                else if( args[iArg+1].equalsIgnoreCase("POINT") )
214
                    eGType = ogr.wkbPoint;
215
                else if( args[iArg+1].equalsIgnoreCase("LINESTRING") )
216
                    eGType = ogr.wkbLineString;
217
                else if( args[iArg+1].equalsIgnoreCase("POLYGON") )
218
                    eGType = ogr.wkbPolygon;
219
                else if( args[iArg+1].equalsIgnoreCase("GEOMETRYCOLLECTION") )
220
                    eGType = ogr.wkbGeometryCollection;
221
                else if( args[iArg+1].equalsIgnoreCase("MULTIPOINT") )
222
                    eGType = ogr.wkbMultiPoint;
223
                else if( args[iArg+1].equalsIgnoreCase("MULTILINESTRING") )
224
                    eGType = ogr.wkbMultiLineString;
225
                else if( args[iArg+1].equalsIgnoreCase("MULTIPOLYGON") )
226
                    eGType = ogr.wkbMultiPolygon;
227
                else if( args[iArg+1].equalsIgnoreCase("GEOMETRY25D") )
228
                    eGType = ogr.wkbUnknown | ogr.wkb25DBit;
229
                else if( args[iArg+1].equalsIgnoreCase("POINT25D") )
230
                    eGType = ogr.wkbPoint25D;
231
                else if( args[iArg+1].equalsIgnoreCase("LINESTRING25D") )
232
                    eGType = ogr.wkbLineString25D;
233
                else if( args[iArg+1].equalsIgnoreCase("POLYGON25D") )
234
                    eGType = ogr.wkbPolygon25D;
235
                else if( args[iArg+1].equalsIgnoreCase("GEOMETRYCOLLECTION25D") )
236
                    eGType = ogr.wkbGeometryCollection25D;
237
                else if( args[iArg+1].equalsIgnoreCase("MULTIPOINT25D") )
238
                    eGType = ogr.wkbMultiPoint25D;
239
                else if( args[iArg+1].equalsIgnoreCase("MULTILINESTRING25D") )
240
                    eGType = ogr.wkbMultiLineString25D;
241
                else if( args[iArg+1].equalsIgnoreCase("MULTIPOLYGON25D") )
242
                    eGType = ogr.wkbMultiPolygon25D;
243
                else
244
                {
245
                    System.err.println("-nlt " + args[iArg+1] + ": type not recognised.");
246
                    System.exit( 1 );
247
                }
248
                iArg++;
249
            }
250
            else if( (args[iArg].equalsIgnoreCase("-tg") ||
251
                    args[iArg].equalsIgnoreCase("-gt")) && iArg < args.length-1 )
252
            {
253
                nGroupTransactions = Integer.parseInt(args[++iArg]);
254
            }
255
            else if( args[iArg].equalsIgnoreCase("-s_srs") && iArg < args.length-1 )
256
            {
257
                pszSourceSRSDef = args[++iArg];
258
            }
259
            else if( args[iArg].equalsIgnoreCase("-a_srs") && iArg < args.length-1 )
260
            {
261
                pszOutputSRSDef = args[++iArg];
262
            }
263
            else if( args[iArg].equalsIgnoreCase("-t_srs") && iArg < args.length-1 )
264
            {
265
                pszOutputSRSDef = args[++iArg];
266
                bTransform = true;
267
            }
268
            else if (args[iArg].equalsIgnoreCase("-spat") && iArg + 4 < args.length)
269
            {
270
                Geometry oRing = new Geometry(ogrConstants.wkbLinearRing);
271
                double xmin = new Double(args[++iArg]).doubleValue();
272
                double ymin = new Double(args[++iArg]).doubleValue();
273
                double xmax = new Double(args[++iArg]).doubleValue();
274
                double ymax = new Double(args[++iArg]).doubleValue();
275
                oRing.AddPoint(xmin, ymin);
276
                oRing.AddPoint(xmin, ymax);
277
                oRing.AddPoint(xmax, ymax);
278
                oRing.AddPoint(xmax, ymin);
279
                oRing.AddPoint(xmin, ymin);
280

  
281
                poSpatialFilter = new Geometry(ogrConstants.wkbPolygon);
282
                poSpatialFilter.AddGeometry(oRing);
283
            }
284
            else if( args[iArg].equalsIgnoreCase("-where") && args[iArg+1] != null )
285
            {
286
                pszWHERE = args[++iArg];
287
            }
288
            else if( args[iArg].equalsIgnoreCase("-select") && args[iArg+1] != null)
289
            {
290
                pszSelect = args[++iArg];
291
                StringTokenizer tokenizer = new StringTokenizer(pszSelect, " ,");
292
                papszSelFields = new Vector();
293
                while(tokenizer.hasMoreElements())
294
                    papszSelFields.addElement(tokenizer.nextToken());
295
            }
296
            else if( args[iArg].equalsIgnoreCase("-simplify") && iArg < args.length-1 )
297
            {
298
                eGeomOp = GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY;
299
                dfGeomOpParam = new Double(args[++iArg]).doubleValue();
300
            }
301
            else if( args[iArg].equalsIgnoreCase("-segmentize") && iArg < args.length-1 )
302
            {
303
                eGeomOp = GeomOperation.SEGMENTIZE;
304
                dfGeomOpParam = new Double(args[++iArg]).doubleValue();
305
            }
306
            else if( args[iArg].equalsIgnoreCase("-fieldTypeToString") && iArg < args.length-1 )
307
            {
308
                StringTokenizer tokenizer = new StringTokenizer(args[++iArg], " ,");
309
                while(tokenizer.hasMoreElements())
310
                {
311
                    String token = (String)tokenizer.nextToken();
312
                    if (token.equalsIgnoreCase("Integer") ||
313
                        token.equalsIgnoreCase("Real") ||
314
                        token.equalsIgnoreCase("String") ||
315
                        token.equalsIgnoreCase("Date") ||
316
                        token.equalsIgnoreCase("Time") ||
317
                        token.equalsIgnoreCase("DateTime") ||
318
                        token.equalsIgnoreCase("Binary") ||
319
                        token.equalsIgnoreCase("IntegerList") ||
320
                        token.equalsIgnoreCase("RealList") ||
321
                        token.equalsIgnoreCase("StringList"))
322
                    {
323
                        papszFieldTypesToString.addElement(token);
324
                    }
325
                    else if (token.equalsIgnoreCase("All"))
326
                    {
327
                        papszFieldTypesToString = null;
328
                        papszFieldTypesToString.addElement("All");
329
                        break;
330
                    }
331
                    else
332
                    {
333
                        System.err.println("Unhandled type for fieldtypeasstring option : " + token);
334
                        Usage();
335
                    }
336
                }
337
            }
338
            else if( args[iArg].equalsIgnoreCase("-progress") )
339
            {
340
                bDisplayProgress = true;
341
            }
342
            /*else if( args[iArg].equalsIgnoreCase("-wrapdateline") )
343
            {
344
                bWrapDateline = true;
345
            }
346
            */
347
            else if( args[iArg].equalsIgnoreCase("-clipsrc") && iArg < args.length-1 )
348
            {
349
                bClipSrc = true;
350
                if ( IsNumber(args[iArg+1]) && iArg < args.length - 4 )
351
                {
352
                    Geometry oRing = new Geometry(ogrConstants.wkbLinearRing);
353
                    double xmin = new Double(args[++iArg]).doubleValue();
354
                    double ymin = new Double(args[++iArg]).doubleValue();
355
                    double xmax = new Double(args[++iArg]).doubleValue();
356
                    double ymax = new Double(args[++iArg]).doubleValue();
357
                    oRing.AddPoint(xmin, ymin);
358
                    oRing.AddPoint(xmin, ymax);
359
                    oRing.AddPoint(xmax, ymax);
360
                    oRing.AddPoint(xmax, ymin);
361
                    oRing.AddPoint(xmin, ymin);
362

  
363
                    poClipSrc = new Geometry(ogrConstants.wkbPolygon);
364
                    poClipSrc.AddGeometry(oRing);
365
                }
366
                else if( (args[iArg+1].length() >= 7 && args[iArg+1].substring(0, 7).equalsIgnoreCase("POLYGON") ) ||
367
                         (args[iArg+1].length() >= 12 && args[iArg+1].substring(0, 12).equalsIgnoreCase("MULTIPOLYGON") ) )
368
                {
369
                    poClipSrc = Geometry.CreateFromWkt(args[iArg+1]);
370
                    if (poClipSrc == null)
371
                    {
372
                        System.err.print("FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
373
                        Usage();
374
                    }
375
                    iArg ++;
376
                }
377
                else if (args[iArg+1].equalsIgnoreCase("spat_extent") )
378
                {
379
                    iArg ++;
380
                }
381
                else
382
                {
383
                    pszClipSrcDS = args[iArg+1];
384
                    iArg ++;
385
                }
386
            }
387
            else if( args[iArg].equalsIgnoreCase("-clipsrcsql") && iArg < args.length-1 )
388
            {
389
                pszClipSrcSQL = args[iArg+1];
390
                iArg ++;
391
            }
392
            else if( args[iArg].equalsIgnoreCase("-clipsrclayer") && iArg < args.length-1 )
393
            {
394
                pszClipSrcLayer = args[iArg+1];
395
                iArg ++;
396
            }
397
            else if( args[iArg].equalsIgnoreCase("-clipsrcwhere") && iArg < args.length-1 )
398
            {
399
                pszClipSrcWhere = args[iArg+1];
400
                iArg ++;
401
            }
402
            else if( args[iArg].equalsIgnoreCase("-clipdst") && iArg < args.length-1 )
403
            {
404
                if ( IsNumber(args[iArg+1]) && iArg < args.length - 4 )
405
                {
406
                    Geometry oRing = new Geometry(ogrConstants.wkbLinearRing);
407
                    double xmin = new Double(args[++iArg]).doubleValue();
408
                    double ymin = new Double(args[++iArg]).doubleValue();
409
                    double xmax = new Double(args[++iArg]).doubleValue();
410
                    double ymax = new Double(args[++iArg]).doubleValue();
411
                    oRing.AddPoint(xmin, ymin);
412
                    oRing.AddPoint(xmin, ymax);
413
                    oRing.AddPoint(xmax, ymax);
414
                    oRing.AddPoint(xmax, ymin);
415
                    oRing.AddPoint(xmin, ymin);
416

  
417
                    poClipDst = new Geometry(ogrConstants.wkbPolygon);
418
                    poClipDst.AddGeometry(oRing);
419
                }
420
                else if( (args[iArg+1].length() >= 7 && args[iArg+1].substring(0, 7).equalsIgnoreCase("POLYGON") ) ||
421
                         (args[iArg+1].length() >= 12 && args[iArg+1].substring(0, 12).equalsIgnoreCase("MULTIPOLYGON") ) )
422
                {
423
                    poClipDst = Geometry.CreateFromWkt(args[iArg+1]);
424
                    if (poClipDst == null)
425
                    {
426
                        System.err.print("FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
427
                        Usage();
428
                    }
429
                    iArg ++;
430
                }
431
                else if (args[iArg+1].equalsIgnoreCase("spat_extent") )
432
                {
433
                    iArg ++;
434
                }
435
                else
436
                {
437
                    pszClipDstDS = args[iArg+1];
438
                    iArg ++;
439
                }
440
            }
441
            else if( args[iArg].equalsIgnoreCase("-clipdstsql") && iArg < args.length-1 )
442
            {
443
                pszClipDstSQL = args[iArg+1];
444
                iArg ++;
445
            }
446
            else if( args[iArg].equalsIgnoreCase("-clipdstlayer") && iArg < args.length-1 )
447
            {
448
                pszClipDstLayer = args[iArg+1];
449
                iArg ++;
450
            }
451
            else if( args[iArg].equalsIgnoreCase("-clipdstwhere") && iArg < args.length-1 )
452
            {
453
                pszClipDstWhere = args[iArg+1];
454
                iArg ++;
455
            }
456
            else if( args[iArg].equalsIgnoreCase("-explodecollections") )
457
            {
458
                bExplodeCollections = true;
459
            }
460
            else if( args[iArg].equalsIgnoreCase("-zfield") && iArg < args.length-1 )
461
            {
462
                pszZField = args[iArg+1];
463
                iArg ++;
464
            }
465
            else if( args[iArg].charAt(0) == '-' )
466
            {
467
                Usage();
468
            }
469
            else if( pszDestDataSource == null )
470
                pszDestDataSource = args[iArg];
471
            else if( pszDataSource == null )
472
                pszDataSource = args[iArg];
473
            else
474
                papszLayers.addElement (args[iArg] );
475
        }
476

  
477
        if( pszDataSource == null )
478
            Usage();
479

  
480
        if( bPreserveFID && bExplodeCollections )
481
        {
482
            System.err.print("FAILURE: cannot use -preserve_fid and -explodecollections at the same time\n\n" );
483
            Usage();
484
        }
485

  
486
        if( bClipSrc && pszClipSrcDS != null)
487
        {
488
            poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
489
            if (poClipSrc == null)
490
            {
491
                System.err.print("FAILURE: cannot load source clip geometry\n\n" );
492
                Usage();
493
            }
494
        }
495
        else if( bClipSrc && poClipSrc == null )
496
        {
497
            if (poSpatialFilter != null)
498
                poClipSrc = poSpatialFilter.Clone();
499
            if (poClipSrc == null)
500
            {
501
                System.err.print("FAILURE: -clipsrc must be used with -spat option or a\n" +
502
                                "bounding box, WKT string or datasource must be specified\n\n");
503
                Usage();
504
            }
505
        }
506

  
507
        if( pszClipDstDS != null)
508
        {
509
            poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
510
            if (poClipDst == null)
511
            {
512
                System.err.print("FAILURE: cannot load dest clip geometry\n\n" );
513
                Usage();
514
            }
515
        }
516
    /* -------------------------------------------------------------------- */
517
    /*      Open data source.                                               */
518
    /* -------------------------------------------------------------------- */
519
        DataSource poDS;
520

  
521
        poDS = ogr.Open( pszDataSource, false );
522

  
523
    /* -------------------------------------------------------------------- */
524
    /*      Report failure                                                  */
525
    /* -------------------------------------------------------------------- */
526
        if( poDS == null )
527
        {
528
            System.err.println("FAILURE:\n" +
529
                    "Unable to open datasource ` " + pszDataSource + "' with the following drivers.");
530

  
531
            for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
532
            {
533
                System.err.println("  . " + ogr.GetDriver(iDriver).GetName() );
534
            }
535

  
536
            System.exit( 1 );
537
        }
538

  
539
    /* -------------------------------------------------------------------- */
540
    /*      Try opening the output datasource as an existing, writable      */
541
    /* -------------------------------------------------------------------- */
542
        DataSource       poODS = null;
543
        Driver poDriver = null;
544

  
545
        if( bUpdate )
546
        {
547
            poODS = ogr.Open( pszDestDataSource, true );
548
            if( poODS == null )
549
            {
550
                if (bOverwrite || bAppend)
551
                {
552
                    poODS = ogr.Open( pszDestDataSource, false );
553
                    if ( poODS == null )
554
                    {
555
                        /* ok the datasource doesn't exist at all */
556
                        bUpdate = false;
557
                    }
558
                    else
559
                    {
560
                        poODS.delete();
561
                        poODS = null;
562
                    }
563
                }
564

  
565
                if (bUpdate)
566
                {
567
                    System.err.println("FAILURE:\n" +
568
                            "Unable to open existing output datasource `" + pszDestDataSource + "'.");
569
                    System.exit( 1 );
570
                }
571
            }
572

  
573
            else if( papszDSCO.size() > 0 )
574
            {
575
                System.err.println("WARNING: Datasource creation options ignored since an existing datasource\n" +
576
                        "         being updated." );
577
            }
578

  
579
            if (poODS != null)
580
                poDriver = poODS.GetDriver();
581
        }
582

  
583
    /* -------------------------------------------------------------------- */
584
    /*      Find the output driver.                                         */
585
    /* -------------------------------------------------------------------- */
586
        if( !bUpdate )
587
        {
588
            int                  iDriver;
589

  
590
            poDriver = ogr.GetDriverByName(pszFormat);
591
            if( poDriver == null )
592
            {
593
                System.err.println("Unable to find driver `" + pszFormat +"'." );
594
                System.err.println( "The following drivers are available:" );
595

  
596
                for( iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
597
                {
598
                    System.err.println("  . " + ogr.GetDriver(iDriver).GetName() );
599
                }
600
                System.exit( 1 );
601
            }
602

  
603
            if( poDriver.TestCapability( ogr.ODrCCreateDataSource ) == false )
604
            {
605
                System.err.println( pszFormat + " driver does not support data source creation.");
606
                System.exit( 1 );
607
            }
608

  
609
    /* -------------------------------------------------------------------- */
610
    /*      Special case to improve user experience when translating        */
611
    /*      a datasource with multiple layers into a shapefile. If the      */
612
    /*      user gives a target datasource with .shp and it does not exist, */
613
    /*      the shapefile driver will try to create a file, but this is not */
614
    /*      appropriate because here we have several layers, so create      */
615
    /*      a directory instead.                                            */
616
    /* -------------------------------------------------------------------- */
617
            if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
618
                pszSQLStatement == null &&
619
                (papszLayers.size() > 1 ||
620
                 (papszLayers.size() == 0 && poDS.GetLayerCount() > 1)) &&
621
                pszNewLayerName == null &&
622
                (pszDestDataSource.endsWith(".shp") || pszDestDataSource.endsWith(".SHP")))
623
            {
624
                File f = new File(pszDestDataSource);
625
                if (!f.exists())
626
                {
627
                    if (!f.mkdir())
628
                    {
629
                        System.err.println(
630
                            "Failed to create directory " + pszDestDataSource + "\n" +
631
                            "for shapefile datastore.");
632
                        System.exit(1);
633
                    }
634
                }
635
            }
636

  
637
    /* -------------------------------------------------------------------- */
638
    /*      Create the output data source.                                  */
639
    /* -------------------------------------------------------------------- */
640
            poODS = poDriver.CreateDataSource( pszDestDataSource, papszDSCO );
641
            if( poODS == null )
642
            {
643
                System.err.println( pszFormat + " driver failed to create "+ pszDestDataSource );
644
                System.exit( 1 );
645
            }
646
        }
647

  
648
    /* -------------------------------------------------------------------- */
649
    /*      Parse the output SRS definition if possible.                    */
650
    /* -------------------------------------------------------------------- */
651
        if( pszOutputSRSDef != null )
652
        {
653
            poOutputSRS = new SpatialReference();
654
            if( poOutputSRS.SetFromUserInput( pszOutputSRSDef ) != 0 )
655
            {
656
                System.err.println( "Failed to process SRS definition: " + pszOutputSRSDef );
657
                System.exit( 1 );
658
            }
659
        }
660

  
661
    /* -------------------------------------------------------------------- */
662
    /*      Parse the source SRS definition if possible.                    */
663
    /* -------------------------------------------------------------------- */
664
        if( pszSourceSRSDef != null )
665
        {
666
            poSourceSRS = new SpatialReference();
667
            if( poSourceSRS.SetFromUserInput( pszSourceSRSDef ) != 0 )
668
            {
669
                System.err.println( "Failed to process SRS definition: " + pszSourceSRSDef );
670
                System.exit( 1 );
671
            }
672
        }
673

  
674
    /* -------------------------------------------------------------------- */
675
    /*      Special case for -sql clause.  No source layers required.       */
676
    /* -------------------------------------------------------------------- */
677
        if( pszSQLStatement != null )
678
        {
679
            Layer poResultSet;
680

  
681
            if( pszWHERE != null )
682
                System.err.println( "-where clause ignored in combination with -sql." );
683
            if( papszLayers.size() > 0 )
684
                System.err.println( "layer names ignored in combination with -sql." );
685

  
686
            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter,
687
                                            null );
688

  
689
            if( poResultSet != null )
690
            {
691
                long nCountLayerFeatures = 0;
692
                if (bDisplayProgress)
693
                {
694
                    if (!poResultSet.TestCapability(ogr.OLCFastFeatureCount))
695
                    {
696
                        System.err.println( "Progress turned off as fast feature count is not available.");
697
                        bDisplayProgress = false;
698
                    }
699
                    else
700
                    {
701
                        nCountLayerFeatures = poResultSet.GetFeatureCount();
702
                        pfnProgress = new TermProgressCallback();
703
                    }
704
                }
705

  
706
/* -------------------------------------------------------------------- */
707
/*      Special case to improve user experience when translating into   */
708
/*      single file shapefile and source has only one layer, and that   */
709
/*      the layer name isn't specified                                  */
710
/* -------------------------------------------------------------------- */
711
                if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
712
                    pszNewLayerName == null)
713
                {
714
                    File f = new File(pszDestDataSource);
715
                    if (f.exists() && f.listFiles() == null)
716
                    {
717
                        pszNewLayerName = f.getName();
718
                        int posPoint = pszNewLayerName.lastIndexOf('.');
719
                        if (posPoint != -1)
720
                            pszNewLayerName = pszNewLayerName.substring(0, posPoint);
721
                    }
722
                }
723

  
724
                if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO,
725
                                    pszNewLayerName, bTransform, poOutputSRS,
726
                                    poSourceSRS, papszSelFields, bAppend, eGType,
727
                                    bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
728
                                    nCountLayerFeatures, poClipSrc, poClipDst, bExplodeCollections,
729
                                    pszZField, pszWHERE, pfnProgress ))
730
                {
731
                    System.err.println(
732
                            "Terminating translation prematurely after failed\n" +
733
                            "translation from sql statement." );
734

  
735
                    System.exit( 1 );
736
                }
737
                poDS.ReleaseResultSet( poResultSet );
738
            }
739
        }
740
        else
741
        {
742
            int nLayerCount = 0;
743
            Layer[] papoLayers = null;
744

  
745
    /* -------------------------------------------------------------------- */
746
    /*      Process each data source layer.                                 */
747
    /* -------------------------------------------------------------------- */
748
            if ( papszLayers.size() == 0)
749
            {
750
                nLayerCount = poDS.GetLayerCount();
751
                papoLayers = new Layer[nLayerCount];
752

  
753
                for( int iLayer = 0;
754
                    iLayer < nLayerCount;
755
                    iLayer++ )
756
                {
757
                    Layer        poLayer = poDS.GetLayer(iLayer);
758

  
759
                    if( poLayer == null )
760
                    {
761
                        System.err.println("FAILURE: Couldn't fetch advertised layer " + iLayer + "!");
762
                        System.exit( 1 );
763
                    }
764

  
765
                    papoLayers[iLayer] = poLayer;
766
                }
767
            }
768
    /* -------------------------------------------------------------------- */
769
    /*      Process specified data source layers.                           */
770
    /* -------------------------------------------------------------------- */
771
            else
772
            {
773
                nLayerCount = papszLayers.size();
774
                papoLayers = new Layer[nLayerCount];
775

  
776
                for( int iLayer = 0;
777
                    iLayer < papszLayers.size();
778
                    iLayer++ )
779
                {
780
                    Layer        poLayer = poDS.GetLayerByName((String)papszLayers.get(iLayer));
781

  
782
                    if( poLayer == null )
783
                    {
784
                        System.err.println("FAILURE: Couldn't fetch advertised layer " + (String)papszLayers.get(iLayer) + "!");
785
                        System.exit( 1 );
786
                    }
787

  
788
                    papoLayers[iLayer] = poLayer;
789
                }
790
            }
791

  
792
/* -------------------------------------------------------------------- */
793
/*      Special case to improve user experience when translating into   */
794
/*      single file shapefile and source has only one layer, and that   */
795
/*      the layer name isn't specified                                  */
796
/* -------------------------------------------------------------------- */
797
            if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
798
                nLayerCount == 1 && pszNewLayerName == null)
799
            {
800
                File f = new File(pszDestDataSource);
801
                if (f.exists() && f.listFiles() == null)
802
                {
803
                    pszNewLayerName = f.getName();
804
                    int posPoint = pszNewLayerName.lastIndexOf('.');
805
                    if (posPoint != -1)
806
                        pszNewLayerName = pszNewLayerName.substring(0, posPoint);
807
                }
808
            }
809

  
810
            long[] panLayerCountFeatures = new long[nLayerCount];
811
            long nCountLayersFeatures = 0;
812
            long nAccCountFeatures = 0;
813

  
814
            /* First pass to apply filters and count all features if necessary */
815
            for( int iLayer = 0;
816
                iLayer < nLayerCount;
817
                iLayer++ )
818
            {
819
                Layer        poLayer = papoLayers[iLayer];
820

  
821
                if( pszWHERE != null )
822
                {
823
                    if( poLayer.SetAttributeFilter( pszWHERE ) != ogr.OGRERR_NONE )
824
                    {
825
                        System.err.println("FAILURE: SetAttributeFilter(" + pszWHERE + ") failed.");
826
                        if (!bSkipFailures)
827
                            System.exit( 1 );
828
                    }
829
                }
830

  
831
                if( poSpatialFilter != null )
832
                    poLayer.SetSpatialFilter( poSpatialFilter );
833

  
834
                if (bDisplayProgress)
835
                {
836
                    if (!poLayer.TestCapability(ogr.OLCFastFeatureCount))
837
                    {
838
                        System.err.println("Progress turned off as fast feature count is not available.");
839
                        bDisplayProgress = false;
840
                    }
841
                    else
842
                    {
843
                        panLayerCountFeatures[iLayer] = poLayer.GetFeatureCount();
844
                        nCountLayersFeatures += panLayerCountFeatures[iLayer];
845
                    }
846
                }
847
            }
848

  
849
            /* Second pass to do the real job */
850
            for( int iLayer = 0;
851
                iLayer < nLayerCount;
852
                iLayer++ )
853
            {
854
                Layer        poLayer = papoLayers[iLayer];
855

  
856
                if (bDisplayProgress)
857
                {
858
                    pfnProgress = new GDALScaledProgress(
859
                            nAccCountFeatures * 1.0 / nCountLayersFeatures,
860
                            (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
861
                            new TermProgressCallback());
862
                }
863

  
864
                nAccCountFeatures += panLayerCountFeatures[iLayer];
865

  
866
                if( !TranslateLayer( poDS, poLayer, poODS, papszLCO,
867
                                    pszNewLayerName, bTransform, poOutputSRS,
868
                                    poSourceSRS, papszSelFields, bAppend, eGType,
869
                                    bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
870
                                    panLayerCountFeatures[iLayer], poClipSrc, poClipDst, bExplodeCollections,
871
                                    pszZField, pszWHERE, pfnProgress)
872
                    && !bSkipFailures )
873
                {
874
                    System.err.println(
875
                            "Terminating translation prematurely after failed\n" +
876
                            "translation of layer " + poLayer.GetLayerDefn().GetName() + " (use -skipfailures to skip errors)");
877

  
878
                    System.exit( 1 );
879
                }
880
            }
881
        }
882

  
883
    /* -------------------------------------------------------------------- */
884
    /*      Close down.                                                     */
885
    /* -------------------------------------------------------------------- */
886
        /* We must explicitly destroy the output dataset in order the file */
887
        /* to be properly closed ! */
888
        poODS.delete();
889
        poDS.delete();
890
    }
891

  
892
    /************************************************************************/
893
    /*                               Usage()                                */
894
    /************************************************************************/
895

  
896
    static void Usage()
897

  
898
    {
899
        System.out.print( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n" +
900
                "               [-select field_list] [-where restricted_where] \n" +
901
                "               [-progress] [-sql <sql statement>] \n" +
902
                "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n" +
903
                "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n" +
904
                "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n" +
905
                "               [-simplify tolerance]\n" +
906
                // "               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n" +
907
                "               [-fieldTypeToString All|(type1[,type2]*)] [-explodecollections]\n" +
908
                "               dst_datasource_name src_datasource_name\n" +
909
                "               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n" +
910
                "\n" +
911
                " -f format_name: output file format name, possible values are:\n");
912

  
913
        for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
914
        {
915
            Driver poDriver = ogr.GetDriver(iDriver);
916

  
917
            if( poDriver.TestCapability( ogr.ODrCCreateDataSource ) )
918
                System.out.print( "     -f \"" + poDriver.GetName() + "\"\n" );
919
        }
920

  
921
        System.out.print( " -append: Append to existing layer instead of creating new if it exists\n" +
922
                " -overwrite: delete the output layer and recreate it empty\n" +
923
                " -update: Open existing output datasource in update mode\n" +
924
                " -progress: Display progress on terminal. Only works if input layers have the \"fast feature count\" capability\n" +
925
                " -select field_list: Comma-delimited list of fields from input layer to\n" +
926
                "                     copy to the new layer (defaults to all)\n" +
927
                " -where restricted_where: Attribute query (like SQL WHERE)\n" +
928
                " -sql statement: Execute given SQL statement and save result.\n" +
929
                " -skipfailures: skip features or layers that fail to convert\n" +
930
                " -gt n: group n features per transaction (default 200)\n" +
931
                " -spat xmin ymin xmax ymax: spatial query extents\n" +
932
                " -simplify tolerance: distance tolerance for simplification.\n" +
933
                //" -segmentize max_dist: maximum distance between 2 nodes.\n" +
934
                //"                       Used to create intermediate points\n" +
935
                " -dsco NAME=VALUE: Dataset creation option (format specific)\n" +
936
                " -lco  NAME=VALUE: Layer creation option (format specific)\n" +
937
                " -nln name: Assign an alternate name to the new layer\n" +
938
                " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n" +
939
                "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n" +
940
                "      MULTIPOLYGON, or MULTILINESTRING.  Add \"25D\" for 3D layers.\n" +
941
                "      Default is type of source layer.\n" +
942
                " -fieldTypeToString type1,...: Converts fields of specified types to\n" +
943
                "      fields of type string in the new layer. Valid types are : \n" +
944
                "      Integer, Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n" +
945
                "      StringList. Special value All can be used to convert all fields to strings.\n");
946

  
947
        System.out.print(" -a_srs srs_def: Assign an output SRS\n" +
948
            " -t_srs srs_def: Reproject/transform to this SRS on output\n" +
949
            " -s_srs srs_def: Override source SRS\n" +
950
            "\n" +
951
            " Srs_def can be a full WKT definition (hard to escape properly),\n" +
952
            " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n" +
953
            " definition.\n" );
954

  
955
        System.exit( 1 );
956
    }
957

  
958
    static int CSLFindString(Vector v, String str)
959
    {
960
        int i = 0;
961
        Enumeration e = v.elements();
962
        while(e.hasMoreElements())
963
        {
964
            String strIter = (String)e.nextElement();
965
            if (strIter.equalsIgnoreCase(str))
966
                return i;
967
            i ++;
968
        }
969
        return -1;
970
    }
971

  
972
    static boolean IsNumber(String pszStr)
973
    {
974
        try
975
        {
976
            Double.parseDouble(pszStr);
977
            return true;
978
        }
979
        catch(Exception ex)
980
        {
981
            return false;
982
        }
983
    }
984

  
985
    static Geometry LoadGeometry( String pszDS,
986
                                  String pszSQL,
987
                                  String pszLyr,
988
                                  String pszWhere)
989
    {
990
        DataSource       poDS;
991
        Layer            poLyr;
992
        Feature          poFeat;
993
        Geometry         poGeom = null;
994

  
995
        poDS = ogr.Open( pszDS, false );
996
        if (poDS == null)
997
            return null;
998

  
999
        if (pszSQL != null)
1000
            poLyr = poDS.ExecuteSQL( pszSQL, null, null );
1001
        else if (pszLyr != null)
1002
            poLyr = poDS.GetLayerByName(pszLyr);
1003
        else
1004
            poLyr = poDS.GetLayer(0);
1005

  
1006
        if (poLyr == null)
1007
        {
1008
            System.err.print("Failed to identify source layer from datasource.\n");
1009
            poDS.delete();
1010
            return null;
1011
        }
1012

  
1013
        if (pszWhere != null)
1014
            poLyr.SetAttributeFilter(pszWhere);
1015

  
1016
        while ((poFeat = poLyr.GetNextFeature()) != null)
1017
        {
1018
            Geometry poSrcGeom = poFeat.GetGeometryRef();
1019
            if (poSrcGeom != null)
1020
            {
1021
                int eType = wkbFlatten(poSrcGeom.GetGeometryType());
1022

  
1023
                if (poGeom == null)
1024
                    poGeom = new Geometry( ogr.wkbMultiPolygon );
1025

  
1026
                if( eType == ogr.wkbPolygon )
1027
                    poGeom.AddGeometry( poSrcGeom );
1028
                else if( eType == ogr.wkbMultiPolygon )
1029
                {
1030
                    int iGeom;
1031
                    int nGeomCount = poSrcGeom.GetGeometryCount();
1032

  
1033
                    for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
1034
                    {
1035
                        poGeom.AddGeometry(poSrcGeom.GetGeometryRef(iGeom) );
1036
                    }
1037
                }
1038
                else
1039
                {
1040
                    System.err.print("ERROR: Geometry not of polygon type.\n" );
1041
                    if( pszSQL != null )
1042
                        poDS.ReleaseResultSet( poLyr );
1043
                    poDS.delete();
1044
                    return null;
1045
                }
1046
            }
1047
        }
1048

  
1049
        if( pszSQL != null )
1050
            poDS.ReleaseResultSet( poLyr );
1051
        poDS.delete();
1052

  
1053
        return poGeom;
1054
    }
1055

  
1056

  
1057
    static int wkbFlatten(int eType)
1058
    {
1059
        return eType & (~ogrConstants.wkb25DBit);
1060
    }
1061

  
1062
    /************************************************************************/
1063
    /*                               SetZ()                                 */
1064
    /************************************************************************/
1065
    static void SetZ (Geometry poGeom, double dfZ )
1066
    {
1067
        if (poGeom == null)
1068
            return;
1069
        switch (wkbFlatten(poGeom.GetGeometryType()))
1070
        {
1071
            case ogr.wkbPoint:
1072
                poGeom.SetPoint(0, poGeom.GetX(), poGeom.GetY(), dfZ);
1073
                break;
1074

  
1075
            case ogr.wkbLineString:
1076
            case ogr.wkbLinearRing:
1077
            {
1078
                int i;
1079
                for(i=0;i<poGeom.GetPointCount();i++)
1080
                    poGeom.SetPoint(i, poGeom.GetX(i), poGeom.GetY(i), dfZ);
1081
                break;
1082
            }
1083

  
1084
            case ogr.wkbPolygon:
1085
            case ogr.wkbMultiPoint:
1086
            case ogr.wkbMultiLineString:
1087
            case ogr.wkbMultiPolygon:
1088
            case ogr.wkbGeometryCollection:
1089
            {
1090
                int i;
1091
                for(i=0;i<poGeom.GetGeometryCount();i++)
1092
                    SetZ(poGeom.GetGeometryRef(i), dfZ);
1093
                break;
1094
            }
1095

  
1096
            default:
1097
                break;
1098
        }
1099
    }
1100

  
1101

  
1102
    /************************************************************************/
1103
    /*                           TranslateLayer()                           */
1104
    /************************************************************************/
1105

  
1106
    static boolean TranslateLayer( DataSource poSrcDS,
1107
                            Layer poSrcLayer,
1108
                            DataSource poDstDS,
1109
                            Vector papszLCO,
1110
                            String pszNewLayerName,
1111
                            boolean bTransform,
1112
                            SpatialReference poOutputSRS,
1113
                            SpatialReference poSourceSRS,
1114
                            Vector papszSelFields,
1115
                            boolean bAppend, int eGType, boolean bOverwrite,
1116
                            GeomOperation eGeomOp,
1117
                            double dfGeomOpParam,
1118
                            Vector papszFieldTypesToString,
1119
                            long nCountLayerFeatures,
1120
                            Geometry poClipSrc,
1121
                            Geometry poClipDst,
1122
                            boolean bExplodeCollections,
1123
                            String pszZField,
1124
                            String pszWHERE,
1125
                            ProgressCallback pfnProgress)
1126

  
1127
    {
1128
        Layer    poDstLayer;
1129
        FeatureDefn poSrcFDefn;
1130
        int      eErr;
1131
        boolean         bForceToPolygon = false;
1132
        boolean         bForceToMultiPolygon = false;
1133
        boolean         bForceToMultiLineString = false;
1134

  
1135
        if( pszNewLayerName == null )
1136
            pszNewLayerName = poSrcLayer.GetLayerDefn().GetName();
1137

  
1138
        if( wkbFlatten(eGType) == ogr.wkbPolygon )
1139
            bForceToPolygon = true;
1140
        else if( wkbFlatten(eGType) == ogr.wkbMultiPolygon )
1141
            bForceToMultiPolygon = true;
1142
        else if( wkbFlatten(eGType) == ogr.wkbMultiLineString )
1143
            bForceToMultiLineString = true;
1144

  
1145
    /* -------------------------------------------------------------------- */
1146
    /*      Setup coordinate transformation if we need it.                  */
1147
    /* -------------------------------------------------------------------- */
1148
        CoordinateTransformation poCT = null;
1149

  
1150
        if( bTransform )
1151
        {
1152
            if( poSourceSRS == null )
1153
                poSourceSRS = poSrcLayer.GetSpatialRef();
1154

  
1155
            if( poSourceSRS == null )
1156
            {
1157
                System.err.println("Can't transform coordinates, source layer has no\n" +
1158
                        "coordinate system.  Use -s_srs to set one." );
1159
                System.exit( 1 );
1160
            }
1161

  
1162
            /*CPLAssert( null != poSourceSRS );
1163
            CPLAssert( null != poOutputSRS );*/
1164

  
1165
            /* New in GDAL 1.10. Before was "new CoordinateTransformation(srs,dst)". */
1166
            poCT = CoordinateTransformation.CreateCoordinateTransformation( poSourceSRS, poOutputSRS );
1167
            if( poCT == null )
1168
            {
1169
                String pszWKT = null;
1170

  
1171
                System.err.println("Failed to create coordinate transformation between the\n" +
1172
                    "following coordinate systems.  This may be because they\n" +
1173
                    "are not transformable, or because projection services\n" +
1174
                    "(PROJ.4 DLL/.so) could not be loaded." );
1175

  
1176
                pszWKT = poSourceSRS.ExportToPrettyWkt( 0 );
1177
                System.err.println( "Source:\n" + pszWKT );
1178

  
1179
                pszWKT = poOutputSRS.ExportToPrettyWkt( 0 );
1180
                System.err.println( "Target:\n" + pszWKT );
1181
                System.exit( 1 );
1182
            }
1183
        }
1184

  
1185
    /* -------------------------------------------------------------------- */
1186
    /*      Get other info.                                                 */
1187
    /* -------------------------------------------------------------------- */
1188
        poSrcFDefn = poSrcLayer.GetLayerDefn();
1189

  
1190
        if( poOutputSRS == null )
1191
            poOutputSRS = poSrcLayer.GetSpatialRef();
1192

  
1193
    /* -------------------------------------------------------------------- */
1194
    /*      Find the layer.                                                 */
1195
    /* -------------------------------------------------------------------- */
1196

  
1197
        /* GetLayerByName() can instantiate layers that would have been */
1198
        /* 'hidden' otherwise, for example, non-spatial tables in a */
1199
        /* PostGIS-enabled database, so this apparently useless command is */
1200
        /* not useless. (#4012) */
1201
        gdal.PushErrorHandler("CPLQuietErrorHandler");
1202
        poDstLayer = poDstDS.GetLayerByName(pszNewLayerName);
1203
        gdal.PopErrorHandler();
1204
        gdal.ErrorReset();
1205

  
1206
        int iLayer = -1;
1207
        if( poDstLayer != null )
1208
        {
1209
            int nLayerCount = poDstDS.GetLayerCount();
1210
            for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
1211
            {
1212
                Layer        poLayer = poDstDS.GetLayer(iLayer);
1213

  
1214
                if( poLayer != null
1215
                    && poLayer.GetName().equals(poDstLayer.GetName()) )
1216
                {
1217
                    break;
1218
                }
1219
            }
1220

  
1221
            if (iLayer == nLayerCount)
1222
                /* shouldn't happen with an ideal driver */
1223
                poDstLayer = null;
1224
        }
1225

  
1226
    /* -------------------------------------------------------------------- */
1227
    /*      If the user requested overwrite, and we have the layer in       */
1228
    /*      question we need to delete it now so it will get recreated      */
1229
    /*      (overwritten).                                                  */
1230
    /* -------------------------------------------------------------------- */
1231
        if( poDstLayer != null && bOverwrite )
1232
        {
1233
            if( poDstDS.DeleteLayer( iLayer ) != 0 )
1234
            {
1235
                System.err.println(
1236
                        "DeleteLayer() failed when overwrite requested." );
1237
                return false;
1238
            }
1239
            poDstLayer = null;
1240
        }
1241

  
1242
    /* -------------------------------------------------------------------- */
1243
    /*      If the layer does not exist, then create it.                    */
1244
    /* -------------------------------------------------------------------- */
1245
        if( poDstLayer == null )
1246
        {
1247
            if( eGType == -2 )
1248
            {
1249
                eGType = poSrcFDefn.GetGeomType();
1250

  
1251
                if ( bExplodeCollections )
1252
                {
1253
                    int n25DBit = eGType & ogr.wkb25DBit;
1254
                    if (wkbFlatten(eGType) == ogr.wkbMultiPoint)
1255
                    {
1256
                        eGType = ogr.wkbPoint | n25DBit;
1257
                    }
1258
                    else if (wkbFlatten(eGType) == ogr.wkbMultiLineString)
1259
                    {
1260
                        eGType = ogr.wkbLineString | n25DBit;
1261
                    }
1262
                    else if (wkbFlatten(eGType) == ogr.wkbMultiPolygon)
1263
                    {
1264
                        eGType = ogr.wkbPolygon | n25DBit;
1265
                    }
1266
                    else if (wkbFlatten(eGType) == ogr.wkbGeometryCollection)
1267
                    {
1268
                        eGType = ogr.wkbUnknown | n25DBit;
1269
                    }
1270
                }
1271

  
1272
                if ( pszZField != null )
1273
                    eGType |= ogr.wkb25DBit;
1274
            }
1275

  
1276
            if( poDstDS.TestCapability( ogr.ODsCCreateLayer ) == false)
1277
            {
1278
                System.err.println(
1279
                "Layer " + pszNewLayerName + "not found, and CreateLayer not supported by driver.");
1280
                return false;
1281
            }
1282

  
1283
            gdal.ErrorReset();
1284

  
1285
            poDstLayer = poDstDS.CreateLayer( pszNewLayerName, poOutputSRS,
1286
                                              eGType, papszLCO );
1287

  
1288
            if( poDstLayer == null )
1289
                return false;
1290

  
1291
            bAppend = false;
1292
        }
1293

  
1294
    /* -------------------------------------------------------------------- */
1295
    /*      Otherwise we will append to it, if append was requested.        */
1296
    /* -------------------------------------------------------------------- */
1297
        else if( !bAppend )
1298
        {
1299
            System.err.println("FAILED: Layer " + pszNewLayerName + "already exists, and -append not specified.\n" +
1300
                                "        Consider using -append, or -overwrite.");
1301
            return false;
1302
        }
1303
        else
1304
        {
1305
            if( papszLCO.size() > 0 )
1306
            {
1307
                System.err.println("WARNING: Layer creation options ignored since an existing layer is\n" +
1308
                        "         being appended to." );
1309
            }
1310
        }
1311

  
1312
    /* -------------------------------------------------------------------- */
1313
    /*      Add fields.  Default to copy all field.                         */
1314
    /*      If only a subset of all fields requested, then output only      */
1315
    /*      the selected fields, and in the order that they were            */
1316
    /*      selected.                                                       */
1317
    /* -------------------------------------------------------------------- */
1318
        int         iField;
1319

  
1320
        /* Initialize the index-to-index map to -1's */
1321
        int nSrcFieldCount = poSrcFDefn.GetFieldCount();
1322
        int[] panMap = new int [nSrcFieldCount];
1323
        for( iField=0; iField < nSrcFieldCount; iField++)
1324
            panMap[iField] = -1;
1325

  
1326
        FeatureDefn poDstFDefn = poDstLayer.GetLayerDefn();
1327

  
1328
        if (papszSelFields != null && !bAppend )
1329
        {
1330
            int  nDstFieldCount = 0;
1331
            if (poDstFDefn != null)
1332
                nDstFieldCount = poDstFDefn.GetFieldCount();
1333

  
1334
            for( iField=0; iField < papszSelFields.size(); iField++)
1335
            {
1336
                int iSrcField = poSrcFDefn.GetFieldIndex((String)papszSelFields.get(iField));
1337
                if (iSrcField >= 0)
1338
                {
1339
                    FieldDefn poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iSrcField);
1340
                    FieldDefn oFieldDefn = new FieldDefn( poSrcFieldDefn.GetNameRef(),
1341
                                                poSrcFieldDefn.GetFieldType() );
1342
                    oFieldDefn.SetWidth( poSrcFieldDefn.GetWidth() );
1343
                    oFieldDefn.SetPrecision( poSrcFieldDefn.GetPrecision() );
1344

  
1345
                    if (papszFieldTypesToString != null &&
1346
                        (CSLFindString(papszFieldTypesToString, "All") != -1 ||
1347
                        CSLFindString(papszFieldTypesToString,
1348
                                    ogr.GetFieldTypeName(poSrcFDefn.GetFieldDefn(iSrcField).GetFieldType())) != -1))
1349
                        oFieldDefn.SetType(ogr.OFTString);
1350

  
1351
                    /* The field may have been already created at layer creation */
1352
                    int iDstField = -1;
1353
                    if (poDstFDefn != null)
1354
                        iDstField = poDstFDefn.GetFieldIndex(oFieldDefn.GetNameRef());
1355
                    if (iDstField >= 0)
1356
                    {
1357
                        panMap[iSrcField] = iDstField;
1358
                    }
1359
                    else if (poDstLayer.CreateField( oFieldDefn ) == 0)
1360
                    {
1361
                        /* now that we've created a field, GetLayerDefn() won't return NULL */
1362
                        if (poDstFDefn == null)
1363
                            poDstFDefn = poDstLayer.GetLayerDefn();
1364

  
1365
                        /* Sanity check : if it fails, the driver is buggy */
1366
                        if (poDstFDefn != null &&
1367
                            poDstFDefn.GetFieldCount() != nDstFieldCount + 1)
1368
                        {
1369
                            System.err.println(
1370
                                    "The output driver has claimed to have added the " + oFieldDefn.GetNameRef() + " field, but it did not!");
1371
                        }
1372
                        else
1373
                        {
1374
                            panMap[iSrcField] = nDstFieldCount;
1375
                            nDstFieldCount ++;
1376
                        }
1377
                    }
1378

  
1379
                }
1380
                else
1381
                {
1382
                    System.err.println("Field '" + (String)papszSelFields.get(iField) + "' not found in source layer.");
1383
                        if( !bSkipFailures )
1384
                            return false;
1385
                }
1386
            }
1387

  
1388
            /* -------------------------------------------------------------------- */
1389
            /* Use SetIgnoredFields() on source layer if available                  */
1390
            /* -------------------------------------------------------------------- */
1391

  
1392
            /* Here we differ from the ogr2ogr.cpp implementation since the OGRFeatureQuery */
1393
            /* isn't mapped to swig. So in that case just don't use SetIgnoredFields() */
1394
            /* to avoid issue raised in #4015 */
1395
            if (poSrcLayer.TestCapability(ogr.OLCIgnoreFields) && pszWHERE == null)
1396
            {
1397
                int iSrcField;
1398
                Vector papszIgnoredFields = new Vector();
1399
                for(iSrcField=0;iSrcField<nSrcFieldCount;iSrcField++)
1400
                {
1401
                    String pszFieldName =
1402
                        poSrcFDefn.GetFieldDefn(iSrcField).GetNameRef();
1403
                    boolean bFieldRequested = false;
1404
                    for( iField=0; iField < papszSelFields.size(); iField++)
1405
                    {
1406
                        if (pszFieldName.equalsIgnoreCase((String)papszSelFields.get(iField)))
1407
                        {
1408
                            bFieldRequested = true;
1409
                            break;
1410
                        }
1411
                    }
1412

  
1413
                    if (pszZField != null && pszFieldName.equalsIgnoreCase(pszZField))
1414
                        bFieldRequested = true;
1415

  
1416
                    /* If source field not requested, add it to ignored files list */
1417
                    if (!bFieldRequested)
1418
                        papszIgnoredFields.addElement(pszFieldName);
1419
                }
1420
                poSrcLayer.SetIgnoredFields(papszIgnoredFields);
1421
            }
1422
        }
1423
        else if( !bAppend )
1424
        {
1425
            int nDstFieldCount = 0;
1426
            if (poDstFDefn != null)
1427
                nDstFieldCount = poDstFDefn.GetFieldCount();
1428
            for( iField = 0; iField < nSrcFieldCount; iField++ )
1429
            {
1430
                FieldDefn poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iField);
1431
                FieldDefn oFieldDefn = new FieldDefn( poSrcFieldDefn.GetNameRef(),
1432
                                            poSrcFieldDefn.GetFieldType() );
1433
                oFieldDefn.SetWidth( poSrcFieldDefn.GetWidth() );
1434
                oFieldDefn.SetPrecision( poSrcFieldDefn.GetPrecision() );
1435

  
1436
                if (papszFieldTypesToString != null &&
1437
                    (CSLFindString(papszFieldTypesToString, "All") != -1 ||
1438
                    CSLFindString(papszFieldTypesToString,
1439
                                ogr.GetFieldTypeName(poSrcFDefn.GetFieldDefn(iField).GetFieldType())) != -1))
1440
                    oFieldDefn.SetType(ogr.OFTString);
1441

  
1442
                /* The field may have been already created at layer creation */
1443
                int iDstField = -1;
1444
                if (poDstFDefn != null)
1445
                    iDstField = poDstFDefn.GetFieldIndex(oFieldDefn.GetNameRef());
1446
                if (iDstField >= 0)
1447
                {
1448
                    panMap[iField] = iDstField;
1449
                }
1450
                else if (poDstLayer.CreateField( oFieldDefn ) == 0)
1451
                {
1452
                    /* now that we've created a field, GetLayerDefn() won't return NULL */
1453
                    if (poDstFDefn == null)
1454
                        poDstFDefn = poDstLayer.GetLayerDefn();
1455

  
1456
                    /* Sanity check : if it fails, the driver is buggy */
1457
                    if (poDstFDefn != null &&
1458
                        poDstFDefn.GetFieldCount() != nDstFieldCount + 1)
1459
                    {
1460
                        System.err.println(
1461
                                "The output driver has claimed to have added the " + oFieldDefn.GetNameRef() + " field, but it did not!");
1462
                    }
1463
                    else
1464
                    {
1465
                        panMap[iField] = nDstFieldCount;
1466
                        nDstFieldCount ++;
1467
                    }
1468
                }
1469
            }
1470
        }
1471
        else
1472
        {
1473
            /* For an existing layer, build the map by fetching the index in the destination */
1474
            /* layer for each source field */
1475
            if (poDstFDefn == null)
1476
            {
1477
                System.err.println("poDstFDefn == NULL.\n" );
1478
                return false;
1479
            }
1480

  
1481
            for( iField = 0; iField < nSrcFieldCount; iField++ )
1482
            {
1483
                FieldDefn poSrcFieldDefn = poSrcFDefn.GetFieldDefn(iField);
1484
                int iDstField = poDstFDefn.GetFieldIndex(poSrcFieldDefn.GetNameRef());
1485
                if (iDstField >= 0)
1486
                    panMap[iField] = iDstField;
1487
            }
1488
        }
1489

  
1490
    /* -------------------------------------------------------------------- */
1491
    /*      Transfer features.                                              */
1492
    /* -------------------------------------------------------------------- */
1493
        Feature  poFeature;
1494
        int         nFeaturesInTransaction = 0;
1495
        long        nCount = 0;
1496

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff