Statistics
| Revision:

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

History | View | Annotate | Download (16 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.DataTypes;
36
import org.gvsig.fmap.dal.exception.CloseException;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.exception.InitializeException;
39
import org.gvsig.fmap.dal.exception.ReadException;
40
import org.gvsig.fmap.dal.feature.DisposableIterator;
41
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
42
import org.gvsig.fmap.dal.feature.EditableFeatureType;
43
import org.gvsig.fmap.dal.feature.Feature;
44
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.FeatureSet;
46
import org.gvsig.fmap.dal.feature.FeatureStore;
47
import org.gvsig.fmap.dal.feature.FeatureType;
48
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
49
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
50
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
51
import org.gvsig.fmap.dal.resource.exception.ResourceException;
52
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyChangesException;
53
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyCloseException;
54
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyOpenException;
55
import org.gvsig.fmap.dal.resource.file.FileResource;
56
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
57
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
58
import org.gvsig.fmap.dal.store.dbf.DBFStoreParameters;
59
import org.gvsig.fmap.dal.store.dbf.DBFStoreProvider;
60
import org.gvsig.fmap.dal.store.shp.utils.SHPFile;
61
import org.gvsig.fmap.geom.GeometryLocator;
62
import org.gvsig.fmap.geom.GeometryManager;
63
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
64
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
65
import org.gvsig.fmap.geom.exception.CreateGeometryException;
66
import org.gvsig.fmap.geom.primitive.Envelope;
67
import org.gvsig.tools.ToolsLocator;
68
import org.gvsig.tools.dynobject.DynClass;
69
import org.gvsig.tools.dynobject.DynField;
70
import org.gvsig.tools.dynobject.DynObjectManager;
71
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
72
import org.slf4j.Logger;
73
import org.slf4j.LoggerFactory;
74

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

    
84

    
85
        protected static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
86
        protected static final String DYNFIELD_SRSORIGINALPARAMETERS_NAME = "SRSOriginalParameters";
87
        private static final String DYNCLASS_NAME = "SHPStore";
88
        protected static DynClass DYNCLASS = null;
89

    
90
        private SHPFeatureWriter writer = null;
91

    
92
        public SHPStoreProvider(SHPStoreParameters params,
93
                        DataStoreProviderServices storeServices)
94
                        throws InitializeException {
95
                super(params, storeServices,ToolsLocator
96
                                .getDynObjectManager().createDynObject(DYNCLASS));
97
        }
98

    
99
        protected void init(DBFStoreParameters params,
100
                        DataStoreProviderServices storeServices) throws InitializeException {
101

    
102
                SHPStoreParameters shpParams = (SHPStoreParameters) params;
103
                shpResource = this.createResource(FileResource.NAME,
104
                                new Object[] { shpParams.getSHPFileName() });
105
                shpResource.addConsumer(this);
106

    
107
                shxResource = this.createResource(FileResource.NAME,
108
                                new Object[] { shpParams.getSHXFileName() });
109
                shxResource.addConsumer(this);
110

    
111
                this.shpFile = new SHPFile(shpParams);
112
                super.init(params, storeServices);
113

    
114
        }
115

    
116
        protected void resourcesBegin() throws ResourceBeginException {
117
                super.resourcesBegin();
118
                this.shpResource.begin();
119
                this.shxResource.begin();
120
                // TODO .prj
121

    
122
        }
123

    
124
        protected void resourcesEnd() {
125
                super.resourcesEnd();
126
                this.shpResource.end();
127
                this.shxResource.end();
128
                // TODO .prj
129

    
130
        }
131

    
132
        /**
133
         *
134
         * @throws ResourceNotifyChangesException
135
         */
136
        protected void resourcesNotifyChanges()
137
                        throws ResourceNotifyChangesException {
138
                super.resourcesNotifyChanges();
139
                this.shpResource.notifyChanges();
140
                this.shxResource.notifyChanges();
141
                // TODO .prj
142

    
143
        }
144

    
145
        /**
146
         * @throws ResourceNotifyCloseException
147
         *
148
         */
149
        protected void resourcesNotifyClose() throws ResourceNotifyCloseException {
150
                super.resourcesNotifyClose();
151
                this.shpResource.notifyClose();
152
                this.shxResource.notifyClose();
153
                // TODO .prj
154

    
155
        }
156

    
157
        public void dispose() throws CloseException {
158
                super.dispose();
159
                this.shpResource.removeConsumer(this);
160
                this.shxResource.removeConsumer(this);
161
                this.shpResource = null;
162
                this.shxResource = null;
163
                this.writer = null;
164
                this.shpFile = null;
165
        }
166

    
167
        /**
168
         * @throws ResourceNotifyOpenException
169
         *
170
         */
171
        protected void resourcesOpen() throws ResourceNotifyOpenException {
172
                super.resourcesOpen();
173
                this.shpResource.notifyOpen();
174
                this.shxResource.notifyOpen();
175
        }
176

    
177

    
178
        protected static void registerDynClass() {
179
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
180
                DynClass dynClass;
181
                DynField field;
182
                if (DYNCLASS == null) {
183

    
184
                        DynClass dbfDynClass = DBFStoreProvider.DYNCLASS;
185
                        dynClass = dynman.add(DYNCLASS_NAME);
186

    
187

    
188
                        field = dynClass.addDynField(DYNFIELD_SRSORIGINALPARAMETERS_NAME);
189
                        field.setType(DataTypes.STRING);
190
                        field.setDescription("SRS original parameters");
191

    
192
            // The SHP store parameters extend the DBF store parameters
193
                        dynClass.extend(dbfDynClass);
194

    
195
                        DYNCLASS = dynClass;
196
                }
197

    
198
        }
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.getDataType() == 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

    
222

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

    
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.getDataType() == DataTypes.GEOMETRY) {
245
                                iter.remove();
246
                        }
