Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / shp / SHPStoreProvider.java @ 33205

History | View | Annotate | Download (17.5 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2008 IVER T.I. S.A.   {{Task}}
26
*/
27

    
28
package org.gvsig.fmap.dal.store.shp;
29

    
30
import java.io.IOException;
31
import java.util.Iterator;
32

    
33
import org.cresques.cts.IProjection;
34
import org.gvsig.fmap.crs.CRSFactory;
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.tools.dispose.DisposableIterator;
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.SHPFile;
66
import org.gvsig.fmap.geom.GeometryLocator;
67
import org.gvsig.fmap.geom.GeometryManager;
68
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
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.dynobject.exception.DynFieldNotFoundException;
73
import org.gvsig.tools.exception.BaseException;
74
import org.slf4j.Logger;
75
import org.slf4j.LoggerFactory;
76

    
77
public class SHPStoreProvider extends DBFStoreProvider {
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 SHPFile 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 SHPFile((SHPStoreParameters) params);
106
                super.init(params, storeServices);
107
        }
108

    
109
        public Object getDynValue(String name) throws DynFieldNotFoundException {
110
                if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
111
                        return this.shpFile.getSRSParameters();
112
                } else if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
113
                        try {
114
                                return this.shpFile.getFullExtent();
115
                        } catch (ReadException e) {
116
                                return null;
117
                        }
118
                }
119
                return super.getDynValue(name);
120
        }
121
        
122
        protected void initResource(DBFStoreParameters params,
123
                        DataStoreProviderServices storeServices) throws InitializeException {
124

    
125
                SHPStoreParameters shpParams = (SHPStoreParameters) params;
126
                resource =
127
                                (MultiResource) createResource(MultiResource.TYPE_NAME,
128
                                                new Object[] { shpParams.getSHPFileName() });
129

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

    
137
                resource.addConsumer(this);
138
        };
139

    
140
        public ResourceProvider getResource() {
141
                return resource;
142
        }
143

    
144
        /**
145
         *
146
         * @throws ResourceNotifyChangesException
147
         */
148
        protected void resourcesNotifyChanges()
149
                        throws ResourceNotifyChangesException {
150
                // super.resourcesNotifyChanges();
151
                // this.shpResource.notifyChanges();
152
                // this.shxResource.notifyChanges();
153
                getResource().notifyChanges();
154
                // TODO .prj
155

    
156
        }
157

    
158
        /**
159
         * @throws ResourceNotifyCloseException
160
         *
161
         */
162
        protected void resourcesNotifyClose() throws ResourceNotifyCloseException {
163
//                super.resourcesNotifyClose();
164
//                this.shpResource.notifyClose();
165
//                this.shxResource.notifyClose();
166
                getResource().notifyClose();
167
                // TODO .prj
168

    
169
        }
170

    
171
        @Override
172
        protected void doDispose() throws BaseException {
173
                super.doDispose();
174
                getResource().removeConsumer(this);
175
                this.writer = null;
176
                this.shpFile = null;
177
        }
178

    
179
        protected void disposeResource() {
180
                getResource().removeConsumer(this);
181
        }
182

    
183
        /**
184
         * @throws ResourceNotifyOpenException
185
         *
186
         */
187
        protected void resourcesOpen() throws ResourceNotifyOpenException {
188
                // super.resourcesOpen();
189
                // this.shpResource.notifyOpen();
190
                // this.shxResource.notifyOpen();
191
                getResource().notifyOpen();
192
        }
193

    
194
        protected static EditableFeatureAttributeDescriptor addGeometryColumn(
195
                        EditableFeatureType fType) {
196

    
197
                EditableFeatureAttributeDescriptor attrTmp = null;
198
                EditableFeatureAttributeDescriptor attr = null;
199
                Iterator iter = fType.iterator();
200
                while (iter.hasNext()) {
201
                        attrTmp = (EditableFeatureAttributeDescriptor) iter.next();
202
                        if (attrTmp.getDataType() == DataTypes.GEOMETRY) {
203
                                if (attr != null) {
204
                                        // Two geom fields not allowed
205
                                        fType.remove(attrTmp.getName());
206
                                } else {
207
                                        attr = attrTmp;
208
                                        attr.setName(GEOMETRY_ATTIBUTE_NAME);
209
                                }
210
                        }
211

    
212

    
213
                }
214

    
215

    
216
                if (attr == null){
217
                        attr = fType.add(
218
                                        GEOMETRY_ATTIBUTE_NAME, DataTypes.GEOMETRY);
219
                        try {
220
                                attr.setDefaultValue(geomManager
221
                                                .createNullGeometry(SUBTYPES.GEOM2D));
222
                        } catch (CreateGeometryException e) {
223
                                logger.error("Error creating the envelope", e);
224
                        }
225
                }
226

    
227
                fType.setDefaultGeometryAttributeName(attr.getName());
228
                return attr;
229

    
230
        }
