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 @ 42464

History | View | Annotate | Download (23.1 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.Iterator;
28

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

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

    
76
public class SHPStoreProvider extends DBFStoreProvider {
77

    
78
    private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
79
    private static final Logger logger = LoggerFactory.getLogger(GeometryManager.class);
80
    public static String NAME = "Shape";
81
    public static String DESCRIPTION = "Shape file";
82
    private ISHPFile shpFile;
83

    
84
    private MultiResource resource;
85

    
86
    protected static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
87

    
88
    public static final String METADATA_DEFINITION_NAME = NAME;
89

    
90
    private SHPFeatureWriter writer = null;
91

    
92
    public SHPStoreProvider(SHPStoreParameters params,
93
            DataStoreProviderServices storeServices)
94
            throws InitializeException {
95
        super(
96
                params,
97
                storeServices,
98
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
99
        );
100
    }
101

    
102
    protected void init(DBFStoreParameters params,
103
            DataStoreProviderServices storeServices) throws InitializeException {
104

    
105
        this.shpFile = new SHPFile2((SHPStoreParameters) params);
106
        super.init(params, storeServices);
107
        this.shpFile.setUseNullGeometry(this.getShpParameters().getUseNullGeometry());
108
    }
109

    
110
    public Object getDynValue(String name) throws DynFieldNotFoundException {
111
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
112

    
113
            return this.getShpParameters().getCRS();
114

    
115
        } else if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
116
            try {
117
                return this.shpFile.getFullExtent();
118
            } catch (ReadException e) {
119
                return null;
120
            }
121
        }
122
        return super.getDynValue(name);
123
    }
124

    
125
    protected void initResource(DBFStoreParameters params,
126
            DataStoreProviderServices storeServices) throws InitializeException {
127

    
128
        SHPStoreParameters shpParams = (SHPStoreParameters) params;
129
        resource
130
                = (MultiResource) createResource(MultiResource.TYPE_NAME,
131
                        new Object[]{shpParams.getSHPFileName()});
132

    
133
        resource.addResource(FileResource.NAME,
134
                new Object[]{shpParams.getSHPFileName()}, true);
135
        resource.addResource(FileResource.NAME,
136
                new Object[]{shpParams.getSHXFileName()}, true);
137
        resource.addResource(FileResource.NAME,
138
                new Object[]{shpParams.getDBFFileName()}, true);
139

    
140
        resource.addConsumer(this);
141
    }
142

    
143
    ;
144

    
145
        public ResourceProvider getResource() {
146
        return resource;
147
    }
148

    
149
    /**
150
     *
151
     * @throws ResourceNotifyChangesException
152
     */
153
    protected void resourcesNotifyChanges()
154
            throws ResourceNotifyChangesException {
155
                // super.resourcesNotifyChanges();
156
        // this.shpResource.notifyChanges();
157
        // this.shxResource.notifyChanges();
158
        getResource().notifyChanges();
159
        // TODO .prj
160

    
161
    }
162

    
163
    /**
164
     * @throws ResourceNotifyCloseException
165
     *
166
     */
167
    protected void resourcesNotifyClose() throws ResourceNotifyCloseException {
168
//                super.resourcesNotifyClose();
169
//                this.shpResource.notifyClose();
170
//                this.shxResource.notifyClose();
171
        getResource().notifyClose();
172
        // TODO .prj
173

    
174
    }
175

    
176
    @Override
177
    protected void doDispose() throws BaseException {
178
        super.doDispose();
179
        getResource().removeConsumer(this);
180
        this.writer = null;
181
        this.shpFile = null;
182
    }
183

    
184
    protected void disposeResource() {
185
        getResource().removeConsumer(this);
186
    }
187

    
188
    /**
189
     * @throws ResourceNotifyOpenException
190
     *
191
     */
192
    protected void resourcesOpen() throws ResourceNotifyOpenException {
193
                // super.resourcesOpen();
194
        // this.shpResource.notifyOpen();
195
        // this.shxResource.notifyOpen();
196
        getResource().notifyOpen();
197
    }
198

    
199
    protected static EditableFeatureAttributeDescriptor addGeometryColumn(
200
            EditableFeatureType fType) {
201

    
202
        EditableFeatureAttributeDescriptor attrTmp = null;
203
        EditableFeatureAttributeDescriptor attr = null;
204
        Iterator iter = fType.iterator();
205
        while (iter.hasNext()) {
206
            attrTmp = (EditableFeatureAttributeDescriptor) iter.next();
207
            if (attrTmp.getType() == DataTypes.GEOMETRY) {
208
                if (attr != null) {
209
                    // Two geom fields not allowed
210
                    fType.remove(attrTmp.getName());
211
                } else {
212
                    attr = attrTmp;
213
                    // attr.setName(GEOMETRY_ATTIBUTE_NAME);
214
                }
215
            }
216
        }
217

    
218
        if (attr == null) {
219
            String geofield = createGeometryFieldName(fType);
220
            attr = fType.add(geofield, DataTypes.GEOMETRY);
221
            attr.setDefaultValue(null);
222
        }
223

    
224
        attr.setObjectClass(Geometry.class);
225
        fType.setDefaultGeometryAttributeName(attr.getName());
226
        return attr;
227

    
228
    }
