Statistics
| Revision:

gvsig-projects-pool / org.gvsig.topology / trunk / org.gvsig.topology / org.gvsig.topology.lib / org.gvsig.topology.lib.impl / src / main / java / org / gvsig / topology / lib / impl / DefaultTopologyDataSet.java @ 2067

History | View | Annotate | Download (19.6 KB)

1 688 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.topology.lib.impl;
25
26 725 jjdelcerro
import java.util.Iterator;
27 721 jjdelcerro
import java.util.Map;
28 725 jjdelcerro
import org.apache.commons.collections.IteratorUtils;
29 688 jjdelcerro
import org.apache.commons.lang3.StringUtils;
30 725 jjdelcerro
import org.apache.commons.lang3.mutable.MutableObject;
31
import org.gvsig.expressionevaluator.Expression;
32 2067 jolivas
import org.gvsig.expressionevaluator.ExpressionBuilder;
33
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
34
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
35 1284 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionUtils;
36
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
37
import org.gvsig.expressionevaluator.GeometryExpressionUtils;
38 727 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
39 688 jjdelcerro
import org.gvsig.fmap.dal.EditingNotification;
40
import org.gvsig.fmap.dal.EditingNotificationManager;
41
import org.gvsig.fmap.dal.exception.DataException;
42
import org.gvsig.fmap.dal.feature.EditableFeature;
43
import org.gvsig.fmap.dal.feature.Feature;
44
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.FeatureReference;
46 894 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
47 688 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
48 725 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
49 688 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
50
import org.gvsig.fmap.dal.swing.DALSwingLocator;
51
import org.gvsig.fmap.geom.Geometry;
52 725 jjdelcerro
import org.gvsig.fmap.geom.GeometryLocator;
53
import org.gvsig.fmap.geom.GeometryManager;
54 894 jjdelcerro
import org.gvsig.fmap.geom.GeometryUtils;
55 725 jjdelcerro
import org.gvsig.fmap.geom.SpatialIndex;
56 688 jjdelcerro
import org.gvsig.fmap.geom.type.GeometryType;
57 894 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
58 688 jjdelcerro
import org.gvsig.tools.exception.BaseException;
59 721 jjdelcerro
import org.gvsig.tools.util.PropertiesSupportHelper;
60 722 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
61 688 jjdelcerro
import org.gvsig.tools.visitor.Visitor;
62
import org.gvsig.topology.lib.api.CancelOperationException;
63
import org.gvsig.topology.lib.api.PerformOperationException;
64
import org.gvsig.topology.lib.api.TopologyDataSet;
65
import org.gvsig.topology.lib.api.TopologyLocator;
66
import org.gvsig.topology.lib.api.TopologyManager;
67
import org.json.JSONObject;
68
import org.gvsig.topology.lib.api.TopologyServices;
69 725 jjdelcerro
import org.slf4j.Logger;
70
import org.slf4j.LoggerFactory;
71 688 jjdelcerro
72
/**
73
 *
74
 * @author jjdelcerro
75
 */
