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 @ 727

History | View | Annotate | Download (13.5 KB)

1
/**
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
import java.util.Iterator;
27
import java.util.Map;
28
import org.apache.commons.collections.IteratorUtils;
29
import org.apache.commons.lang3.StringUtils;
30
import org.apache.commons.lang3.mutable.MutableObject;
31
import org.gvsig.expressionevaluator.Expression;
32
import org.gvsig.fmap.dal.DataStore;
33
import org.gvsig.fmap.dal.EditingNotification;
34
import org.gvsig.fmap.dal.EditingNotificationManager;
35
import org.gvsig.fmap.dal.exception.DataException;
36
import org.gvsig.fmap.dal.feature.EditableFeature;
37
import org.gvsig.fmap.dal.feature.Feature;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureReference;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
42
import org.gvsig.fmap.dal.feature.FeatureType;
43
import org.gvsig.fmap.dal.swing.DALSwingLocator;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.GeometryLocator;
46
import org.gvsig.fmap.geom.GeometryManager;
47
import org.gvsig.fmap.geom.SpatialIndex;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.tools.exception.BaseException;
50
import org.gvsig.tools.util.PropertiesSupportHelper;
51
import org.gvsig.tools.visitor.VisitCanceledException;
52
import org.gvsig.tools.visitor.Visitor;
53
import org.gvsig.topology.lib.api.CancelOperationException;
54
import org.gvsig.topology.lib.api.PerformOperationException;
55
import org.gvsig.topology.lib.api.TopologyDataSet;
56
import org.gvsig.topology.lib.api.TopologyLocator;
57
import org.gvsig.topology.lib.api.TopologyManager;
58
import org.json.JSONObject;
59
import org.gvsig.topology.lib.api.TopologyServices;
60
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62

    
63
/**
64
 *
65
 * @author jjdelcerro
66
 */
