Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.exportto / org.gvsig.exportto.swing / org.gvsig.exportto.swing.prov / org.gvsig.exportto.swing.prov.shape / src / main / java / org / gvsig / export / shape / service / ExportShapeService.java @ 44386

History | View | Annotate | Download (24 KB)

1
package org.gvsig.export.shape.service;
2

    
3
import java.io.File;
4
import java.util.ArrayList;
5
import java.util.List;
6
import org.apache.commons.io.FilenameUtils;
7
import org.cresques.cts.ICoordTrans;
8
import org.cresques.cts.IProjection;
9
import org.gvsig.export.ExportException;
10
import org.gvsig.export.spi.AbstractExportService;
11
import org.gvsig.export.spi.ExportService;
12
import org.gvsig.export.spi.ExportServiceFactory;
13
import org.gvsig.fmap.dal.DALLocator;
14
import org.gvsig.fmap.dal.DataManager;
15
import org.gvsig.fmap.dal.DataServerExplorer;
16
import org.gvsig.fmap.dal.NewDataStoreParameters;
17
import org.gvsig.fmap.dal.OpenDataStoreParameters;
18
import org.gvsig.fmap.dal.exception.DataException;
19
import org.gvsig.fmap.dal.feature.EditableFeature;
20
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
21
import org.gvsig.fmap.dal.feature.EditableFeatureType;
22
import org.gvsig.fmap.dal.feature.Feature;
23
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
24
import org.gvsig.fmap.dal.feature.FeatureSet;
25
import org.gvsig.fmap.dal.feature.FeatureStore;
26
import org.gvsig.fmap.dal.feature.FeatureType;
27
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
28
import org.gvsig.fmap.dal.feature.OpenFeatureStoreParameters;
29
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
30
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
31
import org.gvsig.fmap.geom.DataTypes;
32
import org.gvsig.fmap.geom.Geometry;
33
import org.gvsig.fmap.geom.GeometryLocator;
34
import org.gvsig.fmap.geom.GeometryManager;
35
import org.gvsig.fmap.geom.aggregate.Aggregate;
36
import org.gvsig.fmap.geom.exception.CreateGeometryException;
37
import org.gvsig.fmap.geom.operation.GeometryOperationException;
38
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
39
import org.gvsig.fmap.geom.primitive.Curve;
40
import org.gvsig.fmap.geom.primitive.Line;
41
import org.gvsig.fmap.geom.primitive.OrientablePrimitive;
42
import org.gvsig.fmap.geom.primitive.Point;
43
import org.gvsig.fmap.geom.primitive.Polygon;
44
import org.gvsig.fmap.geom.primitive.Surface;
45
import org.gvsig.fmap.geom.type.GeometryType;
46
import org.gvsig.tools.ToolsLocator;
47
import org.gvsig.tools.dataTypes.CoercionException;
48
import org.gvsig.tools.dataTypes.DataTypesManager;
49
import org.gvsig.tools.dispose.DisposableIterator;
50
import org.gvsig.tools.dispose.DisposeUtils;
51
import org.gvsig.tools.util.HasAFile;
52

    
53
/**
54
 *
55
 * @author jjdelcerro
56
 */
57
public class ExportShapeService
58
        extends AbstractExportService
