Statistics
| Revision:

root / tags / v2_0_0_Build_2020 / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / shp / SHPStoreProvider.java @ 33898

History | View | Annotate | Download (17.7 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.Geometry;
67
import org.gvsig.fmap.geom.GeometryLocator;
68
import org.gvsig.fmap.geom.GeometryManager;
69
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
70
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
71
import org.gvsig.fmap.geom.exception.CreateGeometryException;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
74
import org.gvsig.tools.exception.BaseException;
75
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77

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

    
85
        private MultiResource resource;
86

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

    
89
        public static final String METADATA_DEFINITION_NAME = NAME;
90

    
91
        private SHPFeatureWriter writer = null;
92

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

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

    
106
                this.shpFile = new SHPFile((SHPStoreParameters) params);
107
                super.init(params, storeServices);
108
        }
109

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

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

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

    
141
                resource.addConsumer(this);
142
        };
143

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

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

    
160
        }
161

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

    
173
        }
174

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

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

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

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

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

    
217

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

    
229
                attr.setObjectClass(Geometry.class);                
230
                fType.setDefaultGeometryAttributeName(attr.getName());
231
                return attr;
232

    
233
        }
234

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

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

    
276
                                        attr.setSRS(srs);
277

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

    
289
//        private String getSRSFromPrj(String srsParameters) {
290
//                // TODO identificar que SRS hay que usar, ya sea
291
//                // el que se recibe de los parametros o el que
292
//                // conicida con el que se ha encontrado en el
293
//                // prg... y si ninguna de las dos que?
294
//                return null;
295
//        }
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
                        // } finally {
331
                        // this.resourcesEnd();
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
                        // } finally {
346
                        // this.resourcesEnd();
347
                }
348

    
349
        }
350

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

    
376
                // } finally {
377
                // this.resourcesEnd();
378
                // }
379

    
380
        }
381

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

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

    
407
        public FeatureProvider createFeatureProvider(FeatureType type) throws DataException {
408
                FeatureProvider data = new SHPFeatureProvider(this, type);
409
                return data;
410
        }
411

    
412

    
413
        protected void openFile() throws IOException, DataException {
414
                super.openFile();
415
                this.shpFile.open();
416

    
417
        }
418

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

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

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

    
455
                final EditableFeatureType dbfFtype = fType.getEditable();
456

    
457
                removeGeometryColumn(dbfFtype);
458

    
459
                // try {
460
                // this.resourcesBegin();
461
                // } catch (ResourceExecuteException e1) {
462
                // throw new PerformEditingException(this.getName(), e1);
463
                // }
464

    
465
                try {
466

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

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

    
485
                                                writer.begin(tmpParams, fType, dbfFtype, set.getSize());
486

    
487
                                                iter = set.fastIterator();
488
                                                while (iter.hasNext()) {
489
                                                        Feature feature = (Feature) iter.next();
490
                                                        writer.append(feature);
491
                                                }
492

    
493
                                                writer.end();
494

    
495
                                                close();
496
                                                resourceCloseRequest();
497

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

    
526
                                                resourcesNotifyChanges();
527
                                                initFeatureType();
528
                                                return null;
529
                                        } finally {
530
                                                dispose(set);
531
                                                dispose(iter);
532
                                        }
533
                                }
534
                        });
535

    
536
                } catch (Exception e) {
537
                        throw new PerformEditingException(this.getProviderName(), e);
538
                        // } finally {
539
                        // this.resourcesEnd();
540
                }
541

    
542

    
543
        }
544

    
545
        protected void resourceCloseRequest() throws ResourceException {
546
                // super.resourceCloseRequest();
547
                // this.shpResource.closeRequest();
548
                // this.shxResource.closeRequest();
549
                getResource().closeRequest();
550
        }
551

    
552
        public Envelope getEnvelope() throws DataException {
553
                this.open();
554
                return (Envelope) this.getDynValue("Envelope");
555
        }
556

    
557
        public void append(final FeatureProvider featureProvider) throws DataException {
558
//                this.resourcesBegin();
559
//                try {
560

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

    
571
        }
572

    
573
        public void beginAppend() throws DataException {
574
                // this.resourcesBegin();
575
                // try {
576

    
577
                getResource().execute(new ResourceAction() {
578
                        public Object run() throws Exception {
579
                                FeatureStore store = getFeatureStore();
580
                                FeatureType fType = store.getDefaultFeatureType();
581

    
582
                                // TODO Comprobar el campo de geometria
583

    
584
                                EditableFeatureType dbfFtype = fType.getEditable();
585

    
586
                                removeGeometryColumn(dbfFtype);
587
                                FeatureSet set = store.getFeatureSet();
588

    
589
                                writer = new SHPFeatureWriter(getProviderName());
590

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

    
599
        }
600

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

    
615
        }
616

    
617
        public Object getSourceId() {
618
                return this.getShpParameters().getFile();
619
        }
620
}