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

History | View | Annotate | Download (15.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 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
import org.apache.commons.lang3.StringUtils;
27

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

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

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

    
75
    private FeatureStore store = null;
76
    private long ids = 0;
77

    
78
    private int symbolId = -1;
79

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

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

    
95
        EditableFeatureType editableFeatureType = store.getDefaultFeatureType().getEditable();
96

    
97
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_GROUPID, DataTypes.STRING);
98

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

    
108
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_IDSYMBOL, DataTypes.INT);
109

    
110
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_LABEL, DataTypes.STRING);
111

    
112
        EditableFeatureAttributeDescriptor featureIdDescriptor
113
                = editableFeatureType.add(GraphicLayer.FEATURE_ATTR_FEATUREID, DataTypes.LONG);
114

    
115
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_TAG, DataTypes.OBJECT);
116
        editableFeatureType.add(GraphicLayer.FEATURE_ATTR_PRIORITY, DataTypes.INT);
117

    
118
        featureIdDescriptor.setIsPrimaryKey(true);
119
        editableFeatureType.setHasOID(true);
120

    
121
        store.update(editableFeatureType);
122

    
123
        store.finishEditing();
124

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

    
134
        this.bindToDataStore(store);
135

    
136
        setName("Graphic Layer");
137
    }
138

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

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

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

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

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

    
164
        try {
165
            store.beginComplexNotification();
166
            // Just in case another thread is going to read from the store
167
            synchronized (store) {
168
                if(StringUtils.isNotBlank(label)){
169
                    ISymbol symbol = this.getSymbol(idsym);
170
                    if(symbol instanceof ITextSymbol){
171
                        ITextSymbol textSymbol = (ITextSymbol)(symbol.clone());
172
                        textSymbol.setText(label);
173
                        idsym = this.addSymbol(textSymbol);
174
                    }
175
                }
176
                if (store.isEditing() || store.isAppending() ) {
177
                    insertGeometry(groupId, geom, idsym, label, tag, priority);
178
                } else {
179
                    store.edit(FeatureStore.MODE_APPEND);
180
                    try {
181
                        insertGeometry(groupId, geom, idsym, label, tag, priority);
182
                        store.finishEditing();
183
                    } catch(Throwable th) {
184
                        try {
185
                            store.cancelEditing();
186
                        } catch(Throwable th2) {
187
                            // Do nothing
188
                        }
189
                        throw th;
190
                    }
191
                }
192
            }
193
        } catch (Throwable th) {
194
            LOGGER.warn("Error adding a geometry to the graphic layer", th);
195
        } finally {
196
            try {
197
                store.endComplexNotification();
198
            } catch(Exception ex) {
199
                // Do nothing
200
            }
201
        }
202
    }
203

    
204
    private void insertGeometry(String groupId, Geometry geom, int idsym,
205
            String label, Object tag, int priority) throws DataException {
206
        EditableFeature feature = store.createNewFeature().getEditable();
207
        feature.setString(groupIdIndex, groupId);
208
        feature.setGeometry(geomIndex, geom);
209
        feature.setInt(idsymIndex, idsym);
210
        feature.setString(labelIndex, label);
211
        feature.setLong(featureIdIndex, ids);
212
        feature.set(tagIndex, tag);
213
        feature.setInt(priorityIndex, priority);
214

    
215
        ids++;
216

    
217
        store.insert(feature);
218
    }
219

    
220
    @Override
221
    public void addGraphics(String groupId, Iterator geoms, int idsym) {
222
        addGraphics(groupId, geoms, idsym, null, null, DEFAULT_PRIORITY);
223
    }
224

    
225
    @Override
226
    public void addGraphics(String groupId, Iterator geoms, int idsym,
227
            String label) {
228
        addGraphics(groupId, geoms, idsym, label, null, DEFAULT_PRIORITY);
229
    }
230

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

    
271
    @Override
272
    public int addSymbol(ISymbol newSymbol) {
273
        symbolId++;
274
        legend.addSymbol(symbolId, newSymbol);
275
        return symbolId;
276
    }
277

    
278
    @Override
279
    public ISymbol getSymbol(int symbolPos) {
280
        return legend.getSymbolByValue(symbolPos);
281
    }