229

    
230
    private static String createGeometryFieldName(FeatureType ft) {
231

    
232
        if (ft.getAttributeDescriptor(GEOMETRY_ATTIBUTE_NAME) == null) {
233
            return GEOMETRY_ATTIBUTE_NAME;
234
        }
235

    
236
        int i = 0;
237
        String candidate = GEOMETRY_ATTIBUTE_NAME + i;
238
        while (ft.getAttributeDescriptor(candidate) != null) {
239
            i++;
240
            candidate = GEOMETRY_ATTIBUTE_NAME + i;
241
        }
242
        return candidate;
243
    }
244

    
245
    protected static FeatureType removeGeometryColumn(
246
            EditableFeatureType fType) {
247
        Iterator iter = fType.iterator();
248
        FeatureAttributeDescriptor attr;
249
        while (iter.hasNext()) {
250
            attr = (FeatureAttributeDescriptor) iter.next();
251
            if (attr.getType() == DataTypes.GEOMETRY) {
252
                iter.remove();
253
            }
254
        }
255
        fType.setDefaultGeometryAttributeName(null);
256
        return fType.getNotEditableCopy();
257
    }
258

    
259
    protected EditableFeatureType getTheFeatureType()
260
            throws InitializeException, OpenException {
261
        final EditableFeatureType fType = super.getTheFeatureType();
262
        this.open();
263
                // try {
264
        // this.resourcesBegin();
265
        // } catch (DataException e) {
266
        // throw new InitializeException(this.getName(), e);
267
        // }
268
        try {
269
            getResource().execute(new ResourceAction() {
270
                public Object run() throws Exception {
271
                    EditableFeatureAttributeDescriptor attr
272
                            = addGeometryColumn(fType);
273
                    attr.setGeometryType(shpFile.getGeometryType());
274
                    attr.setGeometrySubType(shpFile.getGeometrySubType());
275

    
276
                    IProjection srs = getShpParameters().getCRS();
277
                    attr.setSRS(srs);
278

    
279
                    return null;
280
                }
281
            });
282
            return fType;
283
        } catch (ResourceExecuteException e) {
284
            throw new InitializeException(e);
285
                        // } finally {
286
            // this.resourcesEnd();
287
        }
288
    }
289

    
290
//        private String getSRSFromPrj(String srsParameters) {
291
//                // TODO identificar que SRS hay que usar, ya sea
292
//                // el que se recibe de los parametros o el que
293
//                // conicida con el que se ha encontrado en el
294
//                // prg... y si ninguna de las dos que?
295
//                return null;
296
//        }
297
    protected SHPStoreParameters getShpParameters() {
298
        return (SHPStoreParameters) getParameters();
299
    }
300

    
301
    public String getProviderName() {
302
        return NAME;
303
    }
304

    
305
    public boolean allowWrite() {
306
        return this.shpFile.isEditable();
307
    }
308

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

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

    
334
    }
335

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

    
350
    /**
351
     *
352
     * @param featureProvider
353
     * @throws DataException
354
     */
355
    protected void loadFeatureProviderByIndex(FeatureProvider featureProvider)
356
            throws DataException {
357

    
358
        FeatureType featureType = featureProvider.getType();
359
        long index = ((Long) featureProvider.getOID()).longValue();
360
        boolean hasGeometry = false;
361
        int i = featureType.getDefaultGeometryAttributeIndex();
362
        if (i >= 0) {
363
            if (!featureProvider.isReadOnly(i)) {
364
                try {
365
                    Geometry geom = this.shpFile.getGeometry(index);
366
                    featureProvider.set(i, geom);
367
                } catch (CreateGeometryException e) {
368
                    throw new ReadException(getProviderName(), e);
369
                }
370
            }
371
            hasGeometry = true;
372
        }
373
        if (hasDBFAttributes(featureType, hasGeometry)) {
374
            super.loadFeatureProviderByIndex(featureProvider);
375
        }
376

    
377
    }
