Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.file / org.gvsig.fmap.dal.file.shp / src / main / java / org / gvsig / fmap / dal / store / shp / SHPStoreProvider.java @ 46875

History | View | Annotate | Download (23.2 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.store.shp;
24

    
25
import java.io.File;
26
import java.io.IOException;
27
import java.util.ArrayList;
28
import java.util.Iterator;
29
import java.util.List;
30

    
31
import org.apache.commons.io.FileUtils;
32
import org.apache.commons.io.FilenameUtils;
33
import org.cresques.cts.IProjection;
34
import org.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36

    
37
import org.gvsig.fmap.dal.DataStore;
38
import org.gvsig.fmap.dal.DataTypes;
39
import org.gvsig.fmap.dal.FileHelper;
40
import org.gvsig.fmap.dal.exception.CloseException;
41
import org.gvsig.fmap.dal.exception.DataException;
42
import org.gvsig.fmap.dal.exception.InitializeException;
43
import org.gvsig.fmap.dal.exception.ReadException;
44
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.EditableFeatureType;
46
import org.gvsig.fmap.dal.feature.Feature;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureSet;
49
import org.gvsig.fmap.dal.feature.FeatureStore;
50
import org.gvsig.fmap.dal.feature.FeatureType;
51
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
52
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
53
import org.gvsig.fmap.dal.resource.ResourceAction;
54
import org.gvsig.fmap.dal.resource.exception.ResourceException;
55
import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException;
56
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyChangesException;
57
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyCloseException;
58
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyOpenException;
59
import org.gvsig.fmap.dal.resource.file.FileResource;
60
import org.gvsig.fmap.dal.resource.spi.MultiResource;
61
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
62
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
63
import org.gvsig.fmap.dal.store.dbf.DBFStoreParameters;
64
import org.gvsig.fmap.dal.store.dbf.DBFStoreProvider;
65
import org.gvsig.fmap.dal.store.shp.utils.ISHPFile;
66
import org.gvsig.fmap.dal.store.shp.utils.SHP;
67
import org.gvsig.fmap.dal.store.shp.utils.SHPFile2;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.GeometryLocator;
70
import org.gvsig.fmap.geom.GeometryManager;
71
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
72
import org.gvsig.fmap.geom.exception.CreateGeometryException;
73
import org.gvsig.fmap.geom.primitive.Envelope;
74
import org.gvsig.tools.dispose.DisposableIterator;
75
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
76
import org.gvsig.tools.exception.BaseException;
77

    
78
/**
79
 *
80
 */
81
public class SHPStoreProvider extends DBFStoreProvider {
82

    
83
    private static final GeometryManager GEOM_MANAGER = GeometryLocator.getGeometryManager();
84
    private static final Logger LOGGER = LoggerFactory.getLogger(SHPStoreProvider.class);
85
    
86
    public static String NAME = DataStore.SHAPE_PROVIDER_NAME;
87
    public static String DESCRIPTION = "Shape file";
88
    private ISHPFile shpFile;
89

    
90
    private MultiResource resource;
91

    
92
    public static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
93

    
94
    public static final String METADATA_DEFINITION_NAME = NAME;
95

    
96
    private SHPFeatureWriter writer = null;
97

    
98
    private boolean loTengoEnUso;
99

    
100
    /**
101
     * @param params
102
     * @param storeServices
103
     * @throws InitializeException
104
     */
105
    public SHPStoreProvider(SHPStoreParameters params, DataStoreProviderServices storeServices)
106
        throws InitializeException {
107
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
108
    }
109

    
110
    protected void init(DBFStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
111

    
112
        this.shpFile = new SHPFile2((SHPStoreParameters) params);
113
        super.init(params, storeServices);
114
        this.shpFile.setUseNullGeometry(this.getShpParameters().getUseNullGeometry());
115
    }
116

    
117
    @Override
118
    public SHPStoreParameters getParameters() {
119
        return (SHPStoreParameters) super.getParameters();
120
    }
121

    
122
    public IProjection getProjection() {
123
        return this.getShpParameters().getCRS();
124
    }
125
    
126
    @Override
127
    public Object getDynValue(String name) throws DynFieldNotFoundException {
128
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
129

    
130
            return this.getShpParameters().getCRS();
131

    
132
        } else if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
133
            try {
134
                return this.shpFile.getFullExtent();
135
            } catch (ReadException e) {
136
                return null;
137
            }
138
        }
139
        return super.getDynValue(name);
140
    }
