Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / layers / vectorial / impl / DefaultGraphicLayer.java @ 45006

History | View | Annotate | Download (14.8 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.layers.vectorial.impl;
24

    
25
import java.util.Iterator;
26

    
27
import org.cresques.cts.ICoordTrans;
28
import org.cresques.cts.IProjection;
29
import org.gvsig.fmap.dal.DALLocator;
30
import org.gvsig.fmap.dal.DataManager;
31
import org.gvsig.fmap.dal.DataTypes;
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.exception.ReadException;
34
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
37
import org.gvsig.fmap.dal.feature.EditableFeatureType;
38
import org.gvsig.fmap.dal.feature.Feature;
39
import org.gvsig.fmap.dal.feature.FeatureSet;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.geom.Geometry;
43
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
44
import org.gvsig.fmap.geom.Geometry.TYPES;
45
import org.gvsig.fmap.geom.GeometryLocator;
46
import org.gvsig.fmap.geom.GeometryManager;
47
import org.gvsig.fmap.geom.primitive.Envelope;
48
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
49
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
50
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
51
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
52
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
53
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
55
import org.gvsig.tools.dispose.DisposableIterator;
56
import org.gvsig.tools.exception.BaseException;
57
import org.slf4j.Logger;
58
import org.slf4j.LoggerFactory;
59

    
60
/**
61
 * Default {@link GraphicLayer} implementation.
62
 *
63
 * @author gvSIG Team
64
 */
65
@SuppressWarnings("UseSpecificCatch")
66
public class DefaultGraphicLayer extends FLyrVect implements GraphicLayer {
67

    
68
    private static final String DEFAULT = "default";
69
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultGraphicLayer.class);
70
    
71
    private IVectorialUniqueValueLegend legend = null;
72

    
73
    private FeatureStore store = null;
74
    private long ids = 0;
75

    
76
    private int symbolId = -1;
77

    
78
    private int featureIdIndex;
79
    private int groupIdIndex;
80
    private int geomIndex;
81
    private int idsymIndex;
82
    private int labelIndex;
83
    private int tagIndex;
84
    private int priorityIndex;
85

    
86
    public void initialize(IProjection projection) throws ValidateDataParametersException, DataException, LoadLayerException {
87
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
88
        DataManager dataManager = DALLocator.getDataManager();
89
        
90
        store = dataManager.createMemoryStore(FEATURE_ATTR_PRIORITY);
91
        store.edit();
92

    
93
        EditableFeatureType editableFeatureType = store.getDefaultFeatureType().getEditable();
94

    
95
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_GROUPID, DataTypes.STRING);
96

    
97
        EditableFeatureAttributeDescriptor geometryDescriptor = editableFeatureType.add(GraphicLayer.FEATURE_ATTR_GEOMETRY, DataTypes.GEOMETRY);
98
        try {
99
            geometryDescriptor.setGeometryType(geomManager.getGeometryType(TYPES.GEOMETRY, SUBTYPES.GEOM2D));
100
        } catch (Exception e) {
101
            LOGGER.info("Can't create/assign geomery type to feature type of GraphicLayer.", e);
102
        }
103
        geometryDescriptor.setSRS(projection);
104
        editableFeatureType.setDefaultGeometryAttributeName(GraphicLayer.FEATURE_ATTR_GEOMETRY);
105

    
106
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_IDSYMBOL, DataTypes.INT);
107

    
108
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_LABEL, DataTypes.STRING);
109

    
110
        EditableFeatureAttributeDescriptor featureIdDescriptor
111
                = editableFeatureType.add(GraphicLayer.FEATURE_ATTR_FEATUREID, DataTypes.LONG);
112

    
113
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_TAG, DataTypes.OBJECT);
114
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_PRIORITY, DataTypes.INT);
115

    
116
        featureIdDescriptor.setIsPrimaryKey(true);
117
        editableFeatureType.setHasOID(true);
118

    
119
        store.update(editableFeatureType);
120

    
121
        store.finishEditing();
122

    
123
        FeatureType ftype = store.getDefaultFeatureType();
124
        featureIdIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_FEATUREID);
125
        groupIdIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_GROUPID);
126
        geomIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_GEOMETRY);
127
        idsymIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_IDSYMBOL);
128
        labelIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_LABEL);
129
        tagIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_TAG);
130
        priorityIndex = ftype.getIndex(GraphicLayer.FEATURE_ATTR_PRIORITY);
131

    
132
        this.bindToDataStore(store);
133

    
134
        setName("Graphic Layer");
135
    }
136

    
137
    @Override
