Statistics
| Revision:

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

History | View | Annotate | Download (15 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.gvsig.fmap.dal.DataTypes;
34
import org.gvsig.fmap.dal.exception.CloseException;
35
import org.gvsig.fmap.dal.exception.DataException;
36
import org.gvsig.fmap.dal.exception.FileNotFoundException;
37
import org.gvsig.fmap.dal.exception.InitializeException;
38
import org.gvsig.fmap.dal.exception.OpenException;
39
import org.gvsig.fmap.dal.exception.ReadException;
40
import org.gvsig.fmap.dal.exception.UnsupportedVersionException;
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.impl.DefaultFeatureType;
49
import org.gvsig.fmap.dal.feature.spi.FeatureData;
50
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
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.primitive.Envelope;
59
import org.gvsig.fmap.geom.primitive.NullGeometry;
60
import org.gvsig.tools.ToolsLocator;
61
import org.gvsig.tools.dynobject.DelegatedDynObject;
62
import org.gvsig.tools.dynobject.DynClass;
63
import org.gvsig.tools.dynobject.DynField;
64
import org.gvsig.tools.dynobject.DynObjectManager;
65
import org.gvsig.tools.persistence.PersistenceException;
66
import org.gvsig.tools.persistence.PersistentState;
67

    
68
public class SHPStoreProvider extends DBFStoreProvider {
69
        public static String NAME = "SHPStore";
70
        public static String DESCRIPTION = "SHP file";
71
        private SHPFile shpFile;
72
        private ResourceProvider shpResource;
73
        private ResourceProvider shxResource;
74

    
75
        private SHPStoreParameters shpParams;
76
        protected static final String GEOMETRY_ATTIBUTE_NAME = "GEOMETRY";
77
        protected static final String DYNFIELD_SRSORIGINALPARAMETERS_NAME = "SRSOriginalParameters";
78
        private static final String DYNCLASS_NAME = "SHPStore";
79
        protected static DynClass DYNCLASS = null;
80

    
81
        private SHPFeatureWriter writer = null;
82

    
83
        public SHPStoreProvider(SHPStoreParameters params)
84
                        throws InitializeException {
85
                super(params);
86
                this.shpParams = params;
87

    
88
                shpResource = this.createResource(FileResource.NAME,
89
                                new Object[] { this.shpParams.getSHPFileName() });
90
                shpResource.addConsumer(this);
91

    
92
                shxResource = this.createResource(FileResource.NAME,
93
                                new Object[] { this.shpParams.getSHXFileName() });
94
                shxResource.addConsumer(this);
95

    
96
                // FIXME
97
                this.dynObject = (DelegatedDynObject) ToolsLocator
98
                                .getDynObjectManager().createDynObject(DYNCLASS);
99

    
100
                this.shpFile = new SHPFile(this.shpParams);
101
        }
102

    
103
        private void resourcesBegin() throws ResourceBeginException {
104
                this.shpResource.begin();
105
                this.shxResource.begin();
106
        }
107

    
108
        private void resourcesEnd() {
109
                this.shpResource.end();
110
                this.shxResource.end();
111
        }
112

    
113
        /**
114
         *
115
         * @throws ResourceNotifyChangesException
116
         */
117
        private void resourcesNotifyChanges() throws ResourceNotifyChangesException {
118
                this.shpResource.notifyChanges();
119
                this.shxResource.notifyChanges();
120
        }
121

    
122
        /**
123
         * @throws ResourceNotifyCloseException
124
         *
125
         */
126
        private void resourcesNotifyClose() throws ResourceNotifyCloseException {
127
                this.shpResource.notifyClose();
128
                this.shxResource.notifyClose();
129
        }
130

    
131
        /**
132
         * @throws ResourceNotifyOpenException
133
         *
134
         */
135
        private void resourcesOpen() throws ResourceNotifyOpenException {
136
                this.shpResource.notifyOpen();
137
                this.shxResource.notifyOpen();
138
        }
139

    
140

    
141
        protected static void registerDynClass() {
142
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
143
                DynClass dynClass;
144
                DynField field;
145
                if (DYNCLASS == null) {
146

    
147
                        DynClass dbfDynClass = DBFStoreProvider.DYNCLASS;
148
                        dynClass = dynman.add(DYNCLASS_NAME);
149

    
150

    
151
                        field = dynClass.addDynField(DYNFIELD_SRSORIGINALPARAMETERS_NAME);
152
                        field.setType(DataTypes.STRING);
153
                        field.setDescription("SRS original parameters");
154

    
155
            // The SHP store parameters extend the DBF store parameters
156
                        dynClass.extend(dbfDynClass);
157

    
158
                        DYNCLASS = dynClass;
159
                }
160

    
161
        }
162

    
163

    
164
        protected static EditableFeatureAttributeDescriptor addGeometryColumn(
165
                        EditableFeatureType fType) {
166

    
167
                EditableFeatureAttributeDescriptor attrTmp = null;
168
                EditableFeatureAttributeDescriptor attr = null;
169
                Iterator iter = fType.iterator();
170
                while (iter.hasNext()) {
171
                        attrTmp = (EditableFeatureAttributeDescriptor) iter.next();
172
                        if (attrTmp.getDataType() == DataTypes.GEOMETRY) {
173
                                if (attr != null) {
174
                                        // Two geom fields not allowed
175
                                        fType.remove(attrTmp.getName());
176
                                } else {
177
                                        attr = attrTmp;
178
                                        attr.setName(GEOMETRY_ATTIBUTE_NAME);
179
                                }
180
                        }
181

    
182

    
183
                }
184

    
185

    
186
                if (attr == null){
187
                        attr = fType.add(
188
                                        GEOMETRY_ATTIBUTE_NAME, DataTypes.GEOMETRY);
189
                        attr.setDefaultValue(new NullGeometry());
190
                }
191

    
192
                fType.setDefaultGeometryAttributeName(attr.getName());
193
                return attr;
194

    
195
        }
196

    
197
        protected static void removeGeometryColumn(
198
                        EditableFeatureType fType) {
199
                Iterator iter = fType.iterator();
200
                FeatureAttributeDescriptor attr;
201
                while (iter.hasNext()) {
202
                        attr = (FeatureAttributeDescriptor) iter.next();
203
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
204
                                iter.remove();
205
                        }
206
                }
207
                fType.setDefaultGeometryAttributeName(null);
208
                fType.remove(GEOMETRY_ATTIBUTE_NAME);
209
        }
210

    
211
        protected EditableFeatureType getTheFeatureType()
212
                        throws InitializeException {
213
                EditableFeatureType fType = super.getTheFeatureType();
214
                try {
215
                        this.open();
216
                        this.resourcesBegin();
217
                } catch (DataException e) {
218
                        throw new InitializeException(this.getName(), e);
219
                }
220
                try {
221

    
222
                        EditableFeatureAttributeDescriptor attr = addGeometryColumn(
223
                                        fType).setGeometryType(
224
                                        this.shpFile.getGeometryType());
225
                        String srs = this.getSRS(this.shpFile.getSRSParameters());
226
                        if (srs == null){
227
                                // TODO petar ??
228
                                srs = "EPSG:23030";
229
                        }
230
                        attr.setSRS(srs);
231

    
232

    
233
                        return fType;
234
                } catch (ReadException e) {
235
                        throw new InitializeException(e);
236
                } finally {
237
                        this.resourcesEnd();
238
                }
239
        }
240

    
241
        private String getSRS(String srsParameters) {
242
                // TODO identificar que SRS hay que usar, ya sea
243
                // el que se recibe de los parametros o el que
244
                // conicida con el que se ha encontrado en el
245
                // prg... y si ninguna de las dos que?
246
                return null;
247
        }
248

    
249
        protected SHPStoreParameters getShpParameters() {
250
                return shpParams;
251
        }
252

    
253
        public String getName() {
254
                return NAME;
255
        }
256

    
257
        public boolean allowWrite() {
258
                return super.allowWrite() && this.shpFile.isEditable();
259
        }
260

    
261
        /**
262
         *
263
         * @param index
264
         * @param featureType
265
         * @return
266
         * @throws ReadException
267
         */
268
        protected FeatureData getFeatureDataByIndex(long index,
269
                        FeatureType featureType) throws DataException {
270
                this.open();
271
                this.resourcesBegin();
272
                try {
273

    
274
                        FeatureData featureData = super.getFeatureDataByIndex(index,
275
                                        featureType);
276
                        featureData.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
277
                        return featureData;
278
                } catch (DataException e) {
279
                        throw e;
280
                } finally {
281
                        this.resourcesEnd();
282
                }
283

    
284
        }
285

    
286
        protected void initFeatureDataByIndex(FeatureData featureData,
287
                        long index, FeatureType featureType) throws DataException {
288
                this.open();
289
                this.resourcesBegin();
290
                try {
291
                        super.initFeatureDataByIndex(featureData, index, featureType);
292
                        featureData.setDefaultEnvelope(this.shpFile.getBoundingBox(index));
293
                } finally {
294
                        this.resourcesEnd();
295
                }
296

    
297
        }
298

    
299
        /**
300
         *
301
         * @param featureData
302
         * @throws DataException
303
         */
304
        protected void loadFeatureDataByIndex(FeatureData featureData)
305
                        throws DataException {
306
                this.open();
307
                this.resourcesBegin();
308
                try {
309
                        long index = ((Long) featureData.getOID()).longValue();
310
                        super.loadFeatureDataByIndex(featureData);
311
                        if (featureData.getType().getIndex(
312
                                        featureData.getType().getDefaultGeometryAttributeName()) >= 0) {
313
                                featureData.setDefaultGeometry(this.shpFile.getGeometry(index));
314
                        }
315

    
316
                } finally {
317
                        this.resourcesEnd();
318
                }
319
        }
320

    
321

    
322
        protected void loadValue(FeatureData featureData, int rowIndex,
323
                        FeatureAttributeDescriptor descriptor) throws ReadException {
324
                if (descriptor.getDataType() == DataTypes.GEOMETRY) {
325
                        return;
326
                } else {
327
                        super.loadValue(featureData, rowIndex, descriptor);
328
                }
329
        }
330

    
331
        public FeatureData createFeatureData(FeatureType type) throws DataException {
332
                FeatureData data = new SHPFeatureData(this, (DefaultFeatureType) type);
333
                return data;
334
        }
335
        public void open() throws OpenException {
336
                super.open();
337
                if (this.shpFile.isOpen()) {
338
                        return;
339
                }
340
                try {
341
                        this.resourcesBegin();
342
                } catch (ResourceBeginException e) {
343
                        throw new OpenException(this.getName(), e);
344
                }
345
                try {
346
                        this.shpFile.open();
347
                        this.resourcesOpen();
348

    
349

    
350

    
351
                        // load metadata
352
                        //                        TODO: Load .prj data
353
                        //                        this.dynObject.setDynValue(
354
                        //                                        DYNFIELD_SRSORIGINALPARAMETERS_NAME,
355
                        //                                        this.shpFile.??);
356

    
357
                        this.dynObject.setDynValue("DefaultSRS", this.shpFile
358
                                        .getSRSParameters());
359

    
360

    
361
                        this.dynObject.setDynValue("Envelope", shpFile.getFullExtent());
362

    
363
                } catch (UnsupportedVersionException e) {
364
                        throw new OpenException(this.getName(), e);
365
                } catch (ResourceNotifyOpenException e) {
366
                        throw new OpenException(this.getName(), e);
367
                } catch (FileNotFoundException e) {
368
                        throw new OpenException(this.getName(), e);
369
                } catch (DataException e) {
370
                        throw new OpenException(this.getName(), e);
371
                } finally {
372
                        this.resourcesEnd();
373
                }
374
        }
375

    
376
        public void close() throws CloseException {
377
                super.close();
378
                if (!this.shpFile.isOpen()) {
379
                        return;
380
                }
381
                try {
382
                        this.resourcesBegin();
383
                } catch (ResourceBeginException e) {
384
                        throw new CloseException(this.getName(), e);
385
                }
386
                try {
387
                        this.shpFile.close();
388
                        this.resourcesNotifyClose();
389

    
390
                } catch (ResourceNotifyCloseException e) {
391
                        throw new CloseException(this.getName(), e);
392
                } finally {
393
                        this.resourcesEnd();
394
                }
395
        }
396

    
397
        public boolean canWriteGeometry(int geometryType) throws DataException {
398
                this.open();
399
                this.resourcesBegin();
400
                try {
401
                        return this.shpFile.canWriteGeometry(geometryType);
402

    
403
                } finally {
404
                        this.resourcesEnd();
405
                }
406
        }
407

    
408
        public void performEditing(Iterator deleteds, Iterator inserteds,
409
                        Iterator updateds) throws PerformEditingException {
410
                FeatureType fType;
411
                try {
412
                        fType = this.store.getDefaultFeatureType();
413
                } catch (DataException e) {
414
                        throw new PerformEditingException(this.getName(), e);
415
                }
416
                // TODO Comprobar el campo de geometria
417

    
418
                EditableFeatureType dbfFtype = fType.getEditable();
419

    
420
                removeGeometryColumn(dbfFtype);
421

    
422
                try {
423
                        this.resourcesBegin();
424
                        this.getDBFResource().begin();
425
                } catch (ResourceBeginException e1) {
426
                        throw new PerformEditingException(this.getName(), e1);
427
                }
428

    
429
                try {
430

    
431
                        FeatureSet set = this.store.getFeatureSet();
432
                        writer = new SHPFeatureWriter(this.getName());
433

    
434
                        SHPStoreParameters tmpParams = (SHPStoreParameters) this.shpParams
435
                                        .getCopy();
436
                        tmpParams.setDBFFileName(tmpParams.getDBFFileName() + ".tmp");
437
                        tmpParams.setSHPFileName(tmpParams.getSHPFileName() + ".tmp");
438
                        tmpParams.setSHXFileName(tmpParams.getSHXFileName() + ".tmp");
439

    
440
                        writer.begin(tmpParams, fType, dbfFtype, set.getSize());
441

    
442
                        Iterator iter = set.iterator();
443
                        while (iter.hasNext()) {
444
                                Feature feature=(Feature) iter.next();
445
                                writer.append(feature);
446
                        }
447

    
448
                        writer.end();
449

    
450
                        this.close();
451

    
452
                        if (!this.shpParams.getDBFFile().delete()) {
453
                                throw new PerformEditingException(this.getName(),
454
                                                new IOException(this.shpParams.getDBFFileName()));
455
                        }
456
                        if (!this.shpParams.getSHPFile().delete()) {
457
                                throw new PerformEditingException(this.getName(),
458
                                                new IOException(this.shpParams.getSHPFileName()));
459
                        }
460
                        if (!this.shpParams.getSHXFile().delete()) {
461
                                throw new PerformEditingException(this.getName(),
462
                                                new IOException(this.shpParams.getSHXFileName()));
463
                        }
464
                        if (!tmpParams.getDBFFile().renameTo(this.shpParams.getDBFFile())) {
465
                                throw new PerformEditingException(this.getName(),
466
                                                new IOException(this.shpParams.getSHPFileName()));
467
                        }
468
                        if (!tmpParams.getSHPFile().renameTo(this.shpParams.getSHPFile())) {
469
                                throw new PerformEditingException(this.getName(),
470
                                                new IOException(this.shpParams.getSHPFileName()));
471
                        }
472
                        if (!tmpParams.getSHXFile().renameTo(this.shpParams.getSHXFile())) {
473
                                throw new PerformEditingException(this.getName(),
474
                                                new IOException(this.shpParams.getSHXFileName()));
475
                        }
476

    
477

    
478
                        this.resourcesNotifyChanges();
479
                        this.getDBFResource().notifyChanges();
480
                } catch (Exception e) {
481
                        throw new PerformEditingException(this.getName(), e);
482
                } finally {
483
                        this.resourcesEnd();
484
                        this.getDBFResource().end();
485
                }
486

    
487

    
488
        }
489

    
490
        public Envelope getEnvelope() throws DataException {
491
                this.open();
492
                return (Envelope) this.dynObject.getDynValue("Envelope");
493
        }
494

    
495
        public void setState(PersistentState state) throws PersistenceException {
496
                // TODO Auto-generated method stub
497
                super.setState(state);
498
        }
499

    
500
        public PersistentState getState() throws PersistenceException {
501
                // TODO Auto-generated method stub
502
                return super.getState();
503
        }
504

    
505
        public void append(Feature feature) throws DataException {
506
                this.resourcesBegin();
507
                try {
508
                        writer.append(feature);
509
                } finally {
510
                        this.resourcesEnd();
511
                }
512

    
513
        }
514

    
515
        public void beginAppend() throws DataException {
516
                this.resourcesBegin();
517
                try {
518

    
519
                        FeatureType fType = this.store.getDefaultFeatureType();
520

    
521
                        // TODO Comprobar el campo de geometria
522

    
523
                        EditableFeatureType dbfFtype = fType.getEditable();
524

    
525
                        removeGeometryColumn(dbfFtype);
526
                        FeatureSet set = this.store.getFeatureSet();
527

    
528
                        writer = new SHPFeatureWriter(this.getName());
529

    
530
                        writer.begin(this.shpParams, fType, dbfFtype, set.getSize());
531
                } finally {
532
                        this.resourcesEnd();
533
                }
534

    
535
        }
536

    
537
        public void endAppend() throws DataException {
538
                this.resourcesBegin();
539
                try {
540
                        writer.end();
541
                        this.resourcesNotifyChanges();
542
                } finally {
543
                        this.resourcesEnd();
544
                }
545

    
546
        }
547

    
548
        /*
549
         * (non-Javadoc)
550
         *
551
         * @see org.gvsig.metadata.Metadata#getMetadataName()
552
         */
553
        public String getMetadataName() {
554
                return this.shpParams.getSHPFile().getName();
555
        }
556

    
557
}