141

    
142
    @Override
143
    public boolean hasDynValue(String name) throws DynFieldNotFoundException {
144
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
145

    
146
            return this.getShpParameters().getCRS() != null;
147

    
148
        } else if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
149
            try {
150
                return this.shpFile.getFullExtent() != null;
151
            } catch (ReadException e) {
152
                return false;
153
            }
154
        }
155
        return super.hasDynValue(name);
156
    }
157

    
158
    protected void initResource(DBFStoreParameters params, DataStoreProviderServices storeServices)
159
        throws InitializeException {
160

    
161
        SHPStoreParameters shpParams = (SHPStoreParameters) params;
162
        resource = (MultiResource) createResource(MultiResource.TYPE_NAME, new Object[] { shpParams.getSHPFileName() });
163

    
164
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getSHPFileName() }, true);
165
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getSHXFileName() }, true);
166
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getDBFFileName() }, true);
167

    
168
        resource.frozen();
169
        resource.addMultiResourceConsumer(this);
170
        super.initResource(resource, storeServices);
171
    }
172

    
173
    ;
174

    
175
    public ResourceProvider getResource() {
176
        return resource;
177
    }
178

    
179
    /**
180
     *
181
     * @throws ResourceNotifyChangesException
182
     */
183
    protected void resourcesNotifyChanges() throws ResourceNotifyChangesException {
184
        getResource().notifyChanges();
185
        // TODO .prj
186

    
187
    }
188

    
189
    /**
190
     * @throws ResourceNotifyCloseException
191
     *
192
     */
193
    protected void resourcesNotifyClose() throws ResourceNotifyCloseException {
194
        getResource().notifyClose();
195
        // TODO .prj
196

    
197
    }
198

    
199
    @Override
200
    protected void doDispose() throws BaseException {
201
        super.doDispose();
202
        getResource().removeConsumer(this);
203
        this.writer = null;
204
        this.shpFile = null;
205
    }
206

    
207
    protected void disposeResource() {
208
        getResource().removeConsumer(this);
209
    }
210

    
211
    /**
212
     * @throws ResourceNotifyOpenException
213
     *
214
     */
215
    protected void resourcesOpen() throws ResourceNotifyOpenException {
216
        getResource().notifyOpen();
217
    }
218

    
219
    protected static EditableFeatureAttributeDescriptor addGeometryColumn(EditableFeatureType fType) {
220

    
221
        EditableFeatureAttributeDescriptor attrTmp = null;
222
        EditableFeatureAttributeDescriptor attr = null;
223
        Iterator<?> iter = fType.iterator();
224
        while (iter.hasNext()) {
225
            attrTmp = (EditableFeatureAttributeDescriptor) iter.next();
226
            if (attrTmp.getType() == DataTypes.GEOMETRY) {
227
                if (attr != null) {
228
                    // Two geom fields not allowed
229
                    fType.remove(attrTmp.getName());
230
                } else {
231
                    attr = attrTmp;
232
                }
233
            }
234
        }
235

    
236
        if (attr == null) {
237
            String geofield = createGeometryFieldName(fType);
238
            attr = fType.add(geofield, DataTypes.GEOMETRY);
239
            attr.setDefaultValue(null);
240
        }
241

    
242
        attr.setObjectClass(Geometry.class);
243
        attr.setAllowNull(true);
244
//        fType.setDefaultGeometryAttributeName(attr.getName());
245
        return attr;
246

    
247
    }
248

    
249
    private static String createGeometryFieldName(FeatureType ft) {
250

    
251
        if (ft.getAttributeDescriptor(GEOMETRY_ATTIBUTE_NAME) == null) {
252
            return GEOMETRY_ATTIBUTE_NAME;
253
        }
254

    
255
        int i = 0;
256
        String candidate = GEOMETRY_ATTIBUTE_NAME + i;
257
        while (ft.getAttributeDescriptor(candidate) != null) {
258
            i++;
259
            candidate = GEOMETRY_ATTIBUTE_NAME + i;
260
        }
261
        return candidate;
262
    }
