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

History | View | Annotate | Download (24.8 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
import java.util.logging.Level;
31

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

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

    
82
/**
83
 *
84
 */
85
public class SHPStoreProvider extends DBFStoreProvider {
86

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

    
94
    private MultiResource resource;
95

    
96
    public static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
97

    
98
    public static final String METADATA_DEFINITION_NAME = NAME;
99

    
100
    private SHPFeatureWriter writer = null;
101

    
102
    private boolean loTengoEnUso;
103

    
104
    /**
105
     * @param params
106
     * @param storeServices
107
     * @throws InitializeException
108
     */
109
    public SHPStoreProvider(SHPStoreParameters params, DataStoreProviderServices storeServices)
110
        throws InitializeException {
111
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
112
    }
113

    
114
    protected void init(DBFStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
115

    
116
        this.shpFile = new SHPFile2((SHPStoreParameters) params);
117
        super.init(params, storeServices);
118
        this.shpFile.setUseNullGeometry(this.getShpParameters().getUseNullGeometry());
119
    }
120

    
121
    @Override
122
    public SHPStoreParameters getParameters() {
123
        return (SHPStoreParameters) super.getParameters();
124
    }
125

    
126
    public IProjection getProjection() {
127
        return this.getShpParameters().getCRS();
128
    }
129
    
130
    @Override
131
    public Object getDynValue(String name) throws DynFieldNotFoundException {
132
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
133

    
134
            return this.getShpParameters().getCRS();
135

    
136
        } else if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
137
            try {
138
                return this.shpFile.getFullExtent();
139
            } catch (ReadException e) {
140
                return null;
141
            }
142
        }
143
        return super.getDynValue(name);
144
    }
145

    
146
    @Override
147
    public boolean hasDynValue(String name) throws DynFieldNotFoundException {
148
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
149

    
150
            return this.getShpParameters().getCRS() != null;
151

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

    
162
    protected void initResource(DBFStoreParameters params, DataStoreProviderServices storeServices)
163
        throws InitializeException {
164

    
165
        SHPStoreParameters shpParams = (SHPStoreParameters) params;
166
        resource = (MultiResource) createResource(MultiResource.TYPE_NAME, new Object[] { shpParams.getSHPFileName() });
167

    
168
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getSHPFileName() }, true);
169
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getSHXFileName() }, true);
170
        resource.addResource(FileResource.NAME, new Object[] { shpParams.getDBFFileName() }, true);
171

    
172
        resource.frozen();
173
        resource.addMultiResourceConsumer(this);
174
        super.initResource(resource, storeServices);
175
    }
176

    
177
    ;
178

    
179
    public ResourceProvider getResource() {
180
        return resource;
181
    }
182

    
183
    /**
184
     *
185
     * @throws ResourceNotifyChangesException
186
     */
187
    protected void resourcesNotifyChanges() throws ResourceNotifyChangesException {
188
        getResource().notifyChanges();
189
        // TODO .prj
190

    
191
    }
192

    
193
    /**
194
     * @throws ResourceNotifyCloseException
195
     *
196
     */
197
    protected void resourcesNotifyClose() throws ResourceNotifyCloseException {
198
        getResource().notifyClose();
199
        // TODO .prj
200

    
201
    }
202

    
203
    @Override
204
    protected void doDispose() throws BaseException {
205
        super.doDispose();
206
        getResource().removeConsumer(this);
207
        this.writer = null;
208
        this.shpFile = null;
209
    }
210

    
211
    protected void disposeResource() {
212
        getResource().removeConsumer(this);
213
    }
214

    
215
    /**
216
     * @throws ResourceNotifyOpenException
217
     *
218
     */
219
    protected void resourcesOpen() throws ResourceNotifyOpenException {
220
        getResource().notifyOpen();
221
    }
222

    
223
    protected static EditableFeatureAttributeDescriptor addGeometryColumn(EditableFeatureType fType) {
224

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

    
240
        if (attr == null) {
241
            String geofield = createGeometryFieldName(fType);
242
            attr = fType.add(geofield, DataTypes.GEOMETRY);
243
            attr.setDefaultValue(null);
244
        }
245

    
246
        attr.setObjectClass(Geometry.class);
247
        attr.setAllowNull(true);
248
//        fType.setDefaultGeometryAttributeName(attr.getName());
249
        return attr;
250

    
251
    }
