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

History | View | Annotate | Download (13.1 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.EditingNotification;
33
import org.gvsig.fmap.dal.EditingNotificationManager;
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureReference;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.dal.swing.DALSwingLocator;
43
import org.gvsig.fmap.geom.Geometry;
44
import org.gvsig.fmap.geom.GeometryLocator;
45
import org.gvsig.fmap.geom.GeometryManager;
46
import org.gvsig.fmap.geom.SpatialIndex;
47
import org.gvsig.fmap.geom.type.GeometryType;
48
import org.gvsig.tools.exception.BaseException;
49
import org.gvsig.tools.util.PropertiesSupportHelper;
50
import org.gvsig.tools.visitor.VisitCanceledException;
51
import org.gvsig.tools.visitor.Visitor;
52
import org.gvsig.topology.lib.api.CancelOperationException;
53
import org.gvsig.topology.lib.api.PerformOperationException;
54
import org.gvsig.topology.lib.api.TopologyDataSet;
55
import org.gvsig.topology.lib.api.TopologyLocator;
56
import org.gvsig.topology.lib.api.TopologyManager;
57
import org.json.JSONObject;
58
import org.gvsig.topology.lib.api.TopologyServices;
59
import org.slf4j.Logger;
60
import org.slf4j.LoggerFactory;
61

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

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

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

    
98
    @Override
99
    public boolean equals(Object obj) {
100
        if( !(obj instanceof DefaultTopologyDataSet) ) {
101
            return false;
102
        }
103
        DefaultTopologyDataSet other = (DefaultTopologyDataSet)obj;
104
        if( this.store != other.store ) {
105
            return false;
106
        }
107
        if( !StringUtils.equals(this.getName(), other.getName()) ) {
108
            return false;
109
        }
110
        return true;
111
    }
112

    
113
    @Override
114
    public String getName() {
115
        return this.name;
116
    }
117

    
118
    @Override
119
    public void setName(String name) {
120
        this.name = name;
121
    }
122

    
123
    @Override
124
    public String toString() {
125
        try {
126
            FeatureAttributeDescriptor attr = this.getStore().getDefaultFeatureType().getDefaultGeometryAttribute();
127
            String geomType = attr.getGeomType().getName();
128
            return this.name + " ("+ geomType + ")";
129
        } catch(Exception ex) {
130
            return this.name ;
131
        }
132
    }
133

    
134
    @Override
135
    public FeatureStore getStore() {
136
        if (this.store == null) {
137
            this.store = this.services.getFeatureStore(this);
138
        }
139
        return this.store;
140
    }
141

    
142
    @Override
143
    public long getSize() {
144
        try {
145
            long size = this.getStore().getFeatureCount();
146
            return size;
147
        } catch (DataException ex) {
148
            // TODO: mensage al log
149
            return 0;
150
        }
151
    }
152

    
153
    @Override
154
    public boolean isThisStore(FeatureStore store) {
155
        if( store == null ) {
156
            return false;
157
        }
158
        return StringUtils.equals(this.fullName, store.getFullName());
159
    }
160
    
161
    @Override
162
    public int getGeometryType() {
163
        try {
164
            FeatureStore theStore = this.getStore();
165
            FeatureType featureType = theStore.getDefaultFeatureType();
166
            FeatureAttributeDescriptor attr = featureType.getDefaultGeometryAttribute();
167
            GeometryType geomType = attr.getGeomType();
168
            return geomType.getType();
169
        } catch (Exception ex) {
170
            return Geometry.TYPES.GEOMETRY;
171
        }
172
    }
173

    
174
    @Override
175
    public void accept(Visitor visitor) throws VisitCanceledException {
176
        FeatureStore st = this.getStore();
177
        try {
178
            st.accept(visitor);
179
        } catch(VisitCanceledException ex) {
180
            throw ex;
181
        } catch(BaseException ex) {
182
            throw new RuntimeException(ex);
183
        }
184
    }
185

    
186
    @Override
187
    public void edit() throws DataException {
188
        FeatureStore theStore = this.getStore();
189
        if (!theStore.isEditing()) {
190
            theStore.edit();
191
            this.needFinishEditing = true;
192
        }
193
    }
194

    
195
    @Override
196
    public void finishEditing() throws DataException {
197
        if (this.needFinishEditing) {
198
            this.getStore().finishEditing();
199
        }
200
    }
201

    
202
    @Override
203
    public EditableFeature createNewFeature() throws DataException {
204
        EditableFeature f = this.getStore().createNewFeature();
205
        return f;
206
    }
207

    
208
    public void perform(
209
            String operation,
210
            Feature feature
211
    ) throws DataException {
212
        this.edit();
213

    
214
        EditingNotificationManager editingNotificationManager
215
                = DALSwingLocator.getEditingNotificationManager();
216
        FeatureStore theStore = this.getStore();
217
        
218
        EditingNotification notification
219
                = editingNotificationManager.notifyObservers(this, // source
220
                        operation, // type
221
                        null,// document
222
                        null,// layer
223
                        theStore,// store
224
                        feature// feature
225
                );
226

    
227
        if (notification.isCanceled()) {
228
            String msg = String.format(
229
                    "Can't insert feature into %1$s, canceled by some observer.",
230
                    this.getName());
231
            throw new CancelOperationException(msg);
232
        }
233
        
234
        String after = null;
235
        if( operation.equalsIgnoreCase(EditingNotification.BEFORE_REMOVE_FEATURE) ) {
236
            theStore.delete(feature);
237
            after = EditingNotification.AFTER_REMOVE_FEATURE;
238
            
239
        } else {
240
            if (notification.shouldValidateTheFeature()) {
241
                if (!editingNotificationManager.validateFeature(feature)) {
242
                    String msg = String.format("%1$s is not valid", feature.toString());
243
                    throw new PerformOperationException(msg);
244
                }
245
            }
246
            switch(operation) {
247
                case EditingNotification.BEFORE_UPDATE_FEATURE:
248
                    theStore.update((EditableFeature) feature);
249
                    after = EditingNotification.AFTER_UPDATE_FEATURE;
250
                    break;
251

    
252
                case EditingNotification.BEFORE_INSERT_FEATURE:
253
                    theStore.insert((EditableFeature) feature);
254
                    after = EditingNotification.AFTER_INSERT_FEATURE;
255
                    break;
256
            }
257
        }
258

    
259
        editingNotificationManager.notifyObservers(this,
260
                after, null, null,
261
                theStore, feature);
262

    
263
    }
264

    
265
    @Override
266
    public void insert(final EditableFeature feature) throws DataException {
267
        perform(
268
            EditingNotification.BEFORE_INSERT_FEATURE,
269
            feature
270
        );
271
    }
272

    
273
    @Override
274
    public void update(final EditableFeature feature) throws DataException {
275
        perform(
276
            EditingNotification.BEFORE_UPDATE_FEATURE,
277
            feature
278
        );
279
    }
280

    
281
    @Override
282
    public void delete(final Feature feature) throws DataException {
283
        perform(
284
            EditingNotification.BEFORE_REMOVE_FEATURE,
285
            feature
286
        );
287
    }
288

    
289
    @Override
290
    public void delete(final FeatureReference feature) throws DataException {
291
        perform(
292
            EditingNotification.BEFORE_REMOVE_FEATURE,
293
            feature.getFeature()
294
        );
295
    }
296

    
297
    @Override
298
    public JSONObject toJSON() {
299
        JSONObject jsonDataSet = new JSONObject();
300
        jsonDataSet.put("name", this.name);
301
        jsonDataSet.put("fullName", this.fullName);
302

    
303
        return jsonDataSet;
304
    }
305

    
306
    @Override
307
    public void fromJSON(String json) {
308
        this.fromJSON(new JSONObject(json));
309
    }
310

    
311
    @Override
312
    public void fromJSON(JSONObject json) {
313
        TopologyManager manager = TopologyLocator.getTopologyManager();
314
        this.name = json.getString("name");
315
        this.fullName = null;
316
        if( json.has("fullName") ) {
317
            this.fullName = json.getString("fullName");
318
        }
319
        this.store = null;
320
        this.needFinishEditing = false;
321
        this.services = manager.getDefaultServices();
322
    }
323

    
324
    @Override
325
    public Object getProperty(String string) {
326
        return this.propertiesHelper.getProperty(name);
327
    }
328

    
329
    @Override
330
    public void setProperty(String string, Object o) {
331
        this.propertiesHelper.setProperty(name, o);
332
    }
333

    
334
    @Override
335
    public Map<String, Object> getProperties() {
336
        return this.propertiesHelper.getProperties();
337
    }
338

    
339
    public SpatialIndex getSpatialIndex() {
340
        if( this.spatialIndex == null ) {
341
            this.spatialIndex = new MutableObject<>();
342
            FeatureStore theStore = this.getStore();
343
            FeatureStoreProviderFactory storeFactory = (FeatureStoreProviderFactory) theStore.getProviderFactory();
344
            if( storeFactory.useLocalIndexesCanImprovePerformance()==FeatureStoreProviderFactory.YES ) {
345
                try {
346
                    GeometryManager geomManager = GeometryLocator.getGeometryManager();
347
                    final SpatialIndex geomIndex = geomManager.createSpatialIndex(
348
                            GeometryManager.SPATIALINDEX_DEFAULT_QUADTREE,
349
                            null
350
                    );
351
                    final SpatialIndex dataIndex = theStore.wrapSpatialIndex(geomIndex);
352
                    try {
353
                        store.accept(new Visitor() {
354
                            @Override
355
                            public void visit(Object o) throws VisitCanceledException, BaseException {
356
                                Feature f = (Feature) o;
357
                                Geometry geom = f.getDefaultGeometry();
358
                                if (geom != null) {
359
                                    dataIndex.insert(geom, f);
360
                                }
361
                            }
362
                        });
363
                    } catch (VisitCanceledException ex) {
364
                    }
365
                    this.spatialIndex.setValue(dataIndex);
366
                } catch (Exception ex) {
367
                    LOGGER.warn("Can't create spatial index", ex);
368
                }
369
            }
370
        }
371
        return this.spatialIndex.getValue();
372
    }
373

    
374
    public Iterable<FeatureReference> query(Geometry geom) {
375
        SpatialIndex index = this.getSpatialIndex();
376
        if( index == null ) {
377
            return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
378
        }
379
        final Iterator it = index.query(geom);
380
        if( it == null ) {
381
            return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR;
382
        }
383
        return new Iterable<FeatureReference>() {
384
            @Override
385
            public Iterator<FeatureReference> iterator() {
386
                return it;
387
            }
388
        };
389
    }
390

    
391
    @Override
392
    public Feature findFirst(Expression filter) {
393
        try {
394
            return this.getStore().findFirst(filter);
395
        } catch (Exception ex) {
396
            return null;
397
        }
398
    }
399

    
400
}