231

    
232
        protected static FeatureType removeGeometryColumn(
233
                        EditableFeatureType fType) {
234
                Iterator iter = fType.iterator();
235
                FeatureAttributeDescriptor attr;
236
                while (iter.hasNext()) {
237
                        attr = (FeatureAttributeDescriptor) iter.next();
238
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
239
                                iter.remove();
240
                        }
241
                }
242
                fType.setDefaultGeometryAttributeName(null);
243
                return fType.getNotEditableCopy();
244
        }
245

    
246
        protected EditableFeatureType getTheFeatureType()
247
                        throws InitializeException, OpenException {
248
                final EditableFeatureType fType = super.getTheFeatureType();
249
                this.open();
250
                // try {
251
                // this.resourcesBegin();
252
                // } catch (DataException e) {
253
                // throw new InitializeException(this.getName(), e);
254
                // }
255
                try {
256
                        getResource().execute(new ResourceAction() {
257
                                public Object run() throws Exception {
258
                                        EditableFeatureAttributeDescriptor attr =
259
                                                        addGeometryColumn(fType);
260
                                        attr.setGeometryType(shpFile.getGeometryType());
261
                                        attr.setGeometrySubType(shpFile.getGeometrySubType());
262
                                        // String srs =
263
                                        // this.getSRSFromPrj(this.shpFile.getSRSParameters());
264
                                        // if (srs == null){
265
                                        // // TODO petar ??
266
                                        // srs = "EPSG:23030";
267
                                        // }
268
                                        IProjection srs = getShpParameters().getCRS();
269
                                        if (srs == null) {
270
                                                srs = CRSFactory.getCRS("EPSG:23030");
271
                                        }
272

    
273
                                        attr.setSRS(srs);
274

    
275
                                        return null;
276
                                }
277
                        });
278
                        return fType;
279
                } catch (ResourceExecuteException e) {
280
                        throw new InitializeException(e);
281
                        // } finally {
282
                        // this.resourcesEnd();
283
                }
284
        }
285

    
286
//        private String getSRSFromPrj(String srsParameters) {
287
//                // TODO identificar que SRS hay que usar, ya sea
288
//                // el que se recibe de los parametros o el que
289
//                // conicida con el que se ha encontrado en el
290
//                // prg... y si ninguna de las dos que?
291
//                return null;
292
//        }
293

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

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

    
302
        public boolean allowWrite() {
303
                return this.shpFile.isEditable();
304
        }
305

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

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

    
331
        }
332

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

    
346
        }
347

    
348
        /**
349
         *
350
         * @param featureProvider
351
         * @throws DataException
352
         */
353
        protected void loadFeatureProviderByIndex(FeatureProvider featureProvider)
354
                        throws DataException {
355
                // this.open();
356
                // this.resourcesBegin();
357
                // try {
358
                        FeatureType featureType = featureProvider.getType();
359
                        long index = ((Long) featureProvider.getOID()).longValue();
360
                        boolean hasGeometry = false;
361
                        if (featureType.getIndex(featureType.getDefaultGeometryAttributeName()) >= 0) {
362
                                try {
363
                                        featureProvider.setDefaultGeometry(this.shpFile.getGeometry(index));
364
                                        hasGeometry = true;
365
                                } catch (CreateGeometryException e) {
366
                                        throw new ReadException(getName(), e);
367
                                }
368
                        }
369
                        if (hasDBFAttributes(featureType, hasGeometry)) {
370
                                super.loadFeatureProviderByIndex(featureProvider);
371
                        }
372

    
373
                // } finally {
374
                // this.resourcesEnd();
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.getDataType() == 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

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

    
414
        }