67
@SuppressWarnings({"EqualsAndHashcode","UseSpecificCatch"})
68
public class DefaultTopologyDataSet implements TopologyDataSet {
69

    
70
    private final static Logger LOGGER = LoggerFactory.getLogger(DefaultTopologyDataSet.class);
71
    
72
    private TopologyServices services;
73
    private String name;
74
    private DataStore store;
75
    private boolean needFinishEditing;
76
    private String fullName;
77
    private PropertiesSupportHelper propertiesHelper;
78
    private MutableObject<SpatialIndex> spatialIndex = null;
79
    
80
    public DefaultTopologyDataSet() {
81
        this.services = null;
82
        this.name = null;
83
        this.store = null;
84
        this.needFinishEditing = false;
85
        this.fullName = null;
86
        this.propertiesHelper = new PropertiesSupportHelper();
87
    }
88

    
89
    public DefaultTopologyDataSet(TopologyServices services, String name, DataStore store) {
90
        this.services = services;
91
        this.name = name;
92
        this.store = store;
93
        this.needFinishEditing = false;
94
        if( store!=null ) {
95
            this.fullName = store.getFullName();
96
        }
97
    }
98

    
99
    public void restart() {
100
        this.store  = null;
101
        this.spatialIndex = null;
102
    }
103
    
104
    @Override
105
    public boolean equals(Object obj) {
106
        if( !(obj instanceof DefaultTopologyDataSet) ) {
107
            return false;
108
        }
109
        DefaultTopologyDataSet other = (DefaultTopologyDataSet)obj;
110
        if( this.store != other.store ) {
111
            return false;
112
        }
113
        if( !StringUtils.equals(this.getName(), other.getName()) ) {
114
            return false;
115
        }
116
        return true;
117
    }
118

    
119
    @Override
120
    public String getName() {
121
        return this.name;
122
    }
123

    
124
    @Override
125
    public void setName(String name) {
126
        this.name = name;
127
    }
128

    
129
    @Override
130
    public String toString() {
131
        try {
132
            FeatureAttributeDescriptor attr = this.getFeatureStore().getDefaultFeatureType().getDefaultGeometryAttribute();
133
            String geomType = attr.getGeomType().getName();
134
            return this.name + " ("+ geomType + ")";
135
        } catch(Exception ex) {
136
            return this.name ;
137
        }
138
    }
139

    
140
    @Override
141
    public DataStore getStore() {
142
        if (this.store == null) {
143
            this.store = this.services.getFeatureStore(this);
144
        }
145
        return this.store;
146
    }
147

    
148
    @Override
149
    public FeatureStore getFeatureStore() {
150
        if (this.store == null) {
151
            this.store = this.services.getFeatureStore(this);
152
        }
153
        return (FeatureStore) this.store;
154
    }
155

    
156
    @Override
157
    public long getSize() {
158
        try {
159
            long size = this.getFeatureStore().getFeatureCount();
160
            return size;
161
        } catch (DataException ex) {
162
            // TODO: mensage al log
163
            return 0;
164
        }
165
    }
166

    
167
    @Override
168
    public boolean isThisStore(FeatureStore store) {
169
        if( store == null ) {
170
            return false;
171
        }
172
        return StringUtils.equals(this.fullName, store.getFullName());
173
    }
174
    
175
    @Override
176
    public int getGeometryType() {
177
        try {
178
            FeatureStore theStore = this.getFeatureStore();
179
            FeatureType featureType = theStore.getDefaultFeatureType();
180
            FeatureAttributeDescriptor attr = featureType.getDefaultGeometryAttribute();
181
            GeometryType geomType = attr.getGeomType();
182
            return geomType.getType();
183
        } catch (Exception ex) {
184
            return Geometry.TYPES.GEOMETRY;
185
        }
186
    }
187

    
188
    @Override
189
    public void accept(Visitor visitor) throws VisitCanceledException {
190
        FeatureStore st = this.getFeatureStore();
191
        try {
192
            st.accept(visitor);
193
        } catch(VisitCanceledException ex) {
194
            throw ex;
195
        } catch(BaseException ex) {
196
            throw new RuntimeException(ex);
197
        }
198
    }
199

    
200
    @Override
201
    public void edit() throws DataException {
202
        FeatureStore theStore = this.getFeatureStore();
203
        if (!theStore.isEditing()) {
204
            theStore.edit();
205
            this.needFinishEditing = true;
206
        }
207
    }
208

    
209
    @Override
210
    public void finishEditing() throws DataException {
211
        if (this.needFinishEditing) {
212
            this.getFeatureStore().finishEditing();
213
        }
214
    }
215

    
216
    @Override
217
    public EditableFeature createNewFeature() throws DataException {
218
        EditableFeature f = this.getFeatureStore().createNewFeature();
219
        return f;
220
    }
221

    
222
    public void perform(
223
            String operation,
224
            Feature feature
225
    ) throws DataException {
226
        this.edit();
227

    
228
        EditingNotificationManager editingNotificationManager
229
                = DALSwingLocator.getEditingNotificationManager();
230
        FeatureStore theStore = this.getFeatureStore();
231
        
232
        EditingNotification notification
233
                = editingNotificationManager.notifyObservers(this, // source
234
                        operation, // type
235
                        null,// document
236
                        null,// layer
237
                        theStore,// store
238
                        feature// feature
239
                );
240

    
241
        if (notification.isCanceled()) {
242
            String msg = String.format(
243
                    "Can't insert feature into %1$s, canceled by some observer.",
244
                    this.getName());
245
            throw new CancelOperationException(msg);
246
        }
247
        
248
        String after = null;
249
        if( operation.equalsIgnoreCase(EditingNotification.BEFORE_REMOVE_FEATURE) ) {
250
            theStore.delete(feature);
251
            after = EditingNotification.AFTER_REMOVE_FEATURE;
252
            
253
        } else {
254
            if (notification.shouldValidateTheFeature()) {
255
                if (!editingNotificationManager.validateFeature(feature)) {
256
                    String msg = String.format("%1$s is not valid", feature.toString());
257
                    throw new PerformOperationException(msg);
258
                }
259
            }
260
            switch(operation) {
261
                case EditingNotification.BEFORE_UPDATE_FEATURE:
262
                    theStore.update((EditableFeature) feature);
263
                    after = EditingNotification.AFTER_UPDATE_FEATURE;
264
                    break;
265

    
266
                case EditingNotification.BEFORE_INSERT_FEATURE:
267
                    theStore.insert((EditableFeature) feature);
268
                    after = EditingNotification.AFTER_INSERT_FEATURE;
269
                    break;
270
            }
271
        }
272

    
273
        editingNotificationManager.notifyObservers(this,
274
                after, null, null,
275
                theStore, feature);
276

    
277
    }
278

    
279
    @Override
280
    public void insert(final EditableFeature feature) throws DataException {
281
        perform(
282
            EditingNotification.BEFORE_INSERT_FEATURE,
283
            feature
284
        );
285
    }
286

    
287
    @Override
288
    public void update(final EditableFeature feature) throws DataException {
289
        perform(
290
            EditingNotification.BEFORE_UPDATE_FEATURE,
291
            feature
292
        );
293
    }
294

    
295
    @Override
296
    public void delete(final Feature feature) throws DataException {
297
        perform(
298
            EditingNotification.BEFORE_REMOVE_FEATURE,
299
            feature
300
        );
301
    }
302

    
303
    @Override
304
    public void delete(final FeatureReference feature) throws DataException {
305
        perform(
306
            EditingNotification.BEFORE_REMOVE_FEATURE,
307
            feature.getFeature()
308
        );
309
    }
310

    
311
    @Override
312
    public JSONObject toJSON() {
313
        JSONObject jsonDataSet = new JSONObject();
314
        jsonDataSet.put("name", this.name);
315
        jsonDataSet.put("fullName", this.fullName);
316

    
317
        return jsonDataSet;
318
    }
319

    
320
    @Override
321
    public void fromJSON(String json) {
322
        this.fromJSON(new JSONObject(json));
323
    }
324

    
325
    @Override
326
    public void fromJSON(JSONObject json) {
327
        TopologyManager manager = TopologyLocator.getTopologyManager();
328
        this.name = json.getString("name");
329
        this.fullName = null;
330
        if( json.has("fullName") ) {
331
            this.fullName = json.getString("fullName");
332
        }
333
        this.store = null;
334
        this.needFinishEditing = false;
335
        this.services = manager.getDefaultServices();
336
    }
337

    
338
    @Override
339
    public Object getProperty(String string) {
340
        return this.propertiesHelper.getProperty(name);
341
    }
342

    
343
    @Override
344
    public void setProperty(String string, Object o) {
345
        this.propertiesHelper.setProperty(name, o);
346
    }
347

    
348
    @Override
349
    public Map<String, Object> getProperties() {
350
        return this.propertiesHelper.getProperties();
351
    }
352

    
353
    public SpatialIndex getSpatialIndex() {
354
        if( this.spatialIndex == null ) {
355
            this.spatialIndex = new MutableObject<>();
356
            FeatureStore theStore = this.getFeatureStore();
357
            FeatureStoreProviderFactory storeFactory = (FeatureStoreProviderFactory) theStore.getProviderFactory();
358
            if( storeFactory.useLocalIndexesCanImprovePerformance()==FeatureStoreProviderFactory.YES ) {
359
                try {
360
                    GeometryManager geomManager = GeometryLocator.getGeometryManager();
361
                    final SpatialIndex geomIndex = geomManager.createSpatialIndex(
362
                            GeometryManager.SPATIALINDEX_DEFAULT_QUADTREE,
363
                            null
364
                    );
365
                    final SpatialIndex dataIndex = theStore.wrapSpatialIndex(geomIndex);
366
                    try {
367
                        store.accept(new Visitor() {
368
                            @Override
369
                            public void visit(Object o) throws VisitCanceledException, BaseException {
370
                                Feature f = (Feature) o;
371
                                Geometry geom = f.getDefaultGeometry();
372
                                if (geom != null) {
373
                                    dataIndex.insert(geom, f);
374
                                }
375
                            }
376
                        });
377
                    } catch (VisitCanceledException ex) {
378
                    }
379
                    this.spatialIndex.setValue(dataIndex);
380
                } catch (Exception ex) {
381
                    LOGGER.warn("Can't create spatial index", ex);
382
                }
383
            }
384
        }
385
        return this.spatialIndex.getValue();
386
    }
387

    
388
    public Iterable<FeatureReference> query(Geometry geom) {
389
        SpatialIndex index = this.getSpatialIndex();
390
        if( index == null ) {
391
            return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
392
        }
393
        final Iterator it = index.query(geom);
394
        if( it == null ) {
395
            return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
396
        }
397
        return new Iterable<FeatureReference>() {
398
            @Override
399
            public Iterator<FeatureReference> iterator() {
400
                return it;
401
            }
402
        };
403
    }
404

    
405
    @Override
406
    public Feature findFirst(Expression filter) {
407
        try {
408
            return this.getFeatureStore().findFirst(filter);
409
        } catch (Exception ex) {
410
            return null;
411
        }
412
    }
413

    
414
}