252

    
253
    private static String createGeometryFieldName(FeatureType ft) {
254

    
255
        if (ft.getAttributeDescriptor(GEOMETRY_ATTIBUTE_NAME) == null) {
256
            return GEOMETRY_ATTIBUTE_NAME;
257
        }
258

    
259
        int i = 0;
260
        String candidate = GEOMETRY_ATTIBUTE_NAME + i;
261
        while (ft.getAttributeDescriptor(candidate) != null) {
262
            i++;
263
            candidate = GEOMETRY_ATTIBUTE_NAME + i;
264
        }
265
        return candidate;
266
    }
267

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

    
278
                public Object run() throws Exception {
279
                    EditableFeatureAttributeDescriptor attr = addGeometryColumn(fType);
280

    
281
                    attr.setGeometryType(GEOM_MANAGER.getGeometryType(
282
                        shpFile.getGeometryType(),
283
                        shpFile.getGeometrySubType()
284
                    ));
285

    
286
                    IProjection srs = getShpParameters().getCRS();
287
                    attr.setSRS(srs);
288

    
289
                    return null;
290
                }
291
            });
292
            return fType;
293
        } catch (ResourceExecuteException e) {
294
            throw new InitializeException(e);
295
        }
296
    }
297

    
298
    protected SHPStoreParameters getShpParameters() {
299
        return (SHPStoreParameters) getParameters();
300
    }
301

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

    
306
    public boolean allowWrite() {
307
        return this.shpFile.isEditable() &&
308
            super.allowWrite() &&
309
            !this.getShpParameters().getLoadCorruptGeometriesAsNull() &&
310
            !this.getShpParameters().getAllowInconsistenciesInGeometryType() &&
311
            !this.getShpParameters().getFixLinearRings();
312
    }
313

    
314
    /**
315
     *
316
     * @param index
317
     * @param providerFeatureType
318
     * @return
319
     * @throws ReadException
320
     */