263

    
264
    protected EditableFeatureType getTheFeatureType() throws InitializeException{
265
        try {
266
            this.open();
267
        } catch (DataException e) {
268
            throw new InitializeException(this.getProviderName(), e);
269
        }
270
        final EditableFeatureType fType = super.getTheFeatureType();
271
        try {
272
            getResource().execute(new ResourceAction() {
273

    
274
                public Object run() throws Exception {
275
                    EditableFeatureAttributeDescriptor attr = addGeometryColumn(fType);
276

    
277
                    attr.setGeometryType(GEOM_MANAGER.getGeometryType(
278
                        shpFile.getGeometryType(),
279
                        shpFile.getGeometrySubType()
280
                    ));
281

    
282
                    IProjection srs = getShpParameters().getCRS();
283
                    attr.setSRS(srs);
284

    
285
                    return null;
286
                }
287
            });
288
            return fType;
289
        } catch (ResourceExecuteException e) {
290
            throw new InitializeException(e);
291
        }
292
    }
293

    
294
    protected SHPStoreParameters getShpParameters() {
295
        return (SHPStoreParameters) getParameters();
296
    }
297

    
298
    public String getProviderName() {
299
        return NAME;
300
    }
301

    
302
    public boolean allowWrite() {
303
        return this.shpFile.isEditable() &&
304
            super.allowWrite() &&
305
            !this.getShpParameters().getLoadCorruptGeometriesAsNull() &&
306
            !this.getShpParameters().getAllowInconsistenciesInGeometryType() &&
307
            !this.getShpParameters().getFixLinearRings();
308
    }
309

    
310
    /**
311
     *
312
     * @param index
313
     * @param featureType
314
     * @return
315
     * @throws ReadException
316
     */
317
    protected FeatureProvider getFeatureProviderByIndex(long index, FeatureType featureType) throws DataException {
318
        this.open();
319
        try {
320

    
321
            FeatureProvider featureProvider = super.getFeatureProviderByIndex(index, featureType);
322
            featureProvider.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
323
            return featureProvider;
324
        } catch (DataException e) {
325
            throw e;
326
        } catch (CreateEnvelopeException e) {
327
            throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(e);
328
        } catch (CreateGeometryException e) {
329
            throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(e);
330
        }
331

    
332
    }
333

    
334
    protected void initFeatureProviderByIndex(FeatureProvider featureProvider, long index, FeatureType featureType)
335
        throws DataException {
336
        try {
337
            super.initFeatureProviderByIndex(featureProvider, index, featureType);
338
            featureProvider.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
339
        } catch (CreateEnvelopeException e) {
340
            throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(e);
341
        } catch (CreateGeometryException e) {
342
            throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(e);
343
        }
344
    }
345

    
346
    /**
347
     *
348
     * @param featureProvider
349
     * @throws DataException
350
     */
351
    @Override
352
    protected void loadFeatureProviderByIndex(FeatureProvider featureProvider) throws DataException {
353

    
354
        FeatureType featureType = featureProvider.getType();
355
        long index = ((Long) featureProvider.getOID());
356
        boolean hasGeometry = false;
357
        int i = featureType.getDefaultGeometryAttributeIndex();
358
        if (i >= 0) {
359
            if (!featureProvider.isReadOnly(i)) {
360
                Geometry geom;
361
                try {
362
                    geom = this.shpFile.getGeometry(index);
363
                } catch (Exception e) {
364
                    if( this.getShpParameters().getLoadCorruptGeometriesAsNull() ) {
365
                        geom = null;
366
                    } else {
367
                        throw new ReadGeometryException(getName(), featureProvider.getOID(), e);
368
                    }
369
                }
370
                featureProvider.set(i, geom);
371
            }
372
            hasGeometry = true;
373
        }
374
        if (hasDBFAttributes(featureType, hasGeometry)) {
375
            super.loadFeatureProviderByIndex(featureProvider);
376
        }
377

    
378
    }
379

    
380
    public class ReadGeometryException extends ReadException {
381

    
382
        private final static String MESSAGE_FORMAT = "There was errors loading a geometry from '%(store)'.\nCheck 'Load corrupt geometries as null' in the shape's properties of the add layer dialog to skip corrupt geometries. The layer will become read only.";
383
        private final static String MESSAGE_KEY = "_ReadGeometryException";
384
        private static final long serialVersionUID = 2626155328734197112L;
385

    
386
        public ReadGeometryException(String store, Object oid, Throwable cause) {
387
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
388
            setValue("store", store);
389
            setValue("storeParameters",getParameters());
390
        }
391
    }
392

    
393
    private boolean hasDBFAttributes(FeatureType featureType, boolean hasGeometry) {
394
        FeatureAttributeDescriptor[] attributes = featureType.getAttributeDescriptors();
395
        // If there aren't any attributes, nor has any DBF attributes
396
        if (attributes == null || attributes.length == 0) {
397
            return false;
398
        }
399
        // If there is only one attribute and it is the geometry one
400
        if (attributes.length == 1 && hasGeometry) {
401
            return false;
402
        }
403
        // In any other case
404
        return true;
405
    }