378

    
379
    private boolean hasDBFAttributes(FeatureType featureType,
380
            boolean hasGeometry) {
381
        FeatureAttributeDescriptor[] attributes
382
                = featureType.getAttributeDescriptors();
383
        // If there aren't any attributes, nor has any DBF attributes
384
        if (attributes == null || attributes.length == 0) {
385
            return false;
386
        }
387
        // If there is only one attribute and it is the geometry one
388
        if (attributes.length == 1 && hasGeometry) {
389
            return false;
390
        }
391
        // In any other case
392
        return true;
393
    }
394

    
395
    protected void loadValue(FeatureProvider featureProvider, int rowIndex,
396
            FeatureAttributeDescriptor descriptor) throws ReadException {
397
        if (descriptor.getType() == DataTypes.GEOMETRY) {
398
            return;
399
        } else {
400
            super.loadValue(featureProvider, rowIndex, descriptor);
401
        }
402
    }
403

    
404
    public FeatureProvider createFeatureProvider(FeatureType type) throws DataException {
405
        FeatureProvider data = new SHPFeatureProvider(this, type);
406
        return data;
407
    }
408

    
409
    protected void openFile() throws IOException, DataException {
410
        super.openFile();
411
        this.shpFile.open();
412

    
413
    }
414

    
415
    protected void closeFile() throws CloseException {
416
        super.closeFile();
417
        if (!this.shpFile.isOpen()) {
418
            return;
419
        }
420
        this.shpFile.close();
421
    }
422

    
423
    public boolean canWriteGeometry(final int geometryType, int geometrySubType)
424
            throws DataException {
425
        this.open();
426
        return ((Boolean) getResource().execute(new ResourceAction() {
427
            public Object run() throws Exception {
428
                boolean value = shpFile.canWriteGeometry(geometryType);
429
                return value ? Boolean.TRUE : Boolean.FALSE;
430
            }
431
        })).booleanValue();
432
//                this.resourcesBegin();
433
//                try {
434
//                        return this.shpFile.canWriteGeometry(geometryType);
435
//
436
//                } finally {
437
//                        this.resourcesEnd();
438
//                }
439
    }
440

    
441
    public void performChanges(Iterator deleteds, Iterator inserteds,
442
            Iterator updateds, Iterator originalFeatureTypesUpdated)