76
@SuppressWarnings({"EqualsAndHashcode","UseSpecificCatch"})
77
public class DefaultTopologyDataSet implements TopologyDataSet {
78
79 725 jjdelcerro
    private final static Logger LOGGER = LoggerFactory.getLogger(DefaultTopologyDataSet.class);
80
81 688 jjdelcerro
    private TopologyServices services;
82
    private String name;
83 727 jjdelcerro
    private DataStore store;
84 688 jjdelcerro
    private boolean needFinishEditing;
85
    private String fullName;
86 721 jjdelcerro
    private PropertiesSupportHelper propertiesHelper;
87 725 jjdelcerro
    private MutableObject<SpatialIndex> spatialIndex = null;
88
89 688 jjdelcerro
    public DefaultTopologyDataSet() {
90
        this.services = null;
91
        this.name = null;
92
        this.store = null;
93
        this.needFinishEditing = false;
94
        this.fullName = null;
95 721 jjdelcerro
        this.propertiesHelper = new PropertiesSupportHelper();
96 688 jjdelcerro
    }
97
98 727 jjdelcerro
    public DefaultTopologyDataSet(TopologyServices services, String name, DataStore store) {
99 688 jjdelcerro
        this.services = services;
100
        this.name = name;
101
        this.store = store;
102
        this.needFinishEditing = false;
103
        if( store!=null ) {
104
            this.fullName = store.getFullName();
105
        }
106
    }
107
108 894 jjdelcerro
    @Override
109 726 jjdelcerro
    public void restart() {
110
        this.store  = null;
111
        this.spatialIndex = null;
112
    }
113
114 688 jjdelcerro
    @Override
115
    public boolean equals(Object obj) {
116
        if( !(obj instanceof DefaultTopologyDataSet) ) {
117
            return false;
118
        }
119
        DefaultTopologyDataSet other = (DefaultTopologyDataSet)obj;
120
        if( this.store != other.store ) {
121
            return false;
122
        }
123
        if( !StringUtils.equals(this.getName(), other.getName()) ) {
124
            return false;
125
        }
126
        return true;
127
    }
128
129
    @Override
130
    public String getName() {
131
        return this.name;
132
    }
133
134
    @Override
135
    public void setName(String name) {
136
        this.name = name;
137
    }
138
139
    @Override
140
    public String toString() {
141
        try {
142 727 jjdelcerro
            FeatureAttributeDescriptor attr = this.getFeatureStore().getDefaultFeatureType().getDefaultGeometryAttribute();
143 688 jjdelcerro
            String geomType = attr.getGeomType().getName();
144
            return this.name + " ("+ geomType + ")";
145
        } catch(Exception ex) {
146
            return this.name ;
147
        }
148
    }
149
150
    @Override
151 727 jjdelcerro
    public DataStore getStore() {
152 688 jjdelcerro
        if (this.store == null) {
153
            this.store = this.services.getFeatureStore(this);
154
        }
155
        return this.store;
156
    }
157
158
    @Override
159 727 jjdelcerro
    public FeatureStore getFeatureStore() {
160
        if (this.store == null) {
161
            this.store = this.services.getFeatureStore(this);
162
        }
163
        return (FeatureStore) this.store;
164
    }
165
166
    @Override
167 688 jjdelcerro
    public long getSize() {
168
        try {
169 727 jjdelcerro
            long size = this.getFeatureStore().getFeatureCount();
170 688 jjdelcerro
            return size;
171
        } catch (DataException ex) {
172
            // TODO: mensage al log
173
            return 0;
174
        }
175
    }
176
177
    @Override
178
    public boolean isThisStore(FeatureStore store) {
179
        if( store == null ) {
180
            return false;
181
        }
182
        return StringUtils.equals(this.fullName, store.getFullName());
183
    }
184
185
    @Override
186
    public int getGeometryType() {
187
        try {
188 727 jjdelcerro
            FeatureStore theStore = this.getFeatureStore();
189 688 jjdelcerro
            FeatureType featureType = theStore.getDefaultFeatureType();
190
            FeatureAttributeDescriptor attr = featureType.getDefaultGeometryAttribute();
191
            GeometryType geomType = attr.getGeomType();
192
            return geomType.getType();
193
        } catch (Exception ex) {
194
            return Geometry.TYPES.GEOMETRY;
195
        }
196
    }
197
198
    @Override
199 722 jjdelcerro
    public void accept(Visitor visitor) throws VisitCanceledException {
200 727 jjdelcerro
        FeatureStore st = this.getFeatureStore();
201 688 jjdelcerro
        try {
202
            st.accept(visitor);
203 722 jjdelcerro
        } catch(VisitCanceledException ex) {
204
            throw ex;
205
        } catch(BaseException ex) {
206 688 jjdelcerro
            throw new RuntimeException(ex);
207
        }
208
    }
209
210
    @Override
211
    public void edit() throws DataException {
212 727 jjdelcerro
        FeatureStore theStore = this.getFeatureStore();
213 688 jjdelcerro
        if (!theStore.isEditing()) {
214
            theStore.edit();
215
            this.needFinishEditing = true;
216
        }
217
    }
218
219
    @Override
220
    public void finishEditing() throws DataException {
221
        if (this.needFinishEditing) {
222 727 jjdelcerro
            this.getFeatureStore().finishEditing();
223 688 jjdelcerro
        }
224
    }
225
226
    @Override
227
    public EditableFeature createNewFeature() throws DataException {
228 727 jjdelcerro
        EditableFeature f = this.getFeatureStore().createNewFeature();
229 688 jjdelcerro
        return f;
230
    }
231
232
    public void perform(
233
            String operation,
234
            Feature feature
235
    ) throws DataException {
236
        this.edit();
237
238
        EditingNotificationManager editingNotificationManager
239
                = DALSwingLocator.getEditingNotificationManager();
240 727 jjdelcerro
        FeatureStore theStore = this.getFeatureStore();
241 688 jjdelcerro
242
        EditingNotification notification
243
                = editingNotificationManager.notifyObservers(this, // source
244
                        operation, // type
245
                        null,// document
246
                        null,// layer
247
                        theStore,// store
248
                        feature// feature
249
                );
250
251
        if (notification.isCanceled()) {
252
            String msg = String.format(
253
                    "Can't insert feature into %1$s, canceled by some observer.",
254
                    this.getName());
255
            throw new CancelOperationException(msg);
256
        }
257
258
        String after = null;
259
        if( operation.equalsIgnoreCase(EditingNotification.BEFORE_REMOVE_FEATURE) ) {
260
            theStore.delete(feature);
261
            after = EditingNotification.AFTER_REMOVE_FEATURE;
262
263
        } else {
264
            if (notification.shouldValidateTheFeature()) {
265
                if (!editingNotificationManager.validateFeature(feature)) {
266
                    String msg = String.format("%1$s is not valid", feature.toString());
267
                    throw new PerformOperationException(msg);
268
                }
269
            }
270
            switch(operation) {
271
                case EditingNotification.BEFORE_UPDATE_FEATURE:
272
                    theStore.update((EditableFeature) feature);
273
                    after = EditingNotification.AFTER_UPDATE_FEATURE;
274
                    break;
275
276
                case EditingNotification.BEFORE_INSERT_FEATURE:
277
                    theStore.insert((EditableFeature) feature);
278
                    after = EditingNotification.AFTER_INSERT_FEATURE;
279
                    break;
280
            }
281
        }
282
283
        editingNotificationManager.notifyObservers(this,
284
                after, null, null,
285
                theStore, feature);
286
287
    }
288
289
    @Override
290
    public void insert(final EditableFeature feature) throws DataException {
291
        perform(
292
            EditingNotification.BEFORE_INSERT_FEATURE,
293
            feature
294
        );
295
    }
296
297
    @Override
298
    public void update(final EditableFeature feature) throws DataException {
299
        perform(
300
            EditingNotification.BEFORE_UPDATE_FEATURE,
301
            feature
302
        );
303
    }
304
305
    @Override
306
    public void delete(final Feature feature) throws DataException {
307
        perform(
308
            EditingNotification.BEFORE_REMOVE_FEATURE,
309
            feature
310
        );
311
    }
312
313
    @Override
314
    public void delete(final FeatureReference feature) throws DataException {
315
        perform(
316
            EditingNotification.BEFORE_REMOVE_FEATURE,
317
            feature.getFeature()
318
        );
319
    }
320
321
    @Override
322
    public JSONObject toJSON() {
323
        JSONObject jsonDataSet = new JSONObject();
324
        jsonDataSet.put("name", this.name);
325
        jsonDataSet.put("fullName", this.fullName);
326
327
        return jsonDataSet;
328
    }
329
330
    @Override
331
    public void fromJSON(String json) {
332
        this.fromJSON(new JSONObject(json));
333
    }
334
335
    @Override
336
    public void fromJSON(JSONObject json) {
337
        TopologyManager manager = TopologyLocator.getTopologyManager();
338
        this.name = json.getString("name");
339
        this.fullName = null;
340
        if( json.has("fullName") ) {
341
            this.fullName = json.getString("fullName");
342
        }
343
        this.store = null;
344
        this.needFinishEditing = false;
345
        this.services = manager.getDefaultServices();
346
    }
347
348 721 jjdelcerro
    @Override
349
    public Object getProperty(String string) {
350
        return this.propertiesHelper.getProperty(name);
351
    }
352
353
    @Override
354
    public void setProperty(String string, Object o) {
355
        this.propertiesHelper.setProperty(name, o);
356
    }
357
358
    @Override
359
    public Map<String, Object> getProperties() {
360
        return this.propertiesHelper.getProperties();
361
    }
362
363 894 jjdelcerro
    @Override
364 725 jjdelcerro
    public SpatialIndex getSpatialIndex() {
365
        if( this.spatialIndex == null ) {
366
            this.spatialIndex = new MutableObject<>();
367 727 jjdelcerro
            FeatureStore theStore = this.getFeatureStore();
368 725 jjdelcerro
            FeatureStoreProviderFactory storeFactory = (FeatureStoreProviderFactory) theStore.getProviderFactory();
369
            if( storeFactory.useLocalIndexesCanImprovePerformance()==FeatureStoreProviderFactory.YES ) {
370
                try {
371
                    GeometryManager geomManager = GeometryLocator.getGeometryManager();
372
                    final SpatialIndex geomIndex = geomManager.createSpatialIndex(
373
                            GeometryManager.SPATIALINDEX_DEFAULT_QUADTREE,
374
                            null
375
                    );
376
                    final SpatialIndex dataIndex = theStore.wrapSpatialIndex(geomIndex);
377
                    try {
378 2067 jolivas
                        store.accept(new Visitor() {
379
                            @Override
380
                            public void visit(Object o) throws VisitCanceledException, BaseException {
381
                                Feature f = (Feature) o;
382
                                Geometry geom = f.getDefaultGeometry();
383
                                if (geom != null) {
384
                                    dataIndex.insert(geom, f);
385
                                }
386 725 jjdelcerro
                            }
387
                        });
388
                    } catch (VisitCanceledException ex) {
389
                    }
390
                    this.spatialIndex.setValue(dataIndex);
391
                } catch (Exception ex) {
392
                    LOGGER.warn("Can't create spatial index", ex);
393
                }
394
            }
395
        }
396
        return this.spatialIndex.getValue();
397
    }
398
399 894 jjdelcerro
    @Override
400 725 jjdelcerro
    public Iterable<FeatureReference> query(Geometry geom) {
401 894 jjdelcerro
        return this.queryReferences(geom);
402
    }
403
404
    @Override
405
    public Iterable<FeatureReference> queryReferences(Geometry geom) {
406 725 jjdelcerro
        SpatialIndex index = this.getSpatialIndex();
407
        if( index == null ) {
408 894 jjdelcerro
            try {
409
                FeatureStore theStore = (FeatureStore) this.getStore();
410 1284 jjdelcerro
                Expression expression = ExpressionUtils.createExpression();
411
                GeometryExpressionBuilder expressionBuilder = GeometryExpressionUtils.createExpressionBuilder();
412 894 jjdelcerro
                String geomName = theStore.getDefaultFeatureType().getDefaultGeometryAttributeName();
413
                if( GeometryUtils.isSubtype(Geometry.TYPES.POINT, geom.getType()) )  {
414
                    expression.setPhrase(
415
                        expressionBuilder.ifnull(
416
                            expressionBuilder.column(geomName),
417
                            expressionBuilder.constant(false),
418
                            expressionBuilder.ST_Intersects(
419
                                    expressionBuilder.column(geomName),
420
                                    expressionBuilder.geometry(geom)
421
                            )
422
                        ).toString()
423
                    );
424
                } else {
425
                    expression.setPhrase(
426
                        expressionBuilder.ifnull(
427
                            expressionBuilder.column(geomName),
428
                            expressionBuilder.constant(false),
429
                            expressionBuilder.ST_Overlaps(
430
                                    expressionBuilder.column(geomName),
431
                                    expressionBuilder.envelope(geom.getEnvelope())
432
                            )
433
                        ).toString()
434
                    );
435
                }
436
                FeatureSet set = theStore.getFeatureSet(expression);
437
                final DisposableIterator it = set.fastIterator();
438 2067 jolivas
                return new Iterable<FeatureReference>() {
439 894 jjdelcerro
                    @Override
440 2067 jolivas
                    public Iterator<FeatureReference> iterator() {
441
                        return new Iterator<FeatureReference>() {
442
                            @Override
443
                            public boolean hasNext() {
444
                                return it.hasNext();
445
                            }
446
447
                            @Override
448
                            public FeatureReference next() {
449
                                Feature f = (Feature) it.next();
450
                                return f.getReference();
451
                            }
452
                        };
453 894 jjdelcerro
                    }
454
                };
455
456
            } catch(Exception ex) {
457
                return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
458
            }
459 725 jjdelcerro
        }
460
        final Iterator it = index.query(geom);
461
        if( it == null ) {
462
            return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
463
        }
464 2067 jolivas
        return new Iterable<FeatureReference>() {
465
            @Override
466
            public Iterator<FeatureReference> iterator() {
467
                return it;
468
            }
469
        };
470 725 jjdelcerro
    }
471
472
    @Override
473 894 jjdelcerro
    public Iterable<Feature> queryFeatures(Geometry geom) {
474
        SpatialIndex index = this.getSpatialIndex();
475
        if( index == null ) {
476
            try {
477
                FeatureStore theStore = (FeatureStore) this.getStore();
478 1284 jjdelcerro
                Expression expression = ExpressionUtils.createExpression();
479
                GeometryExpressionBuilder expressionBuilder = GeometryExpressionUtils.createExpressionBuilder();
480 894 jjdelcerro
                String geomName = theStore.getDefaultFeatureType().getDefaultGeometryAttributeName();
481
                if( GeometryUtils.isSubtype(Geometry.TYPES.POINT, geom.getType()) )  {
482
                    expression.setPhrase(
483
                        expressionBuilder.ifnull(
484
                            expressionBuilder.column(geomName),
485
                            expressionBuilder.constant(false),
486
                            expressionBuilder.ST_Intersects(
487
                                    expressionBuilder.column(geomName),
488
                                    expressionBuilder.geometry(geom)
489
                            )
490
                        ).toString()
491
                    );
492
                } else {
493
                    expression.setPhrase(
494
                        expressionBuilder.ifnull(
495
                            expressionBuilder.column(geomName),
496
                            expressionBuilder.constant(false),
497
                            expressionBuilder.ST_Overlaps(
498
                                    expressionBuilder.column(geomName),
499
                                    expressionBuilder.envelope(geom.getEnvelope())
500
                            )
501
                        ).toString()
502
                    );
503
                }
504
                FeatureSet set = theStore.getFeatureSet(expression);
505
                final DisposableIterator it = set.fastIterator();
506 2067 jolivas
                return new Iterable<Feature>() {
507
                    @Override
508
                    public Iterator<Feature> iterator() {
509
                        return it;
510
                    }
511
                };
512 894 jjdelcerro
513
            } catch(Exception ex) {
514
                return (Iterable<Feature>) IteratorUtils.EMPTY_ITERATOR;
515
            }
516
        }
517
        final Iterator it = index.query(geom);
518
        if( it == null ) {
519
            return (Iterable<Feature>) IteratorUtils.EMPTY_ITERATOR;
520
        }
521 2067 jolivas
        return new Iterable<Feature>() {
522 894 jjdelcerro
            @Override
523 2067 jolivas
            public Iterator<Feature> iterator() {
524
                return new Iterator<Feature>() {
525
                    @Override
526
                    public boolean hasNext() {
527
                        return it.hasNext();
528
                    }
529
530
                    @Override
531
                    public Feature next() {
532
                        FeatureReference ref = (FeatureReference) it.next();
533
                        try {
534
                            return ref.getFeature();
535
                        } catch (DataException ex) {
536
                            return null;
537
                        }
538
                    }
539
                };
540 894 jjdelcerro
            }
541
        };
542
    }
543
544
    @Override
545 725 jjdelcerro
    public Feature findFirst(Expression filter) {
546
        try {
547 727 jjdelcerro
            return this.getFeatureStore().findFirst(filter);
548 725 jjdelcerro
        } catch (Exception ex) {
549
            return null;
550
        }
551
    }
552
553 688 jjdelcerro
}