406

    
407
    protected void loadValue(FeatureProvider featureProvider, long rowIndex, FeatureAttributeDescriptor descriptor)
408
        throws ReadException {
409
        if (descriptor.getType() == DataTypes.GEOMETRY) {
410
            return;
411
        } else {
412
            super.loadValue(featureProvider, rowIndex, descriptor);
413
        }
414
    }
415

    
416
    public FeatureProvider createFeatureProvider(FeatureType type) throws DataException {
417
        FeatureProvider data = new SHPFeatureProvider(this, type);
418
        return data;
419
    }
420

    
421
    protected void openFile() throws IOException, DataException {
422
        super.openFile();
423
        this.shpFile.open();
424

    
425
    }
426

    
427
    protected void closeFile() throws CloseException {
428
        super.closeFile();
429
        if (!this.shpFile.isOpen()) {
430
            return;
431
        }
432
        this.shpFile.close();
433
    }
434

    
435
    public boolean canWriteGeometry(final int geometryType, int geometrySubType) throws DataException {
436
        this.open();
437
        return ((Boolean) getResource().execute(new ResourceAction() {
438

    
439
            public Object run() throws Exception {
440
                boolean value = shpFile.canWriteGeometry(geometryType);
441
                return value ? Boolean.TRUE : Boolean.FALSE;
442
            }
443
        })).booleanValue();
444
    }
445

    
446
    @SuppressWarnings("rawtypes")
447
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds,
448
        Iterator originalFeatureTypesUpdated) throws PerformEditingException {
449
        final List<Object> originalFeatureTypesUpdatedList = new ArrayList<>();
450
        while (originalFeatureTypesUpdated.hasNext()) {
451
            originalFeatureTypesUpdatedList.add(originalFeatureTypesUpdated.next());
452
        }
453
        
454
        /*
455
         * This will throw an exception if there are new fields
456
         * with names too long
457
         */
458
        checkNewFieldsNameSize(originalFeatureTypesUpdatedList.iterator());
459

    
460
        final FeatureType fType;
461
        try {
462
            fType = this.getStoreServices().getDefaultFeatureType();
463
        } catch (DataException e) {
464
            throw new PerformEditingException(this.getProviderName(), e);
465
        }
466
        try {
467
            // TODO repasar el concepto de enUso de un recurso.
468
            loTengoEnUso = true;
469
            resourceCloseRequest();
470

    
471
            getResource().execute(new ResourceAction() {
472

    
473
                public Object run() throws Exception {
474
                    FeatureSet set = null;
475
                    DisposableIterator iter = null;
476
                    try {
477
                        set = getFeatureStore().getFeatureSet();
478
                        writer = new SHPFeatureWriter(getProviderName());
479

    
480
                        SHPStoreParameters shpParams = getShpParameters();
481
                        SHPStoreParameters tmpParams = (SHPStoreParameters) shpParams.getCopy();
482

    
483
                        File tmp_base = File.createTempFile("tmp_" + System.currentTimeMillis(), null);
484
                        String str_base = tmp_base.getCanonicalPath();
485

    
486
                        tmpParams.setDBFFile(str_base + ".dbf");
487
                        tmpParams.setSHPFile(str_base + ".shp");
488
                        tmpParams.setSHXFile(str_base + ".shx");
489

    
490
                        writer.begin(tmpParams, fType, set.getSize());
491

    
492
                        iter = set.fastIterator();
493
                        while (iter.hasNext()) {
494
                            Feature feature = (Feature) iter.next();
495
                            writer.append(feature);
496
                        }
497

    
498
                        writer.end();
499
                        loTengoEnUso = false;
500
                        close();
501

    
502

    
503
                        if (!shpParams.getDBFFile().delete()) {
504
                            LOGGER.debug("Can't delete dbf file '" + shpParams.getDBFFile() + "'.");
505
                            throw new IOException("Can't delete dbf '"
506
                                + FilenameUtils.getBaseName(shpParams.getDBFFileName())
507
                                + "' file to replace with the new dbf.\nThe new dbf is in temporary file '" + str_base
508
                                + "'");
509
                        }
510
                        if (!shpParams.getSHPFile().delete()) {
511
                            LOGGER.debug("Can't delete dbf file '" + shpParams.getSHPFile() + "'.");
512
                            throw new IOException("Can't delete shp '"
513
                                + FilenameUtils.getBaseName(shpParams.getSHPFileName())
514
                                + "' file to replace with the new shp.\nThe new shp is in temporary file '" + str_base
515
                                + "'");
516
                        }
517
                        if (!shpParams.getSHXFile().delete()) {
518
                            LOGGER.debug("Can't delete dbf file '" + shpParams.getSHXFile() + "'.");
519
                            throw new IOException("Can't delete shx '"
520
                                + FilenameUtils.getBaseName(shpParams.getSHXFileName())
521
                                + "' file to replace with the new shx.\nThe new shx is in temporary file '" + str_base
522
                                + "'");
523
                        }
524
                        if (shpParams.getCPGFile().exists() && !shpParams.getCPGFile().delete()) {
525
                            LOGGER.debug("Can't delete cpg file '" + shpParams.getCPGFile() + "'.");
526
                            throw new IOException("Can't delete cpg '"
527
                                + FilenameUtils.getBaseName(shpParams.getCPGFileName())
528
                                + "' file to replace with the new cpg.\nThe new cpg is in temporary file '" + str_base
529
                                + "'");
530
                        }
531

    
532
                        File prjFile = SHP.getPrjFile(shpParams.getSHPFile());
533
                        if (prjFile.exists()) {
534
                            if (!prjFile.delete()) {
535
                                LOGGER.debug("Can't delete prj file '" + prjFile + "'.");
536
                                throw new IOException("Can't delete shx '"
537
                                    + FilenameUtils.getBaseName(prjFile.getPath())
538
                                    + "' file to replace with the new shx.\nThe new shx is in temporary file '"
539
                                    + str_base + "'");
540
                            }
541
                        }
542
                        FileUtils.moveFile(tmpParams.getDBFFile(), shpParams.getDBFFile());
543
                        FileUtils.moveFile(tmpParams.getSHPFile(), shpParams.getSHPFile());
544
                        FileUtils.moveFile(tmpParams.getSHXFile(), shpParams.getSHXFile());
545
                        FileUtils.moveFile(tmpParams.getCPGFile(), shpParams.getCPGFile());
546

    
547
                        savePrjFile(shpParams.getFile(), tmpParams.getCRS());
548

    
549
                        resourcesNotifyChanges();
550
                        if (!originalFeatureTypesUpdatedList.isEmpty()) {
551
                             initFeatureType();
552
                        }
553
                       
554
                        return null;
555
                    } finally {
556
                        loTengoEnUso = false;
557
                        dispose(set);
558
                        dispose(iter);
559
                    }
560
                }
561
            });
562

    
563
        } catch (Exception e) {
564
            throw new PerformEditingException(this.getProviderName(), e);
565
        }
566

    
567
    }