321
    protected FeatureProvider getFeatureProviderByIndex(long index, FeatureType providerFeatureType, FeatureType storeFeatureType) throws DataException {
322
        this.open();
323
        try {
324

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

    
336
    }
337

    
338
    protected void initFeatureProviderByIndex(FeatureProvider featureProvider, long index, FeatureType featureType)
339
        throws DataException {
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
    @Override
356
    protected void loadFeatureProviderByIndex(FeatureProvider featureProvider) throws DataException {
357

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

    
382
    }
383

    
384
    public class ReadGeometryException extends ReadException {
385

    
386
        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.";
387
        private final static String MESSAGE_KEY = "_ReadGeometryException";
388
        private static final long serialVersionUID = 2626155328734197112L;
389

    
390
        public ReadGeometryException(String store, Object oid, Throwable cause) {
391
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
392
            setValue("store", store);
393
            setValue("storeParameters",getParameters());
394
        }
395
    }
396

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

    
411
    @Override
412
    protected void loadValue(DBFFeatureProvider featureProvider, long rowIndex, FeatureAttributeDescriptor descriptor)
413
        throws ReadException {
414
        if (descriptor.getType() != DataTypes.GEOMETRY) {
415
            super.loadValue((DBFFeatureProvider) featureProvider, rowIndex, descriptor);
416
        }
417
    }
418

    
419
    public FeatureProvider createFeatureProvider(FeatureType type) throws DataException {
420
        FeatureProvider data = new SHPFeatureProvider(this, type, null);
421
        return data;
422
    }
423

    
424
    public FeatureProvider createFeatureProvider(FeatureType providerFeatureType, FeatureType storeFeatureType) throws DataException {
425
        return new SHPFeatureProvider(this, providerFeatureType, storeFeatureType);
426
    }
427

    
428
    
429
    protected void openFile() throws IOException, DataException {
430
        super.openFile();
431
        this.shpFile.open();
432

    
433
    }
434

    
435
    protected void closeFile() throws CloseException {
436
        super.closeFile();
437
        if (!this.shpFile.isOpen()) {
438
            return;
439
        }
440
        this.shpFile.close();
441
    }
442

    
443
    public boolean canWriteGeometry(final int geometryType, int geometrySubType) throws DataException {
444
        this.open();
445
        return ((Boolean) getResource().execute(new ResourceAction() {
446

    
447
            public Object run() throws Exception {
448
                boolean value = shpFile.canWriteGeometry(geometryType);
449
                return value ? Boolean.TRUE : Boolean.FALSE;
450
            }
451
        })).booleanValue();
452
    }
453

    
454
    @SuppressWarnings("rawtypes")
455
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds,
456
        Iterator originalFeatureTypesUpdated) throws PerformEditingException {
457
        final List<Object> originalFeatureTypesUpdatedList = new ArrayList<>();
458
        while (originalFeatureTypesUpdated.hasNext()) {
459
            originalFeatureTypesUpdatedList.add(originalFeatureTypesUpdated.next());
460
        }
461
        
462
        /*
463
         * This will throw an exception if there are new fields
464
         * with names too long
465
         */
466
        checkNewFieldsNameSize(originalFeatureTypesUpdatedList.iterator());
467

    
468
        final FeatureType fType;
469
        try {
470
            fType = this.getStoreServices().getDefaultFeatureType();
471
        } catch (DataException e) {
472
            throw new PerformEditingException(this.getProviderName(), e);
473
        }
474
        try {
475
            // TODO repasar el concepto de enUso de un recurso.
476
            loTengoEnUso = true;
477
            resourceCloseRequest();
478

    
479
            getResource().execute(new ResourceAction() {
480

    
481
                public Object run() throws Exception {
482
                    FeatureSet set = null;
483
                    DisposableIterator iter = null;
484
                    try {
485
                        set = getFeatureStore().getFeatureSet();
486
                        writer = new SHPFeatureWriter(getProviderName());
487

    
488
                        SHPStoreParameters shpParams = getShpParameters();
489
                        SHPStoreParameters tmpParams = (SHPStoreParameters) shpParams.getCopy();
490

    
491
                        File tmp_base = File.createTempFile("tmp_" + System.currentTimeMillis(), null);
492
                        String str_base = tmp_base.getCanonicalPath();
493

    
494
                        tmpParams.setDBFFile(str_base + ".dbf");
495
                        tmpParams.setSHPFile(str_base + ".shp");
496
                        tmpParams.setSHXFile(str_base + ".shx");
497

    
498
                        writer.begin(tmpParams, fType, set.getSize());
499

    
500
                        iter = set.fastIterator();
501
                        while (iter.hasNext()) {
502
                            Feature feature = (Feature) iter.next();
503
                            writer.append(feature);
504
                        }
505

    
506
                        writer.end();
507
                        loTengoEnUso = false;
508
                        close();
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 '"
514
                                + FilenameUtils.getBaseName(shpParams.getDBFFileName())
515
                                + "' file to replace with the new dbf.\nThe new dbf is in temporary file '" + str_base
516
                                + "'");
517
                        }
518
                        if (!shpParams.getSHPFile().delete()) {
519
                            LOGGER.debug("Can't delete dbf file '" + shpParams.getSHPFile() + "'.");
520
                            throw new IOException("Can't delete shp '"
521
                                + FilenameUtils.getBaseName(shpParams.getSHPFileName())
522
                                + "' file to replace with the new shp.\nThe new shp is in temporary file '" + str_base
523
                                + "'");
524
                        }
525
                        if (!shpParams.getSHXFile().delete()) {
526
                            LOGGER.debug("Can't delete dbf file '" + shpParams.getSHXFile() + "'.");
527
                            throw new IOException("Can't delete shx '"
528
                                + FilenameUtils.getBaseName(shpParams.getSHXFileName())
529
                                + "' file to replace with the new shx.\nThe new shx is in temporary file '" + str_base
530
                                + "'");
531
                        }
532
                        if (shpParams.getCPGFile().exists() && !shpParams.getCPGFile().delete()) {
533
                            LOGGER.debug("Can't delete cpg file '" + shpParams.getCPGFile() + "'.");
534
                            throw new IOException("Can't delete cpg '"
535
                                + FilenameUtils.getBaseName(shpParams.getCPGFileName())
536
                                + "' file to replace with the new cpg.\nThe new cpg is in temporary file '" + str_base
537
                                + "'");
538
                        }
539

    
540
                        File prjFile = SHP.getPrjFile(shpParams.getSHPFile());
541
                        if (prjFile.exists()) {
542
                            if (!prjFile.delete()) {
543
                                LOGGER.debug("Can't delete prj file '" + prjFile + "'.");
544
                                throw new IOException("Can't delete shx '"
545
                                    + FilenameUtils.getBaseName(prjFile.getPath())
546
                                    + "' file to replace with the new shx.\nThe new shx is in temporary file '"
547
                                    + str_base + "'");
548
                            }
549
                        }
550
                        FileUtils.moveFile(tmpParams.getDBFFile(), shpParams.getDBFFile());
551
                        FileUtils.moveFile(tmpParams.getSHPFile(), shpParams.getSHPFile());
552
                        FileUtils.moveFile(tmpParams.getSHXFile(), shpParams.getSHXFile());
553
                        FileUtils.moveFile(tmpParams.getCPGFile(), shpParams.getCPGFile());
554

    
555
                        savePrjFile(shpParams.getFile(), tmpParams.getCRS());
556

    
557
                        resourcesNotifyChanges();
558
                        if (!originalFeatureTypesUpdatedList.isEmpty()) {
559
                             initFeatureType();
560
                        }
561
                       
562
                        return null;
563
                    } finally {
564
                        loTengoEnUso = false;
565
                        dispose(set);
566
                        dispose(iter);
567
                    }
568
                }
569
            });
570

    
571
        } catch (Exception e) {
572
            throw new PerformEditingException(this.getProviderName(), e);
573
        }