138
    public void addGraphic(String groupId, Geometry geom, int idsym) {
139
        addGraphic(groupId, geom, idsym, null, null, DEFAULT_PRIORITY);
140
    }
141

    
142
    @Override
143
    public void addGraphic(Geometry geom, int idsym) {
144
        addGraphic(DEFAULT, geom, idsym, null, null, DEFAULT_PRIORITY);
145
    }
146

    
147
    @Override
148
    public void addGraphic(Geometry geom, int idsym, String label) {
149
        addGraphic(DEFAULT, geom, idsym, label, null, DEFAULT_PRIORITY);
150
    }
151

    
152
    @Override
153
    public void addGraphic(String groupId, Geometry geom, int idsym, String label) {
154
        addGraphic(groupId, geom, idsym, label, null, DEFAULT_PRIORITY);
155
    }
156

    
157
    @Override
158
    @SuppressWarnings("SynchronizeOnNonFinalField")
159
    public void addGraphic(String groupId, Geometry geom, int idsym, String label,
160
            Object tag, int priority) {
161

    
162
        try {
163
            store.beginComplexNotification();
164
            // Just in case another thread is going to read from the store
165
            synchronized (store) {
166
                if (store.isEditing() || store.isAppending() ) {
167
                    insertGeometry(groupId, geom, idsym, label, tag, priority);
168
                } else {
169
                    store.edit(FeatureStore.MODE_APPEND);
170
                    try {
171
                        insertGeometry(groupId, geom, idsym, label, tag, priority);
172
                        store.finishEditing();
173
                    } catch(Throwable th) {
174
                        try {
175
                            store.cancelEditing();
176
                        } catch(Throwable th2) {
177
                            // Do nothing
178
                        }
179
                        throw th;
180
                    }
181
                }
182
            }
183
        } catch (Throwable th) {
184
            LOGGER.warn("Error adding a geometry to the graphic layer", th);
185
        } finally {
186
            try {
187
                store.endComplexNotification();
188
            } catch(Exception ex) {
189
                // Do nothing
190
            }
191
        }
192
    }
193

    
194
    private void insertGeometry(String groupId, Geometry geom, int idsym,
195
            String label, Object tag, int priority) throws DataException {
196
        EditableFeature feature = store.createNewFeature().getEditable();
197
        feature.setString(groupIdIndex, groupId);
198
        feature.setGeometry(geomIndex, geom);
199
        feature.setInt(idsymIndex, idsym);
200
        feature.setString(labelIndex, label);
201
        feature.setLong(featureIdIndex, ids);
202
        feature.set(tagIndex, tag);
203
        feature.setInt(priorityIndex, priority);
204

    
205
        ids++;
206

    
207
        store.insert(feature);
208
    }
209

    
210
    @Override
211
    public void addGraphics(String groupId, Iterator geoms, int idsym) {
212
        addGraphics(groupId, geoms, idsym, null, null, DEFAULT_PRIORITY);
213
    }
214

    
215
    @Override
216
    public void addGraphics(String groupId, Iterator geoms, int idsym,
217
            String label) {
218
        addGraphics(groupId, geoms, idsym, label, null, DEFAULT_PRIORITY);
219
    }
220

    
221
    @Override
222
    @SuppressWarnings("SynchronizeOnNonFinalField")
223
    public void addGraphics(String groupId, Iterator geoms, int idsym,
224
            String label, Object tag, int priority) {
225
        try {
226
            // Just in case another thread is going to read from the store
227
            synchronized (store) {
228
                if (store.isEditing() || store.isAppending() ) {
229
                    store.disableNotifications();
230
                    for (; geoms.hasNext();) {
231
                        Geometry geom = (Geometry) geoms.next();
232
                        insertGeometry(groupId, geom, idsym, label, tag, priority);
233
                    }
234
                    store.enableNotifications();
235
                } else {
236
                    store.edit(FeatureStore.MODE_APPEND);
237
                    try {
238
                        store.disableNotifications();
239
                        for (; geoms.hasNext();) {
240
                            Geometry geom = (Geometry) geoms.next();
241
                            insertGeometry(groupId, geom, idsym, label, tag, priority);
242
                        }
243
                        store.enableNotifications();
244
                        store.finishEditing();
245
                    } catch(Throwable th) {
246
                        try {
247
                            store.cancelEditing();
248
                        } catch(Throwable th2) {
249
                            // Do nothing
250
                        }
251
                        throw th;
252
                        
253
                    }
254
                }
255
            }
256
        } catch (Throwable th) {
257
            LOGGER.warn("Error adding a geometry to the graphic layer", th);
258
        }
259
    }
