Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2057 / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / shp / SHPStoreProvider.java @ 39169

History | View | Annotate | Download (17.9 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.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36

    
37
import org.gvsig.fmap.crs.CRSFactory;
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.OpenException;
45
import org.gvsig.fmap.dal.exception.ReadException;
46
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
47
import org.gvsig.fmap.dal.feature.EditableFeatureType;
48
import org.gvsig.fmap.dal.feature.Feature;
49
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
50
import org.gvsig.fmap.dal.feature.FeatureSet;
51
import org.gvsig.fmap.dal.feature.FeatureStore;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
54
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
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.DBFStoreParameters;
66
import org.gvsig.fmap.dal.store.dbf.DBFStoreProvider;
67
import org.gvsig.fmap.dal.store.shp.utils.SHPFile;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
70
import org.gvsig.fmap.geom.GeometryLocator;
71
import org.gvsig.fmap.geom.GeometryManager;
72
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
73
import org.gvsig.fmap.geom.exception.CreateGeometryException;
74
import org.gvsig.fmap.geom.primitive.Envelope;
75
import org.gvsig.fmap.mapcontext.MapContextLocator;
76
import org.gvsig.fmap.mapcontext.MapContextManager;
77
import org.gvsig.tools.dispose.DisposableIterator;
78
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
79
import org.gvsig.tools.exception.BaseException;
80

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

    
88
        private MultiResource resource;
89

    
90
        protected static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
91

    
92
        public static final String METADATA_DEFINITION_NAME = NAME;
93

    
94
        private SHPFeatureWriter writer = null;
95

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

    
106
        protected void init(DBFStoreParameters params,
107
                        DataStoreProviderServices storeServices) throws InitializeException {
108

    
109
                this.shpFile = new SHPFile((SHPStoreParameters) params);
110
                super.init(params, storeServices);
111
        }
112

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

    
132
                SHPStoreParameters shpParams = (SHPStoreParameters) params;
133
                resource =
134
                                (MultiResource) createResource(MultiResource.TYPE_NAME,
135
                                                new Object[] { shpParams.getSHPFileName() });
136

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

    
144
                resource.addConsumer(this);
145
        };
146

    
147
        public ResourceProvider getResource() {
148
                return resource;
149
        }
150

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

    
163
        }
164

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

    
176
        }
177

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

    
186
        protected void disposeResource() {
187
                getResource().removeConsumer(this);
188
        }
189

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

    
201
        protected static EditableFeatureAttributeDescriptor addGeometryColumn(
202
                        EditableFeatureType fType) {
203

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

    
220

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

    
232
                attr.setObjectClass(Geometry.class);                
233
                fType.setDefaultGeometryAttributeName(attr.getName());
234
                return attr;
235

    
236
        }
237

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

    
252
        protected EditableFeatureType getTheFeatureType()
253
                        throws InitializeException, OpenException {
254
                final EditableFeatureType fType = super.getTheFeatureType();
255
                this.open();
256
                // try {
257
                // this.resourcesBegin();
258
                // } catch (DataException e) {
259
                // throw new InitializeException(this.getName(), e);
260
                // }
261
                try {
262
                        getResource().execute(new ResourceAction() {
263
                                public Object run() throws Exception {
264
                                        EditableFeatureAttributeDescriptor attr =
265
                                                        addGeometryColumn(fType);
266
                                        attr.setGeometryType(shpFile.getGeometryType());
267
                                        attr.setGeometrySubType(shpFile.getGeometrySubType());
268

    
269
                                        IProjection srs = getShpParameters().getCRS();
270
                                        if (srs == null) {
271
                                            MapContextManager mcm = MapContextLocator.getMapContextManager();
272
                                                srs = mcm.getDefaultCRS();
273
                                        }
274

    
275
                                        attr.setSRS(srs);
276

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

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

    
296
        protected SHPStoreParameters getShpParameters() {
297
                return (SHPStoreParameters) getParameters();
298
        }
299

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

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

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

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

    
333
        }
334

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

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

    
374
                // } finally {
375
                // this.resourcesEnd();
376
                // }
377

    
378
        }
379

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

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

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

    
410

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

    
415
        }
416

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

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

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

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

    
455
                removeGeometryColumn(dbfFtype);
456

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

    
463
                try {
464

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

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

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

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

    
491
                                                writer.end();
492

    
493
                                                close();
494
                                                resourceCloseRequest();
495

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

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

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

    
540

    
541
        }
542

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

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

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

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

    
569
        }
570

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

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

    
580
                                // TODO Comprobar el campo de geometria
581

    
582
                                EditableFeatureType dbfFtype = fType.getEditable();
583

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

    
587
                                writer = new SHPFeatureWriter(getProviderName());
588

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

    
597
        }
598

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

    
613
        }
614

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