Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / shp / SHPStoreProvider.java @ 28676

History | View | Annotate | Download (16.1 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.FeatureType;
47
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
48
import org.gvsig.fmap.dal.feature.spi.FeatureData;
49
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
50
import org.gvsig.fmap.dal.resource.exception.ResourceException;
51
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyChangesException;
52
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyCloseException;
53
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyOpenException;
54
import org.gvsig.fmap.dal.resource.file.FileResource;
55
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
56
import org.gvsig.fmap.dal.store.dbf.DBFStoreProvider;
57
import org.gvsig.fmap.dal.store.shp.utils.SHPFile;
58
import org.gvsig.fmap.geom.GeometryLocator;
59
import org.gvsig.fmap.geom.GeometryManager;
60
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
61
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
62
import org.gvsig.fmap.geom.exception.CreateGeometryException;
63
import org.gvsig.fmap.geom.primitive.Envelope;
64
import org.gvsig.tools.ToolsLocator;
65
import org.gvsig.tools.dynobject.DelegatedDynObject;
66
import org.gvsig.tools.dynobject.DynClass;
67
import org.gvsig.tools.dynobject.DynField;
68
import org.gvsig.tools.dynobject.DynObjectManager;
69
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
70
import org.gvsig.tools.persistence.PersistenceException;
71
import org.gvsig.tools.persistence.PersistentState;
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 = "SHPStore";
79
        public static String DESCRIPTION = "SHP file";
80
        private SHPFile shpFile;
81
        private ResourceProvider shpResource;
82
        private ResourceProvider shxResource;
83

    
84
        private SHPStoreParameters shpParams;
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
                        throws InitializeException {
94
                super(params);
95
                this.shpParams = params;
96

    
97
                shpResource = this.createResource(FileResource.NAME,
98
                                new Object[] { this.shpParams.getSHPFileName() });
99
                shpResource.addConsumer(this);
100

    
101
                shxResource = this.createResource(FileResource.NAME,
102
                                new Object[] { this.shpParams.getSHXFileName() });
103
                shxResource.addConsumer(this);
104

    
105
                // TODO .prj
106

    
107
                // FIXME
108
                this.dynObject = (DelegatedDynObject) ToolsLocator
109
                                .getDynObjectManager().createDynObject(DYNCLASS);
110

    
111
                this.shpFile = new SHPFile(this.shpParams);
112
        }
113

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

    
120
        }
121

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

    
128
        }
129

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

    
141
        }
142

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

    
153
        }
154

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

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

    
176

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

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

    
186

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

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

    
194
                        DYNCLASS = dynClass;
195
                }
196

    
197
        }
198

    
199

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

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

    
218

    
219
                }
220

    
221

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

    
232
                fType.setDefaultGeometryAttributeName(attr.getName());
233
                return attr;
234

    
235
        }
236

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

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

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

    
275
                        attr.setSRS(srs);
276

    
277

    
278
                        return fType;
279
                } catch (ReadException 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 shpParams;
296
        }
297

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

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

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

    
319
                        FeatureData featureData = super.getFeatureDataByIndex(index,
320
                                        featureType);
321
                        featureData.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
322
                        return featureData;
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 initFeatureDataByIndex(FeatureData featureData,
334
                        long index, FeatureType featureType) throws DataException {
335
                this.open();
336
                this.resourcesBegin();
337
                try {
338
                        super.initFeatureDataByIndex(featureData, index, featureType);
339
                        featureData.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 featureData
351
         * @throws DataException
352
         */
353
        protected void loadFeatureDataByIndex(FeatureData featureData)
354
                        throws DataException {
355
                this.open();
356
                this.resourcesBegin();
357
                try {
358
                        long index = ((Long) featureData.getOID()).longValue();
359
                        super.loadFeatureDataByIndex(featureData);
360
                        if (featureData.getType().getIndex(
361
                                        featureData.getType().getDefaultGeometryAttributeName()) >= 0) {
362
                                try {
363
                                        featureData.setDefaultGeometry(this.shpFile.getGeometry(index));
364
                                } catch (CreateGeometryException e) {
365
                                        throw new ReadException(getName(), e);
366
                                }
367
                        }
368

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

    
374

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

    
384
        public FeatureData createFeatureData(FeatureType type) throws DataException {
385
                FeatureData data = new SHPFeatureData(this, type);
386
                return data;
387
        }
388

    
389

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

    
394
        }
395

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

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

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

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

    
408
        }
409

    
410

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

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

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

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

    
440
                EditableFeatureType dbfFtype = fType.getEditable();
441

    
442
                removeGeometryColumn(dbfFtype);
443

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

    
450
                try {
451

    
452
                        FeatureSet set = this.store.getFeatureSet();
453
                        writer = new SHPFeatureWriter(this.getName());
454

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

    
461
                        writer.begin(tmpParams, fType, dbfFtype, set.getSize());
462

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

    
469
                        writer.end();
470

    
471
                        this.close();
472
                        this.resourceCloseRequest();
473

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

    
499

    
500
                        this.resourcesNotifyChanges();
501
                        this.initFeatureType();
502

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

    
509

    
510
        }
511

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

    
518
        public Envelope getEnvelope() throws DataException {
519
                this.open();
520
                return (Envelope) this.dynObject.getDynValue("Envelope");
521
        }
522

    
523
        public void loadFromState(PersistentState state) throws PersistenceException {
524
                // TODO Auto-generated method stub
525
                super.loadFromState(state);
526
        }
527

    
528
        public PersistentState getState() throws PersistenceException {
529
                // TODO Auto-generated method stub
530
                return super.getState();
531
        }
532

    
533
        public void append(FeatureData featureData) throws DataException {
534
                this.resourcesBegin();
535
                try {
536
                        writer.append(store.createFeature(featureData));
537
                } finally {
538
                        this.resourcesEnd();
539
                }
540

    
541
        }
542

    
543
        public void beginAppend() throws DataException {
544
                this.resourcesBegin();
545
                try {
546

    
547
                        FeatureType fType = this.store.getDefaultFeatureType();
548

    
549
                        // TODO Comprobar el campo de geometria
550

    
551
                        EditableFeatureType dbfFtype = fType.getEditable();
552

    
553
                        removeGeometryColumn(dbfFtype);
554
                        FeatureSet set = this.store.getFeatureSet();
555

    
556
                        writer = new SHPFeatureWriter(this.getName());
557

    
558
                        writer.begin(this.shpParams, fType, dbfFtype, set.getSize());
559
                } finally {
560
                        this.resourcesEnd();
561
                }
562

    
563
        }
564

    
565
        public void endAppend() throws DataException {
566
                this.resourcesBegin();
567
                try {
568
                        writer.end();
569
                        this.resourcesNotifyChanges();
570
                } finally {
571
                        this.resourcesEnd();
572
                }
573

    
574
        }
575

    
576
        /*
577
         * (non-Javadoc)
578
         *
579
         * @see org.gvsig.metadata.Metadata#getMetadataName()
580
         */
581
        public String getMetadataName() {
582
                return this.shpParams.getSHPFile().getName();
583
        }
584

    
585
        public Object getSourceId() {
586
                return this.getShpParameters().getFile();
587
        }
588

    
589
}