260

    
261
    @Override
262
    public int addSymbol(ISymbol newSymbol) {
263
        symbolId++;
264
        legend.addSymbol(symbolId, newSymbol);
265
        return symbolId;
266
    }
267

    
268
    @Override
269
    public ISymbol getSymbol(int symbolPos) {
270
        return legend.getSymbolByValue(symbolPos);
271
    }
272

    
273
    @Override
274
    public int getSymbolId(ISymbol symbol) {
275
        Object key = legend.getSymbolKey(symbol);
276
        return key == null ? -1 : ((Number) key).intValue();
277
    }
278

    
279
    @Override
280
    public void clearAllGraphics() {
281
        DisposableIterator iterator = null;
282
        FeatureSet featureSet = null;
283
        try {
284
            if (!store.isEditing()) {
285
                store.edit();
286
                featureSet = store.getFeatureSet();
287
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
288
                    Feature feature = (Feature) iterator.next();
289
                    featureSet.delete(feature);
290
                }
291
                store.finishEditing();
292
            } else {
293
                featureSet = store.getFeatureSet();
294
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
295
                    Feature feature = (Feature) iterator.next();
296
                    featureSet.delete(feature);
297
                }
298
            }
299
        } catch (DataException e) {
300
            LOGGER.warn("Error clearing all the geometry of the graphic layer", e);
301
        } finally {
302
            if (featureSet != null) {
303
                featureSet.dispose();
304
            }
305
            if (iterator != null) {
306
                iterator.dispose();
307
            }
308
        }
309
    }
310

    
311
    @Override
312
    public int clearAllSymbols() {
313
        legend.clear();
314
        symbolId = -1;
315
        return symbolId;
316
    }
317

    
318
    @Override
319
    public void removeGraphics(String groupId) {
320
        DisposableIterator iterator = null;
321
        FeatureSet featureSet = null;
322
        try {
323
            store.beginComplexNotification();
324
            if (!store.isEditing()) {
325
                store.edit();
326
                featureSet = store.getFeatureSet();
327
                store.beginEditingGroup(groupId);
328
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
329
                    Feature feature = (Feature) iterator.next();
330
                    if (feature.get(FEATURE_ATTR_GROUPID).equals(groupId)) {
331
                        featureSet.delete(feature);
332
                    }
333
                }
334
                store.endEditingGroup();
335
                store.finishEditing();
336
            } else {
337
                featureSet = store.getFeatureSet();
338
                store.beginEditingGroup(groupId);
339
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
340
                    Feature feature = (Feature) iterator.next();
341
                    if (feature.get(FEATURE_ATTR_GROUPID).equals(groupId)) {
342
                        featureSet.delete(feature);
343
                    }
344
                }
345
                store.endEditingGroup();
346
            }
347
            store.endComplexNotification();
348
        } catch (DataException e) {
349
            LOGGER.warn("Error clearing all the geometry of the graphic layer", e);
350
        } finally {
351
            if (featureSet != null) {
352
                featureSet.dispose();
353
            }
354
            if (iterator != null) {
355
                iterator.dispose();
356
            }
357
        }
358
    }
359

    
360
    @Override
361
    protected void doDispose() throws BaseException {
362
        super.doDispose();
363
        if (store != null) {
364
            store.dispose();
365
            store = null;
366
        }
367
    }
368

    
369
    @Override
370
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
371
        if (legend instanceof IVectorialUniqueValueLegend) {
372
            super.setLegend(legend);
373
            this.legend = (IVectorialUniqueValueLegend) legend;
374
            this.legend.setClassifyingFieldNames(new String[]{FEATURE_ATTR_IDSYMBOL});
375
            this.legend.setClassifyingFieldTypes(new int[]{DataTypes.INT});
376
        } else {
377
            if (this.legend != null) { // Skip the first assignment, is always bad.
378
                LOGGER.warn("The allocation of legend type '" + (legend==null? "null":legend.getClass().getName()) + "' is ignored. Required a legend of type IVectorialUniqueValueLegend.");
379
            }
380
        }
381
    }
382

    
383
    @Override
384
    public Envelope getFullEnvelope() throws ReadException {
385
        Envelope rAux;
386
        try {
387
            rAux = getFeatureStore().getEnvelope();
388
        } catch (BaseException e) {
389
            throw new ReadException(getName(), e);
390
        }
391

    
392
        if (rAux == null) {
393
            return null;
394
        }
395

    
396
        ICoordTrans ct = getCoordTrans();
397
        if (ct != null) {
398
            rAux = rAux.convert(ct);
399
        }
400
        return rAux;
401
    }
402
}