443
            throws PerformEditingException {
444

    
445
        /*
446
         * This will throw an exception if there are new fields
447
         * with names too long
448
         */
449
        checkNewFieldsNameSize(originalFeatureTypesUpdated);
450

    
451
        final FeatureType fType;
452
        try {
453
            fType = this.getStoreServices().getDefaultFeatureType();
454
        } catch (DataException e) {
455
            throw new PerformEditingException(this.getProviderName(), e);
456
        }
457
        // TODO Comprobar el campo de geometria
458

    
459
        final EditableFeatureType dbfFtype = fType.getEditable();
460

    
461
        removeGeometryColumn(dbfFtype);
462

    
463
                // try {
464
        // this.resourcesBegin();
465
        // } catch (ResourceExecuteException e1) {
466
        // throw new PerformEditingException(this.getName(), e1);
467
        // }
468
        try {
469

    
470
            getResource().execute(new ResourceAction() {
471
                public Object run() throws Exception {
472
                    FeatureSet set = null;
473
                    DisposableIterator iter = null;
474
                    try {
475
                        set = getFeatureStore().getFeatureSet();
476
                        writer = new SHPFeatureWriter(getProviderName());
477

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

    
482
                        File tmp_base = File.createTempFile(
483
                                "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, dbfFtype, 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

    
500
                        close();
501
                        resourceCloseRequest();
502

    
503
                        //FIXME: Descomentarizar este c?digo cuando se consiga exportar la proyecci?n al formato de WKT_ESRI.
504
//                        File tmpPrjFile = SHP.getPrjFile(tmpParams.getSHPFile());
505
//                        try {
506
//                        FileUtils.writeStringToFile(tmpPrjFile, tmpParams.getCRS().export(ICRSFactory.FORMAT_WKT_ESRI));
507
//                        } catch(Exception e) {
508
//                            logger.info("Can't write prj file '"+tmpPrjFile.getAbsolutePath()+"'.");
509
//                        }
510

    
511
                        if (!shpParams.getDBFFile().delete()) {
512
                            logger.debug("Can't delete dbf file '"+shpParams.getDBFFile()+"'.");
513
                            throw new IOException("Can't delete dbf '"+FilenameUtils.getBaseName(shpParams.getDBFFileName())+"' file to replace with the new dbf.\nThe new dbf is in temporary file '"+str_base+"'");
514
                        }
515
                        if (!shpParams.getSHPFile().delete()) {
516
                            logger.debug("Can't delete dbf file '"+shpParams.getSHPFile()+"'.");
517
                            throw new IOException("Can't delete shp '"+FilenameUtils.getBaseName(shpParams.getSHPFileName())+"' file to replace with the new shp.\nThe new shp is in temporary file '"+str_base+"'");
518
                        }
519
                        if (!shpParams.getSHXFile().delete()) {
520
                            logger.debug("Can't delete dbf file '"+shpParams.getSHXFile()+"'.");
521
                            throw new IOException("Can't delete shx '"+FilenameUtils.getBaseName(shpParams.getSHXFileName())+"' file to replace with the new shx.\nThe new shx is in temporary file '"+str_base+"'");
522
                        }
523
                        //FIXME: Descomentarizar este c?digo cuando se consiga exportar la proyecci?n al formato de WKT_ESRI.
524
//                        if (SHP.getPrjFile(shpParams.getSHPFile()).exists()) {
525
//                            if (!SHP.getPrjFile(shpParams.getSHPFile()).delete()) {
526
//                                logger.debug("Can't delete prj file '" + SHP.getPrjFile(shpParams.getSHPFile()) + "'.");
527
//                                throw new IOException("Can't delete shx '"
528
//                                    + FilenameUtils.getBaseName(SHP.getPrjFile(shpParams.getSHPFile()).getPath())
529
//                                    + "' file to replace with the new shx.\nThe new shx is in temporary file '"
530
//                                    + str_base + "'");
531
//                            }
532
//                        }
533
                        FileUtils.moveFile(
534
                                tmpParams.getDBFFile(),
535
                                shpParams.getDBFFile());
536
                        FileUtils.moveFile(
537
                                tmpParams.getSHPFile(),
538
                                shpParams.getSHPFile());
539
                        FileUtils.moveFile(
540
                                tmpParams.getSHXFile(),
541
                                shpParams.getSHXFile());
542
                        //FIXME: Descomentarizar este c?digo cuando se consiga exportar la proyecci?n al formato de WKT_ESRI.
543
//                        FileUtils.moveFile(
544
//                            tmpPrjFile,
545
//                            SHP.getPrjFile(shpParams.getSHPFile()));
546

    
547
                        resourcesNotifyChanges();
548
                        initFeatureType();
549
                        return null;
550
                    } finally {
551
                        dispose(set);
552
                        dispose(iter);
553
                    }
554
                }
555
            });
556

    
557
        } catch (Exception e) {
558
            throw new PerformEditingException(this.getProviderName(), e);
559
        }
560

    
561
    }
562

    
563
    protected void resourceCloseRequest() throws ResourceException {
564
                // super.resourceCloseRequest();
565
        // this.shpResource.closeRequest();
566
        // this.shxResource.closeRequest();
567
        getResource().closeRequest();
568
    }
569

    
570
    public Envelope getEnvelope() throws DataException {
571
        this.open();
572
        return (Envelope) this.getDynValue("Envelope");
573
    }
574

    
575
    public void append(final FeatureProvider featureProvider) throws DataException {
576
//                this.resourcesBegin();
577
//                try {
578

    
579
        getResource().execute(new ResourceAction() {
580
            public Object run() throws Exception {
581
                writer.append(getStoreServices().createFeature(featureProvider));
582
                return null;
583
            }
584
        });
585
//                } finally {
586
//                        this.resourcesEnd();
587
//                }
588

    
589
    }
590

    
591
    public void beginAppend() throws DataException {
592
                // this.resourcesBegin();
593
        // try {
594

    
595
        getResource().execute(new ResourceAction() {
596
            public Object run() throws Exception {
597
                FeatureStore store = getFeatureStore();
598
                FeatureType fType = store.getDefaultFeatureType();
599

    
600
                                // TODO Comprobar el campo de geometria
601
                EditableFeatureType dbfFtype = fType.getEditable();
602

    
603
                removeGeometryColumn(dbfFtype);
604
                FeatureSet set = store.getFeatureSet();
605

    
606
                writer = new SHPFeatureWriter(getProviderName());
607

    
608
                writer.begin(getShpParameters(), fType, dbfFtype, set.getSize());
609
                return null;
610
            }
611
        });
612
                // } finally {
613
        // this.resourcesEnd();
614
        // }
615

    
616
    }
617

    
618
    public void endAppend() throws DataException {
619
//                this.resourcesBegin();
620
//                try {
621
        getResource().execute(new ResourceAction() {
622
            public Object run() throws Exception {
623
                writer.end();
624
                close();
625
                resourcesNotifyChanges();
626
                return null;
627
            }
628
        });
629
//                } finally {
630
//                        this.resourcesEnd();
631
//                }
632

    
633
    }
634

    
635
    public Object getSourceId() {
636
        return this.getShpParameters().getFile();
637
    }
638
}