574

    
575
    }
576

    
577
    protected void resourceCloseRequest() throws ResourceException {
578
        getResource().closeRequest();
579
    }
580

    
581
    public Envelope getEnvelope() throws DataException {
582
        this.open();
583
        return (Envelope) this.getDynValue("Envelope");
584
    }
585

    
586
    public void append(final FeatureProvider featureProvider) throws DataException {
587
        getResource().execute(new ResourceAction() {
588

    
589
            public Object run() throws Exception {
590
                writer.append(getStoreServices().createFeature(featureProvider));
591
                return null;
592
            }
593
        });
594
    }
595

    
596
    public void beginAppend() throws DataException {
597
        getResource().execute(new ResourceAction() {
598

    
599
            public Object run() throws Exception {
600
                FeatureStore store = getFeatureStore();
601
                FeatureType fType = store.getDefaultFeatureType();
602

    
603
                writer = new SHPFeatureWriter(getProviderName());
604
                writer.begin(getShpParameters(), fType, store.getFeatureCount());
605
                return null;
606
            }
607
        });
608
    }
609

    
610
    public void endAppend() throws DataException {
611
        getResource().execute(new ResourceAction() {
612

    
613
            public Object run() throws Exception {
614
                writer.end();
615
                close();
616

    
617
                SHPStoreParameters shpParameters = SHPStoreProvider.this.getShpParameters();
618

    
619
                savePrjFile(shpParameters.getFile(), shpParameters.getCRS());
620

    
621
                resourcesNotifyChanges();
622
                return null;
623
            }
624
        });
625
    }
626

    
627
    public Object getSourceId() {
628
        return this.getShpParameters().getFile();
629
    }
630

    
631
    @Override
632
    public void fixFeatureTypeFromParameters() {
633
        try {
634
            super.fixFeatureTypeFromParameters();
635
            FeatureStoreProviderServices store = this.getStoreServices();
636
            
637
            FeatureType ft = store.getDefaultFeatureType();
638
            FeatureAttributeDescriptor geomAttr = ft.getDefaultGeometryAttribute();
639
            
640
            GeometryType geomType = geomAttr.getGeomType();
641
            if(geomType.getType() != this.shpFile.getGeometryType() || geomType.getSubType() != this.shpFile.getGeometrySubType()) {
642
                EditableFeatureType eft = ft.getEditable();
643
                EditableFeatureAttributeDescriptor geomEditableAttr = (EditableFeatureAttributeDescriptor) eft.getDefaultGeometryAttribute();
644
                geomEditableAttr.setGeometryType(this.shpFile.getGeometryType(), this.shpFile.getGeometrySubType());
645
                this.setStoreFeatureType(eft.getNotEditableCopy());
646
            }
647
        } catch (DataException ex) {
648
            LOGGER.warn("Can't fix feture type.", ex);
649
        }
650

    
651
    }
652

    
653
    
654

    
655
}