568

    
569
    protected void resourceCloseRequest() throws ResourceException {
570
        getResource().closeRequest();
571
    }
572

    
573
    public Envelope getEnvelope() throws DataException {
574
        this.open();
575
        return (Envelope) this.getDynValue("Envelope");
576
    }
577

    
578
    public void append(final FeatureProvider featureProvider) throws DataException {
579
        getResource().execute(new ResourceAction() {
580

    
581
            public Object run() throws Exception {
582
                writer.append(getStoreServices().createFeature(featureProvider));
583
                return null;
584
            }
585
        });
586
    }
587

    
588
    public void beginAppend() throws DataException {
589
        getResource().execute(new ResourceAction() {
590

    
591
            public Object run() throws Exception {
592
                FeatureStore store = getFeatureStore();
593
                FeatureType fType = store.getDefaultFeatureType();
594

    
595
                writer = new SHPFeatureWriter(getProviderName());
596
                writer.begin(getShpParameters(), fType, store.getFeatureCount());
597
                return null;
598
            }
599
        });
600
    }
601

    
602
    public void endAppend() throws DataException {
603
        getResource().execute(new ResourceAction() {
604

    
605
            public Object run() throws Exception {
606
                writer.end();
607
                close();
608

    
609
                SHPStoreParameters shpParameters = SHPStoreProvider.this.getShpParameters();
610

    
611
                savePrjFile(shpParameters.getFile(), shpParameters.getCRS());
612

    
613
                resourcesNotifyChanges();
614
                return null;
615
            }
616
        });
617
    }
618

    
619
    public Object getSourceId() {
620
        return this.getShpParameters().getFile();
621
    }
622

    
623

    
624
}