415

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

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

    
442
        public void performChanges(Iterator deleteds, Iterator inserteds,
443
                        Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
444
                final FeatureType fType;
445
                try {
446
                        fType = this.getStoreServices().getDefaultFeatureType();
447
                } catch (DataException e) {
448
                        throw new PerformEditingException(this.getName(), e);
449
                }
450
                // TODO Comprobar el campo de geometria
451

    
452
                final EditableFeatureType dbfFtype = fType.getEditable();
453

    
454
                removeGeometryColumn(dbfFtype);
455

    
456
                // try {
457
                // this.resourcesBegin();
458
                // } catch (ResourceExecuteException e1) {
459
                // throw new PerformEditingException(this.getName(), e1);
460
                // }
461

    
462
                try {
463

    
464
                        getResource().execute(new ResourceAction() {
465
                                public Object run() throws Exception {
466
                                        FeatureSet set = null;
467
                                        DisposableIterator iter = null;
468
                                        try {
469
                                                set = getFeatureStore().getFeatureSet();
470
                                                writer = new SHPFeatureWriter(getName());
471

    
472
                                                SHPStoreParameters shpParams = getShpParameters();
473
                                                SHPStoreParameters tmpParams =
474
                                                                (SHPStoreParameters) shpParams.getCopy();
475
                                                tmpParams.setDBFFile(tmpParams.getDBFFileName()
476
                                                                + ".tmp");
477
                                                tmpParams.setSHPFile(tmpParams.getSHPFileName()
478
                                                                + ".tmp");
479
                                                tmpParams.setSHXFile(tmpParams.getSHXFileName()
480
                                                                + ".tmp");
481

    
482
                                                writer.begin(tmpParams, fType, dbfFtype, set.getSize());
483

    
484
                                                iter = set.fastIterator();
485
                                                while (iter.hasNext()) {
486
                                                        Feature feature = (Feature) iter.next();
487
                                                        writer.append(feature);
488
                                                }
489

    
490
                                                writer.end();
491

    
492
                                                close();
493
                                                resourceCloseRequest();
494

    
495
                                                if (!shpParams.getDBFFile().delete()) {
496
                                                        throw new PerformEditingException(getName(),
497
                                                                        new IOException(shpParams.getDBFFileName()));
498
                                                }
499
                                                if (!shpParams.getSHPFile().delete()) {
500
                                                        throw new PerformEditingException(getName(),
501
                                                                        new IOException(shpParams.getSHPFileName()));
502
                                                }
503
                                                if (!shpParams.getSHXFile().delete()) {
504
                                                        throw new PerformEditingException(getName(),
505
                                                                        new IOException(shpParams.getSHXFileName()));
506
                                                }
507
                                                if (!tmpParams.getDBFFile().renameTo(
508
                                                                shpParams.getDBFFile())) {
509
                                                        throw new PerformEditingException(getName(),
510
                                                                        new IOException(shpParams.getSHPFileName()));
511
                                                }
512
                                                if (!tmpParams.getSHPFile().renameTo(
513
                                                                shpParams.getSHPFile())) {
514
                                                        throw new PerformEditingException(getName(),
515
                                                                        new IOException(shpParams.getSHPFileName()));
516
                                                }
517
                                                if (!tmpParams.getSHXFile().renameTo(
518
                                                                shpParams.getSHXFile())) {
519
                                                        throw new PerformEditingException(getName(),
520
                                                                        new IOException(shpParams.getSHXFileName()));
521
                                                }
522

    
523
                                                resourcesNotifyChanges();
524
                                                initFeatureType();
525
                                                return null;
526
                                        } finally {
527
                                                dispose(set);
528
                                                dispose(iter);
529
                                        }
530
                                }
531
                        });
532

    
533
                } catch (Exception e) {
534
                        throw new PerformEditingException(this.getName(), e);
535
                        // } finally {
536
                        // this.resourcesEnd();
537
                }
538

    
539

    
540
        }
541

    
542
        protected void resourceCloseRequest() throws ResourceException {
543
                // super.resourceCloseRequest();
544
                // this.shpResource.closeRequest();
545
                // this.shxResource.closeRequest();
546
                getResource().closeRequest();
547
        }
548

    
549
        public Envelope getEnvelope() throws DataException {
550
                this.open();
551
                return (Envelope) this.getDynValue("Envelope");
552
        }
553

    
554
        public void append(final FeatureProvider featureProvider) throws DataException {
555
//                this.resourcesBegin();
556
//                try {
557

    
558
                getResource().execute(new ResourceAction() {
559
                        public Object run() throws Exception {
560
                                writer.append(getStoreServices().createFeature(featureProvider));
561
                                return null;
562
                        }
563
                });
564
//                } finally {
565
//                        this.resourcesEnd();
566
//                }
567

    
568
        }
569

    
570
        public void beginAppend() throws DataException {
571
                // this.resourcesBegin();
572
                // try {
573

    
574
                getResource().execute(new ResourceAction() {
575
                        public Object run() throws Exception {
576
                                FeatureStore store = getFeatureStore();
577
                                FeatureType fType = store.getDefaultFeatureType();
578

    
579
                                // TODO Comprobar el campo de geometria
580

    
581
                                EditableFeatureType dbfFtype = fType.getEditable();
582

    
583
                                removeGeometryColumn(dbfFtype);
584
                                FeatureSet set = store.getFeatureSet();
585

    
586
                                writer = new SHPFeatureWriter(getName());
587

    
588
                                writer.begin(getShpParameters(), fType, dbfFtype, set.getSize());
589
                                return null;
590
                        }
591
                });
592
                // } finally {
593
                // this.resourcesEnd();
594
                // }
595

    
596
        }
597

    
598
        public void endAppend() throws DataException {
599
//                this.resourcesBegin();
600
//                try {
601
                getResource().execute(new ResourceAction() {
602
                        public Object run() throws Exception {
603
                                writer.end();
604
                                resourcesNotifyChanges();
605
                                return null;
606
                        }
607
                });
608
//                } finally {
609
//                        this.resourcesEnd();
610
//                }
611

    
612
        }
613

    
614
        public Object getSourceId() {
615
                return this.getShpParameters().getFile();
616
        }
617
}