247
                }
248
                fType.setDefaultGeometryAttributeName(null);
249
                return fType.getNotEditableCopy();
250
        }
251

    
252
        protected EditableFeatureType getTheFeatureType()
253
                        throws InitializeException {
254
                EditableFeatureType fType = super.getTheFeatureType();
255
                try {
256
                        this.open();
257
                        this.resourcesBegin();
258
                } catch (DataException e) {
259
                        throw new InitializeException(this.getName(), e);
260
                }
261
                try {
262

    
263
                        EditableFeatureAttributeDescriptor attr = addGeometryColumn(fType);
264
                        attr.setGeometryType(this.shpFile.getGeometryType());
265
                        attr.setGeometrySubType(this.shpFile.getGeometrySubType());
266
                        // String srs = this.getSRSFromPrj(this.shpFile.getSRSParameters());
267
                        // if (srs == null){
268
                        // // TODO petar ??
269
                        // srs = "EPSG:23030";
270
                        // }
271
                        IProjection srs = getShpParameters().getSRS();
272
                        if (srs == null){
273
                                srs = CRSFactory.getCRS("EPSG:23030");
274
                        }
275

    
276
                        attr.setSRS(srs);
277

    
278

    
279
                        return fType;
280
                } catch (ReadException e) {
281
                        throw new InitializeException(e);
282
                } finally {
283
                        this.resourcesEnd();
284
                }
285
        }
286

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

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

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

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

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

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

    
332
        }
333

    
334
        protected void initFeatureProviderByIndex(FeatureProvider featureProvider,
335
                        long index, FeatureType featureType) throws DataException {
336
                this.open();
337
                this.resourcesBegin();
338
                try {
339
                        super.initFeatureProviderByIndex(featureProvider, index, featureType);
340
                        featureProvider.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
341
                } catch (CreateEnvelopeException e) {
342
                        throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(e);
343
                } finally {
344
                        this.resourcesEnd();
345
                }
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
                        long index = ((Long) featureProvider.getOID()).longValue();
360
                        super.loadFeatureProviderByIndex(featureProvider);
361
                        if (featureProvider.getType().getIndex(
362
                                        featureProvider.getType().getDefaultGeometryAttributeName()) >= 0) {
363
                                try {
364
                                        featureProvider.setDefaultGeometry(this.shpFile.getGeometry(index));
365
                                } catch (CreateGeometryException e) {
366
                                        throw new ReadException(getName(), e);
367
                                }
368
                        }
369

    
370
                } finally {
371
                        this.resourcesEnd();
372
                }
373
        }
374

    
375

    
376
        protected void loadValue(FeatureProvider featureProvider, int rowIndex,
377
                        FeatureAttributeDescriptor descriptor) throws ReadException {
378
                if (descriptor.getDataType() == DataTypes.GEOMETRY) {
379
                        return;
380
                } else {
381
                        super.loadValue(featureProvider, rowIndex, descriptor);
382
                }
383
        }
384

    
385
        public FeatureProvider createFeatureProvider(FeatureType type) throws DataException {
386
                FeatureProvider data = new SHPFeatureProvider(this, type);
387
                return data;
388
        }
389

    
390

    
391
        protected void openFile() throws IOException, DataException {
392
                super.openFile();
393
                this.shpFile.open();
394

    
395
        }
396

    
397
        protected void loadMetadataValues() throws DynFieldNotFoundException,
398
                        ReadException {
399
                super.loadMetadataValues();
400

    
401
                this.setDynValue(DYNFIELD_SRSORIGINALPARAMETERS_NAME,
402
                                this.shpFile.getSRSParameters());
403

    
404
                this.setDynValue("DefaultSRS", this.getShpParameters()
405
                                .getSRS());
406

    
407
                this.setDynValue("Envelope", shpFile.getFullExtent());
408

    
409
        }
410

    
411

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

    
420
        public boolean canWriteGeometry(int geometryType, int geometrySubType) throws DataException {
421
                this.open();
422
                this.resourcesBegin();
423
                try {
424
                        return this.shpFile.canWriteGeometry(geometryType);
425

    
426
                } finally {
427
                        this.resourcesEnd();
428
                }
429
        }