282

    
283
    @Override
284
    public int getSymbolId(ISymbol symbol) {
285
        Object key = legend.getSymbolKey(symbol);
286
        return key == null ? -1 : ((Number) key).intValue();
287
    }
288

    
289
    @Override
290
    public void clearAllGraphics() {
291
        DisposableIterator iterator = null;
292
        FeatureSet featureSet = null;
293
        try {
294
            if (!store.isEditing()) {
295
                store.edit();
296
                featureSet = store.getFeatureSet();
297
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
298
                    Feature feature = (Feature) iterator.next();
299
                    featureSet.delete(feature);
300
                }
301
                store.finishEditing();
302
            } else {
303
                featureSet = store.getFeatureSet();
304
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
305
                    Feature feature = (Feature) iterator.next();
306
                    featureSet.delete(feature);
307
                }
308
            }
309
        } catch (DataException e) {
310
            LOGGER.warn("Error clearing all the geometry of the graphic layer", e);
311
        } finally {
312
            if (featureSet != null) {
313
                featureSet.dispose();
314
            }
315
            if (iterator != null) {
316
                iterator.dispose();
317
            }
318
        }
319
    }
320

    
321
    @Override
322
    public int clearAllSymbols() {
323
        legend.clear();
324
        symbolId = -1;
325
        return symbolId;
326
    }
327

    
328
    @Override
329
    public boolean removeGraphics(String groupId) {
330
        boolean res = false;
331
        DisposableIterator iterator = null;
332
        FeatureSet featureSet = null;
333
        try {
334
            store.beginComplexNotification();
335
            if (!store.isEditing()) {
336
                store.edit();
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
                        res = true;
344
                    }
345
                }
346
                store.endEditingGroup();
347
                store.finishEditing();
348
            } else {
349
                featureSet = store.getFeatureSet();
350
                store.beginEditingGroup(groupId);
351
                for (iterator = featureSet.fastIterator(); iterator.hasNext();) {
352
                    Feature feature = (Feature) iterator.next();
353
                    if (feature.get(FEATURE_ATTR_GROUPID).equals(groupId)) {
354
                        featureSet.delete(feature);
355
                        res = true;
356
                    }
357
                }
358
                store.endEditingGroup();
359
            }
360
            store.endComplexNotification();
361
        } catch (DataException e) {
362
            LOGGER.warn("Error clearing all the geometry of the graphic layer", e);
363
        } finally {
364
            if (featureSet != null) {
365
                featureSet.dispose();
366
            }
367
            if (iterator != null) {
368
                iterator.dispose();
369
            }
370
        }
371
        return res;
372
    }
373

    
374
    @Override
375
    protected void doDispose() throws BaseException {
376
        super.doDispose();
377
        if (store != null) {
378
            store.dispose();
379
            store = null;
380
        }
381
    }
382

    
383
    @Override
384
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
385
        if (legend instanceof IVectorialUniqueValueLegend) {
386
            super.setLegend(legend);
387
            this.legend = (IVectorialUniqueValueLegend) legend;
388
            this.legend.setClassifyingFieldNames(new String[]{FEATURE_ATTR_IDSYMBOL});
389
            this.legend.setClassifyingFieldTypes(new int[]{DataTypes.INT});
390
        } else {
391
            if (this.legend != null) { // Skip the first assignment, is always bad.
392
                LOGGER.warn("The allocation of legend type '" + (legend==null? "null":legend.getClass().getName()) + "' is ignored. Required a legend of type IVectorialUniqueValueLegend.");
393
            }
394
        }
395
    }
396

    
397
    @Override
398
    public Envelope getFullEnvelope() throws ReadException {
399
        Envelope rAux;
400
        try {
401
            rAux = getFeatureStore().getEnvelope();
402
        } catch (BaseException e) {
403
            throw new ReadException(getName(), e);
404
        }
405

    
406
        if (rAux == null) {
407
            return null;
408
        }
409

    
410
        ICoordTrans ct = getCoordTrans();
411
        if (ct != null) {
412
            rAux = rAux.convert(ct);
413
        }
414
        return rAux;
415
    }
416
}