59
        implements ExportService {
60

    
61
    public static final int MAX_FIELD_NAME_LENGTH = 10;
62

    
63
    private final List<OpenDataStoreParameters> targetOpenStoreParameters;
64

    
65
    public ExportShapeService(ExportServiceFactory factory, ExportShapeParameters parameters) {
66
        super(factory, parameters);
67
        this.targetOpenStoreParameters = new ArrayList<>();
68
    }
69

    
70
    @Override
71
    public ExportShapeParameters getParameters() {
72
        return (ExportShapeParameters) super.getParameters();
73
    }
74

    
75
    @Override
76
    protected DataServerExplorer createServerExplorer() throws ExportException {
77

    
78
        DataManager dataManager = DALLocator.getDataManager();
79

    
80
        FilesystemServerExplorerParameters explorerParams;
81
        try {
82
            explorerParams
83
                    = (FilesystemServerExplorerParameters) dataManager
84
                            .createServerExplorerParameters(FilesystemServerExplorer.NAME);
85
        } catch (Exception e) {
86
            throw new ExportException(e);
87
        }
88
        explorerParams.setRoot(this.getParameters().getFile().getParent());
89

    
90
        FilesystemServerExplorer explorer;
91
        try {
92
            explorer = (FilesystemServerExplorer) dataManager.openServerExplorer(
93
                    "FilesystemExplorer", explorerParams
94
            );
95
            return explorer;
96
        } catch (Exception e) {
97
            throw new ExportException(e);
98
        }
99
    }
100

    
101
    @Override
102
    protected NewDataStoreParameters createTargetNewStoreParameters() throws ExportException {
103
        try {
104
            FilesystemServerExplorer explorer = (FilesystemServerExplorer) this.createServerExplorer();
105
            NewFeatureStoreParameters newStoreParameters = (NewFeatureStoreParameters) explorer.getAddParameters(
106
                    this.getParameters().getFile()
107
            );
108
            newStoreParameters.setDynValue("Encoding", this.getParameters().getEncoding());
109
            newStoreParameters.setDynValue("CRS", this.getParameters().getTargetProjection());
110
            FeatureType ft;
111
            if (this.getParameters().getExportAttributes() != null) {
112
                ft = this.getParameters().getExportAttributes().getTargetFeatureType();
113

    
114
            } else {
115
                ft = this.getParameters().getSourceFeatureType();
116
            }
117

    
118
            // FIXME: check if ft has one and only one geometry.
119
            newStoreParameters.setDefaultFeatureType(ft.getEditable());
120
            return newStoreParameters;
121
        } catch (DataException ex) {
122
            throw new ExportException(ex);
123
        }
124
    }
125

    
126
    @Override
127
    public List<OpenDataStoreParameters> getTargetOpenStoreParameters() throws ExportException {
128
        return this.targetOpenStoreParameters;
129
    }
130

    
131
    @Override
132
    public OpenDataStoreParameters createTargetOpenStoreParameters() throws ExportException {
133
        try {
134
            DataManager dataManager = DALLocator.getDataManager();
135
            OpenFeatureStoreParameters openStoreParameters = (OpenFeatureStoreParameters) dataManager.createStoreParameters("Shape");
136
            ((HasAFile) openStoreParameters).setFile(getParameters().getFile());
137
            openStoreParameters.setDynValue("Encoding", getParameters().getEncoding());
138
            openStoreParameters.setDynValue("CRS", this.getParameters().getTargetProjection());
139
            return openStoreParameters;
140
        } catch (DataException ex) {
141
            throw new ExportException(ex);
142
        }
143
    }
144

    
145
    @Override
146
    public void export(FeatureSet featureSet) throws ExportException {
147

    
148
        File parametersFile = this.getParameters().getFile();
149
        String pathName = FilenameUtils.removeExtension(parametersFile.getAbsolutePath());
150

    
151
        int geometryType = this.getParameters().getTargetGeometryTypeAsInt();
152

    
153
        if (geometryType == Geometry.TYPES.GEOMETRY) {
154
            try {
155
                // SURFACE
156
                String fullPathName = pathName + "_surface" + ".shp";
157
                this.getParameters().setFile(new File(fullPathName));
158
                this.getTaskStatus().setTitle("Exporting surfaces");
159
                export(featureSet, Geometry.TYPES.SURFACE, true);
160

    
161
                // CURVE
162
                fullPathName = pathName + "_curve" + ".shp";
163
                this.getParameters().setFile(new File(fullPathName));
164
                this.getTaskStatus().setTitle("Exporting curves");
165
                export(featureSet, Geometry.TYPES.CURVE, true);
166

    
167
                // POINT
168
                fullPathName = pathName + "_point" + ".shp";
169
                this.getParameters().setFile(new File(fullPathName));
170
                this.getTaskStatus().setTitle("Exporting points");
171
                export(featureSet, Geometry.TYPES.POINT, true);
172

    
173
            } finally {
174
                this.getParameters().setFile(parametersFile);
175
            }
176

    
177
        } else {
178
            export(featureSet, geometryType, false);
179
        }
180

    
181
        this.getTaskStatus().terminate();
182
        this.getTaskStatus().remove();
183

    
184
    }
185

    
186
    private void export(
187
            FeatureSet featureSet,
188
            int geometryType,
189
            boolean checkType
190
    ) throws ExportException {
191

    
192
        DataServerExplorer explorer = this.createServerExplorer();
193
        NewFeatureStoreParameters params = (NewFeatureStoreParameters) this.createTargetNewStoreParameters();
194

    
195
        String providerName = params.getDataStoreName();
196
        String explorerName = explorer.getProviderName();
197
        boolean there_was_error = false;
198

    
199
        DisposableIterator it = null;
200
        try {
201
//            EditableFeatureType type = this.getParameters().getSourceFeatureType().getCopy().getEditable();
202
            EditableFeatureType type = params.getDefaultFeatureType();
203

    
204
            String geomFieldName = this.getParameters().getSourceGeometryFieldName();
205

    
206
            FeatureAttributeDescriptor geomFieldDescSource = (FeatureAttributeDescriptor) type.getDefaultGeometryAttribute();
207
            if (geomFieldDescSource != null) {
208
                type.remove(geomFieldDescSource.getName());
209
            }
210
            EditableFeatureAttributeDescriptor geomFieldDescTarget = type.add(
211
                    "GEOMETRY",
212
                    DataTypes.GEOMETRY
213
            );
214
            geomFieldDescTarget.setDefaultValue(null);
215
            int gsubtype = this.getParameters().getTargetGeometrySubtype();
216
            // El shp solo soporta los subtipos 2D y 3D
217
            switch (gsubtype) {
218
                case Geometry.SUBTYPES.GEOM2D:
219
                    break;
220
                case Geometry.SUBTYPES.GEOM3D:
221
                    break;
222
                default:
223
                    // Forzaremos las geometrias a 3D
224
                    gsubtype = Geometry.SUBTYPES.GEOM3D;
225
                    break;
226
            }
227
            GeometryType gty = null;
228
            try {
229
                GeometryManager geoManager = GeometryLocator.getGeometryManager();
230
                gty = geoManager.getGeometryType(geometryType, gsubtype);
231
            } catch (Exception e) {
232
                throw new ExportException(e);
233
            }
234

    
235
            geomFieldDescTarget.setGeometryType(gty);
236
            geomFieldDescTarget.setName(this.getParameters().getExportAttributes().getTargetName("GEOMETRY"));
237
            type.setDefaultGeometryAttributeName(geomFieldDescTarget.getName());
238

    
239
            // ==========================
240
            fixNames(type);
241
            // ==========================
242

    
243
            params.setDefaultFeatureType(type.getNotEditableCopy());
244

    
245
            params.setDynValue("geometryType", null);
246

    
247
            DataManager manager = DALLocator.getDataManager();
248

    
249
            manager.newStore(explorerName, providerName, params, true);
250

    
251
            FeatureStore target = (FeatureStore) manager.openStore(providerName, params);
252
            FeatureType targetType = target.getDefaultFeatureType();
253

    
254
            getTaskStatus().setRangeOfValues(0, featureSet.getSize());
255

    
256
            target.edit(FeatureStore.MODE_APPEND);
257
            it = featureSet.fastIterator();
258
            int featureCount = 0;
259

    
260
            // ================================================
261
            // Reprojection stuff
262
            Geometry reproj_geom;
263
            EditableFeature edit_feat;
264
            IProjection sourceProjection
265
                    = getParameters().getSourceFeatureType().getDefaultGeometryAttribute().getSRS();
266

    
267
            ICoordTrans coord_trans = null;
268
            // this comparison is perhaps too preventive
269
            // we could  have two instances of same projection
270
            // so we would do more computations than needed
271
            if (sourceProjection != null && sourceProjection != this.getParameters().getTargetProjection()) {
272
                if (this.getParameters().getTargetTransformation() != null) {
273
                    coord_trans = this.getParameters().getTargetTransformation();
274
                } else {
275
                    coord_trans = sourceProjection.getCT(this.getParameters().getTargetProjection());
276
                }
277
            }
278
            // ================================================
279

    
280
            List<Geometry> extracted;
281
            Geometry gitem;
282
            DataTypesManager.Coercion toGeometry = ToolsLocator.getDataTypesManager()
283
                    .get(DataTypes.GEOMETRY).getCoercion();
284

    
285
            while (it.hasNext()) {
286

    
287
                Feature feature = (Feature) it.next();
288
                if (geomFieldName == null) {
289
                    edit_feat = target.createNewFeature(true);
290
                    //
291
                    // Accumulate error in boolean.
292
                    // This also fixes field names (using origNameToDbfName)
293
                    // 
294
                    there_was_error = there_was_error
295
                            | setNonNulls(
296
                                    getParameters().getSourceFeatureType(),
297
                                    targetType,
298
                                    feature,
299
                                    edit_feat
300
                            );
301
                    edit_feat.setDefaultGeometry(null);
302
                    target.insert(edit_feat);
303
                } else {
304
                    Object x = feature.getGeometry(geomFieldName);
305
                    try {
306
                        gitem = (Geometry) toGeometry.coerce(x);
307
                    } catch (CoercionException ex) {
308
                        gitem = null;
309
                    }
310

    
311
                    if (checkType) {
312
                        extracted = getGeometriesFrom(gitem, geometryType);
313
                        if (extracted.isEmpty()) {
314
                            // found no geometries of correct type
315
                            continue;
316
                        } else {
317
                            if (geometryType != Geometry.TYPES.POINT) {
318
                                // If not points, merge geometries
319
                                // (curves or surfaces)
320
                                try {
321
                                    gitem = union(extracted);
322
                                    extracted = new ArrayList<>();
323
                                    extracted.add(gitem);
324
                                } catch (Exception ex) {
325
                                    there_was_error = true;
326
                                    LOG.info("Error in union.", ex);
327
                                }
328
                            } else {
329
                                // only in the case of points, we can have several
330
                                // geometries if source is multipoint
331
                            }
332
                        }
333
                    } else {
334
                        extracted = new ArrayList<>();
335
                        extracted.add(gitem);
336
                    }
337

    
338
                    for (int i = 0; i < extracted.size(); i++) {
339
                        gitem = extracted.get(i);
340

    
341
                        if (gsubtype == Geometry.SUBTYPES.GEOM2D) {
342
                            gitem = force2D(gitem, geometryType);
343
                        } else {
344
                            gitem = force3D(gitem, geometryType);
345
                        }
346
                        edit_feat = target.createNewFeature(true);
347
                        //
348
                        // Accumulate error in boolean.
349
                        // This also fixes field names (using origNameToDbfName)
350
                        // 
351
                        there_was_error = there_was_error
352
                                | setNonNulls(
353
                                        getParameters().getSourceFeatureType(),
354
                                        targetType,
355
                                        feature,
356
                                        edit_feat
357
                                );
358
                        edit_feat.setDefaultGeometry(gitem);
359
                        // ================================================
360
                        // Reprojection stuff
361
                        if (coord_trans != null && gitem != null) {
362
                            reproj_geom = edit_feat.getDefaultGeometry();
363
                            reproj_geom = reproj_geom.cloneGeometry();
364
                            reproj_geom.reProject(coord_trans);
365
                            edit_feat.setDefaultGeometry(reproj_geom);
366
                        }
367
                        // ================================================
368
                        target.insert(edit_feat);
369
                    }
370
                }
371
                featureCount++;
372
                this.getTaskStatus().setCurValue(featureCount);
373

    
374
                if (this.getTaskStatus().isCancellationRequested()) {
375
                    return;
376
                }
377
            }
378
            target.finishEditing();
379
            target.dispose();
380

    
381
            this.targetOpenStoreParameters.add(this.createTargetOpenStoreParameters());
382

    
383
        } catch (Exception e) {
384
            throw new ExportException(e);
385
        } finally {
386
            DisposeUtils.dispose(it);
387
        }
388

    
389
        if (there_was_error) {
390
            Exception cause = new Exception(
391
                    "_Issues_with_attributes_or_geometries");
392
            throw new ExportException(cause);
393
        }
394
    }
395

    
396
    private void fixNames(EditableFeatureType eft) {
397

    
398
        FeatureAttributeDescriptor[] atts = eft.getAttributeDescriptors();
399
        EditableFeatureAttributeDescriptor efad;
400
        for (FeatureAttributeDescriptor att : atts) {
401
            String new_name = this.getParameters().getExportAttributes().getTargetName(att.getName());
402
            if (new_name != null) {
403
                eft.remove(att.getName());
404
                efad = eft.add(new_name, att.getType(), att.getSize());
405
                efad.setPrecision(att.getPrecision());
406
                if (att.getDataType().getType() == DataTypes.GEOMETRY) {
407
                    efad.setGeometryType(att.getGeomType());
408
                }
409
            }
410
        }
411
    }
412

    
413
    /**
414
     * @param gitem
415
     * @param geometryType2
416
     * @return
417
     */
418
    private Geometry force2D(Geometry ge, int gt) throws CreateGeometryException {
419
        if (ge == null) {
420
            return null;
421
        }
422
        if (ge.getGeometryType().getSubType() == Geometry.SUBTYPES.GEOM2D) {
423
            return ge;
424
        } else {
425
            GeometryManager geoManager = GeometryLocator.getGeometryManager();
426
            switch (gt) {
427
                case Geometry.TYPES.POINT:
428
                    Point p = (Point) ge;
429
                    Point point = geoManager.createPoint(
430
                            p.getX(), p.getY(),
431
                            Geometry.SUBTYPES.GEOM2D);
432
                    return point;
433
                case Geometry.TYPES.CURVE:
434
                    return geoManager.createCurve(ge.getGeneralPath(), Geometry.SUBTYPES.GEOM2D);
435
                case Geometry.TYPES.SURFACE:
436
                    return geoManager.createSurface(ge.getGeneralPath(), Geometry.SUBTYPES.GEOM2D);
437
                default:
438
                    return ge;
439
            }
440
        }
441
    }
442

    
443
    /**
444
     * @param gitem
445
     * @param geometryType2
446
     * @return
447
     */
448
    private Geometry force3D(Geometry ge, int gt) throws CreateGeometryException {
449
        if (ge == null) {
450
            return null;
451
        }
452
        // Los try catch que hay abajo, son para asegurarse de que la geometr?a original
453
        // tiene las 3 dimensiones necesarias. A veces nos llegan geometr?as que aunque son de subtipo GEOM3D
454
        // los puntos del generalPath que contienen no son 3D y no tienen la coordenada Z
455
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
456
        Point point;
457
        switch (gt) {
458
            case Geometry.TYPES.POINT:
459
                Point p = (Point) ge;
460
                point = geoManager.createPoint(
461
                        p.getX(), p.getY(),
462
                        Geometry.SUBTYPES.GEOM3D);
463
                try {
464
                    point.setCoordinateAt(2, p.getCoordinateAt(2));
465
                } catch (Exception e) {
466
                    point.setCoordinateAt(2, 0);
467
                }
468
                return point;
469
            case Geometry.TYPES.CURVE:
470
            case Geometry.TYPES.LINE:
471
                Line line = geoManager.createLine(Geometry.SUBTYPES.GEOM3D);
472
                for (int i = 0; i < ((OrientablePrimitive) ge).getNumVertices(); i++) {
473
                    Point vertex = ((OrientablePrimitive) ge).getVertex(i);
474
                    point = geoManager.createPoint(vertex.getX(), vertex.getY(), Geometry.SUBTYPES.GEOM3D);
475
                    try {
476
                        point.setCoordinateAt(2, vertex.getCoordinateAt(2));
477
                    } catch (Exception e) {
478
                        point.setCoordinateAt(2, 0);
479
                    }
480
                    line.addVertex(point);
481
                }
482
                ;
483
                return line;
484

    
485
            case Geometry.TYPES.SURFACE:
486
            case Geometry.TYPES.POLYGON:
487
                Polygon polygon = geoManager.createPolygon(Geometry.SUBTYPES.GEOM3D);
488
                for (int i = 0; i < ((OrientablePrimitive) ge).getNumVertices(); i++) {
489
                    Point vertex = ((OrientablePrimitive) ge).getVertex(i);
490
                    point = geoManager.createPoint(vertex.getX(), vertex.getY(), Geometry.SUBTYPES.GEOM3D);
491
                    try {
492
                        point.setCoordinateAt(2, vertex.getCoordinateAt(2));
493
                    } catch (Exception e) {
494
                        point.setCoordinateAt(2, 0);
495
                    }
496
                    polygon.addVertex(point);
497
                }
498
                ;
499
                return polygon;
500
            default:
501
                return ge;
502
        }
503
    }
504

    
505
    /**
506
     * @param feature
507
     * @param edit_feat
508
     */
509
    private boolean setNonNulls(
510
            FeatureType src_ft,
511
            FeatureType target_ft,
512
            Feature feat,
513
            EditableFeature edit_f
514
    ) {
515

    
516
        boolean error = false;
517
        FeatureAttributeDescriptor[] atts = src_ft.getAttributeDescriptors();
518
        String orig_name;
519
        String dbf_name;
520
        for (FeatureAttributeDescriptor att : atts) {
521
            if (att.getType() != org.gvsig.fmap.geom.DataTypes.GEOMETRY) {
522
                Object val;
523
                try {
524
                    orig_name = att.getName();
525
                    dbf_name = this.getParameters().getExportAttributes().getTargetName(orig_name);
526
                    if (dbf_name == null) {
527
                        dbf_name = orig_name;
528
                    }
529
                    val = feat.get(orig_name);
530
                    if (val != null && target_ft.getAttributeDescriptor(dbf_name) != null) {
531
                        edit_f.set(dbf_name, val);
532
                    }
533
                } catch (Exception ex) {
534
                    LOG.info("Error while getting/setting value", ex);
535
                    error = true;
536
                }
537
            }
538
        }
539
        return error;
540
    }
541

    
542
    private Geometry union(List<Geometry> geoms)
543
            throws GeometryOperationNotSupportedException, GeometryOperationException {
544

    
545
        if (geoms == null || geoms.isEmpty()) {
546
            return null;
547
        }
548

    
549
        if (geoms.size() == 1) {
550
            return geoms.get(0);
551
        }
552

    
553
        Geometry resp = geoms.get(0);
554
        for (int i = 1; i < geoms.size(); i++) {
555
            resp = resp.union(geoms.get(i));
556
        }
557
        return resp;
558
    }
559

    
560
    /**
561
     * @param feat_geom_type
562
     * @param type must be POINT, LINE or POLYGON (Geometry.TYPES)
563
     * @return
564
     */
565
    private List<Geometry> getGeometriesFrom(Geometry in_geom, int type) {
566

    
567
        List<Geometry> resp = new ArrayList<>();
568
        Aggregate agg;
569

    
570
        /*
571
         * If input geometry is aggregate, search its
572
         * primitives
573
         */
574
        if (in_geom instanceof Aggregate) {
575
            agg = (Aggregate) in_geom;
576
            Geometry item;
577
            List<Geometry> add_parts;
578
            for (int i = 0; i < agg.getPrimitivesNumber(); i++) {
579
                item = agg.getPrimitiveAt(i);
580
                add_parts = getGeometriesFrom(item, type);
581
                resp.addAll(add_parts);
582
            }
583
            return resp;
584
        }
585

    
586
        // ============================================
587
        switch (type) {
588
            case Geometry.TYPES.POINT:
589
                if (in_geom instanceof Point) {
590
                    resp.add(in_geom);
591
                }
592
                // =======================================================
593
                break;
594
            case Geometry.TYPES.CURVE:
595
                if (in_geom instanceof Curve) {
596
                    resp.add(in_geom);
597
                }
598
                // =======================================================
599
                break;
600
            case Geometry.TYPES.SURFACE:
601
                if (in_geom instanceof Surface) {
602
                    resp.add(in_geom);
603
                }
604
                // =======================================================
605
                break;
606
        }
607
        return resp;
608
    }
609

    
610
}