430

    
431
        public void performChanges(Iterator deleteds, Iterator inserteds,
432
                        Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
433
                FeatureType fType;
434
                try {
435
                        fType = this.getStoreServices().getDefaultFeatureType();
436
                } catch (DataException e) {
437
                        throw new PerformEditingException(this.getName(), e);
438
                }
439
                // TODO Comprobar el campo de geometria
440

    
441
                EditableFeatureType dbfFtype = fType.getEditable();
442

    
443
                removeGeometryColumn(dbfFtype);
444

    
445
                try {
446
                        this.resourcesBegin();
447
                } catch (ResourceBeginException e1) {
448
                        throw new PerformEditingException(this.getName(), e1);
449
                }
450

    
451
                try {
452

    
453
                        FeatureSet set = this.getFeatureStore().getFeatureSet();
454
                        writer = new SHPFeatureWriter(this.getName());
455

    
456
                        SHPStoreParameters shpParams = this.getShpParameters();
457
                        SHPStoreParameters tmpParams = (SHPStoreParameters) shpParams
458
                                        .getCopy();
459
                        tmpParams.setDBFFileName(tmpParams.getDBFFileName() + ".tmp");
460
                        tmpParams.setSHPFileName(tmpParams.getSHPFileName() + ".tmp");
461
                        tmpParams.setSHXFileName(tmpParams.getSHXFileName() + ".tmp");
462

    
463
                        writer.begin(tmpParams, fType, dbfFtype, set.getSize());
464

    
465
                        DisposableIterator iter = set.fastIterator();
466
                        while (iter.hasNext()) {
467
                                Feature feature=(Feature) iter.next();
468
                                writer.append(feature);
469
                        }
470

    
471
                        writer.end();
472

    
473
                        this.close();
474
                        this.resourceCloseRequest();
475

    
476
                        if (!shpParams.getDBFFile().delete()) {
477
                                throw new PerformEditingException(this.getName(),
478
                                                new IOException(shpParams.getDBFFileName()));
479
                        }
480
                        if (!shpParams.getSHPFile().delete()) {
481
                                throw new PerformEditingException(this.getName(),
482
                                                new IOException(shpParams.getSHPFileName()));
483
                        }
484
                        if (!shpParams.getSHXFile().delete()) {
485
                                throw new PerformEditingException(this.getName(),
486
                                                new IOException(shpParams.getSHXFileName()));
487
                        }
488
                        if (!tmpParams.getDBFFile().renameTo(shpParams.getDBFFile())) {
489
                                throw new PerformEditingException(this.getName(),
490
                                                new IOException(shpParams.getSHPFileName()));
491
                        }
492
                        if (!tmpParams.getSHPFile().renameTo(shpParams.getSHPFile())) {
493
                                throw new PerformEditingException(this.getName(),
494
                                                new IOException(shpParams.getSHPFileName()));
495
                        }
496
                        if (!tmpParams.getSHXFile().renameTo(shpParams.getSHXFile())) {
497
                                throw new PerformEditingException(this.getName(),
498
                                                new IOException(shpParams.getSHXFileName()));
499
                        }
500

    
501

    
502
                        this.resourcesNotifyChanges();
503
                        this.initFeatureType();
504

    
505
                } catch (Exception e) {
506
                        throw new PerformEditingException(this.getName(), e);
507
                } finally {
508
                        this.resourcesEnd();
509
                }
510

    
511

    
512
        }
513

    
514
        protected void resourceCloseRequest() throws ResourceException {
515
                super.resourceCloseRequest();
516
                this.shpResource.closeRequest();
517
                this.shxResource.closeRequest();
518
        }
519

    
520
        public Envelope getEnvelope() throws DataException {
521
                this.open();
522
                return (Envelope) this.getDynValue("Envelope");
523
        }
524

    
525
        public void append(FeatureProvider featureProvider) throws DataException {
526
                this.resourcesBegin();
527
                try {
528
                        writer
529
                                        .append(this.getStoreServices()
530
                                        .createFeature(
531
                                                        featureProvider));
532
                } finally {
533
                        this.resourcesEnd();
534
                }
535

    
536
        }
537

    
538
        public void beginAppend() throws DataException {
539
                this.resourcesBegin();
540
                try {
541

    
542
                        FeatureStore store = this.getFeatureStore();
543
                        FeatureType fType = store.getDefaultFeatureType();
544

    
545
                        // TODO Comprobar el campo de geometria
546

    
547
                        EditableFeatureType dbfFtype = fType.getEditable();
548

    
549
                        removeGeometryColumn(dbfFtype);
550
                        FeatureSet set = store.getFeatureSet();
551

    
552
                        writer = new SHPFeatureWriter(this.getName());
553

    
554
                        writer.begin(getShpParameters(), fType, dbfFtype, set.getSize());
555
                } finally {
556
                        this.resourcesEnd();
557
                }
558

    
559
        }
560

    
561
        public void endAppend() throws DataException {
562
                this.resourcesBegin();
563
                try {
564
                        writer.end();
565
                        this.resourcesNotifyChanges();
566
                } finally {
567
                        this.resourcesEnd();
568
                }
569

    
570
        }
571

    
572
        public Object getSourceId() {
573
                return this.getShpParameters().getFile();
574
        }
575

    
576
}