Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2020 / extensions / org.gvsig.symbology / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / legend / impl / VectorialUniqueValueLegend.java @ 33972

History | View | Annotate | Download (13.4 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22
package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
23

    
24
import java.awt.Color;
25
import java.util.ArrayList;
26
import java.util.Comparator;
27
import java.util.Iterator;
28
import java.util.List;
29
import java.util.Map;
30
import java.util.Map.Entry;
31
import java.util.TreeMap;
32

    
33
import org.gvsig.fmap.dal.feature.Feature;
34
import org.gvsig.fmap.mapcontext.MapContextException;
35
import org.gvsig.fmap.mapcontext.MapContextLocator;
36
import org.gvsig.fmap.mapcontext.MapContextManager;
37
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialUniqueValueLegend;
38
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
39
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
40
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
41
import org.gvsig.tools.ToolsLocator;
42
import org.gvsig.tools.dynobject.DynStruct;
43
import org.gvsig.tools.persistence.PersistenceManager;
44
import org.gvsig.tools.persistence.PersistentState;
45
import org.gvsig.tools.persistence.exception.PersistenceException;
46
import org.gvsig.tools.util.Callable;
47
import org.slf4j.Logger;
48
import org.slf4j.LoggerFactory;
49

    
50
/**
51
 * Vectorial legend for unique values
52
 * 
53
 * @author Vicente Caballero Navarro
54
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
55
 */
56
public class VectorialUniqueValueLegend extends AbstractClassifiedVectorLegend implements IVectorialUniqueValueLegend {
57
        final static private Logger LOG = LoggerFactory.getLogger(VectorialUniqueValueLegend.class);
58

    
59
        public static final String VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME =
60
                        "VectorialUniqueValueLegend";
61

    
62
        private static final String FIELD_KEYS = "keys";
63
        private static final String FIELD_NULL_VALUE_SYMBOL = "nullValueSymbol";
64
        private static final String FIELD_SELECTED_COLORS = "selectedColors";
65
        private static final String FIELD_SYMBOLS = "symbols";
66
        private static final String FIELD_USE_DEFAULT_SYMBOL = "useDefaultSymbol";
67

    
68
        private Map<Object, ISymbol> symbols = createSymbolMap();
69

    
70
        private List<Object> keys = new ArrayList<Object>();
71

    
72
    private ISymbol defaultSymbol;
73
    private int shapeType;
74
    private boolean useDefaultSymbol = false;
75
    private Color[] selectedColors=null;
76
    
77
    private ISymbol nullValueSymbol = null;
78
    
79
    public VectorialUniqueValueLegend() {
80
                super();
81
        }
82

    
83
    /**
84
     * Constructor method
85
     *
86
     * @param shapeType Type of the shape.
87
     */
88
    public VectorialUniqueValueLegend(int shapeType) {
89
                super();
90
            setShapeType(shapeType);
91
    }
92

    
93
     public void setShapeType(int shapeType) {
94
            if (this.shapeType != shapeType) {
95
                    ISymbol old = defaultSymbol;
96
                        defaultSymbol = getSymbolManager().createSymbol(shapeType);
97
                    fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
98
                    this.shapeType = shapeType;
99
            }
100
    }
101

    
102
    public void setValueSymbolByID(int id, ISymbol symbol) {
103
        ISymbol old = (ISymbol)symbols.put(keys.get(id), symbol);
104
        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(old, symbol));
105
    }
106

    
107
    public Object[] getValues() {
108
        return symbols.keySet().toArray(new Object[0]);
109
    }
110

    
111
    public void addSymbol(Object key, ISymbol symbol) {
112
            ISymbol resul;
113
            if (key == null) {
114
                    resul = nullValueSymbol;
115
                    nullValueSymbol = symbol;
116
            }
117
            else {
118
                        resul = (ISymbol) symbols.put(key, symbol);
119

    
120
                        if (resul != null) {
121
                                LOG.error("Error: la clave " + key + " ya exist?a. Resul = "
122
                                                + resul);
123
                                LOG.warn("symbol nuevo:" + symbol.getDescription()
124
                                                + " Sviejo= " + resul.getDescription());
125
                        } else {
126
                                keys.add(key);
127
                        }
128
            }
129
            
130
        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(resul, symbol));
131
    }
132

    
133
    public void clear() {
134
        keys.clear();
135
        ISymbol[] olds = (ISymbol[])symbols.values().toArray(new ISymbol[0]);
136
        symbols.clear();
137
        removeLegendListener(getZSort());
138
        setZSort(null);
139

    
140
        fireLegendClearEvent(new LegendClearEvent(olds));
141
    }
142

    
143
    public String[] getDescriptions() {
144
        String[] descriptions = new String[symbols.size()];
145
        ISymbol[] auxSym = getSymbols();
146

    
147
        for (int i = 0; i < descriptions.length; i++) {
148
                        descriptions[i] = auxSym[i].getDescription();
149
                }
150

    
151
        return descriptions;
152
    }
153

    
154
     public ISymbol[] getSymbols() {
155
                 ISymbol[] symbolList;
156
                if (nullValueSymbol == null) {
157
                        symbolList = new ISymbol[symbols.size()];
158
                        return (ISymbol[]) symbols.values().toArray(symbolList);
159
                }
160
                else {
161
                        symbolList = new ISymbol[symbols.size() + 1];
162
                        symbolList[0] = nullValueSymbol;
163
                        int i = 1;
164
                        for (Iterator<ISymbol> iterator = symbols.values().iterator(); iterator
165
                                        .hasNext();) {
166
                                symbolList[i] = iterator.next();
167
                                i++;
168
                        }
169
                        return symbolList;
170
                }
171
    }
172

    
173
    public void setClassifyingFieldNames(String[] fNames) {
174
             super.setClassifyingFieldNames(fNames);
175
             LOG.warn("TODO: Check if need more process in VectorialUniqueValueLegend.setClassifyingFieldNames");
176
     }
177

    
178
    /**
179
         * Devuelve un s?mbolo a partir de una IFeature. OJO!! Cuando usamos un
180
         * feature iterator de base de datos el ?nico campo que vendr? rellenado es
181
         * el de fieldID. Los dem?s vendr?n a nulos para ahorra tiempo de creaci?n.
182
         *
183
         * @param feat
184
         *            IFeature
185
         *
186
         * @return S?mbolo.
187
     * @throws MapContextException 
188
         */
189
    public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
190

    
191
            Object val = feat.get(getClassifyingFieldNames()[0]);
192
//        Object val = feat.get(fieldId);
193
        ISymbol theSymbol = getSymbolByValue(val);
194

    
195
        if (theSymbol != null) {
196
                return theSymbol;
197

    
198
        }
199

    
200
        if (isUseDefaultSymbol()) {
201
                        return defaultSymbol;
202
                }
203

    
204
        return null;
205
    }
206

    
207

    
208
    public ISymbol getDefaultSymbol() {
209

    
210
            if(defaultSymbol==null) {
211
                        defaultSymbol = getSymbolManager().createSymbol(shapeType);
212
                    fireDefaultSymbolChangedEvent(new SymbolLegendEvent(null, defaultSymbol));
213
            }
214
            return defaultSymbol;
215
    }
216

    
217
        public void setDefaultSymbol(ISymbol s) {
218
            ISymbol mySymbol = defaultSymbol;
219

    
220
            if (s == null) {
221
                        throw new NullPointerException("Default symbol cannot be null");
222
                }
223

    
224
            ISymbol old = mySymbol;
225
            defaultSymbol = s;
226
            fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, s));
227
    }
228

    
229

    
230
    /*
231
     * (non-Javadoc)
232
     *
233
     * @see com.iver.cit.gvsig.fmap.rendering.UniqueValueLegend#getSymbolByValue(com.hardcode.gdbms.engine.values.Value)
234
     */
235
    public ISymbol getSymbolByValue(Object key) {
236
            ISymbol symbol = null; 
237
            if (key == null) {
238
                    symbol = nullValueSymbol;
239
            }
240
            else {
241
                    symbol = (ISymbol)symbols.get(key);
242
            }
243
            if (symbol == null && useDefaultSymbol) {
244
                    symbol = getDefaultSymbol();
245
            }
246
            return symbol;
247

    
248
    }
249

    
250
        public Object getSymbolKey(ISymbol symbol) {
251
                if (symbol != null) {
252
                        for (Iterator<Entry<Object, ISymbol>> iterator = symbols.entrySet()
253
                                        .iterator(); iterator.hasNext();) {
254
                                Entry<Object, ISymbol> entry = iterator.next();
255
                                if (symbol.equals(entry.getValue())) {
256
                                        return entry.getKey();
257
                                }
258
                        }
259
                }
260
                return null;
261
        }
262

    
263
    public int getShapeType() {
264
        return shapeType;
265
    }
266

    
267
    public void useDefaultSymbol(boolean b) {
268
        useDefaultSymbol = b;
269
    }
270

    
271
    /**
272
         * Devuelve si se utiliza o no el resto de valores para representarse.
273
         * @return  True si se utiliza el resto de valores.
274
         */
275
    public boolean isUseDefaultSymbol() {
276
        return useDefaultSymbol;
277
    }
278

    
279
    public void delSymbol(Object key) {
280
        keys.remove(key);
281

    
282
                ISymbol removedSymbol = (ISymbol) symbols.remove(key);
283
                if (removedSymbol != null){
284
                        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(removedSymbol, null));
285
                }
286
    }
287

    
288
        public String getClassName() {
289
                return getClass().getName();
290
        }
291

    
292
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
293
                if (symbols.containsValue(oldSymbol)) {
294
                        Iterator<Object> it = symbols.keySet().iterator();
295
                        while (it.hasNext()) {
296
                                Object key = it.next();
297
                                if (symbols.get(key).equals(oldSymbol)) {
298
                                        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(
299
                                                        (ISymbol)symbols.put(key, newSymbol), newSymbol));
300
                                }
301

    
302
                        }
303
                }
304
        }
305
        public Color[] getColorScheme() {
306
                return selectedColors;
307
        }
308

    
309
        public void setColorScheme(Color[] cc) {
310
                 this.selectedColors = cc;
311
        }
312

    
313
        public Object clone() throws CloneNotSupportedException {
314
                VectorialUniqueValueLegend clone =
315
                                (VectorialUniqueValueLegend) super.clone();
316

    
317
                // Clone default symbol
318
                if (defaultSymbol != null) {
319
                        clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
320
                }
321
                // Clone keys
322
                clone.keys = new ArrayList<Object>();
323

    
324
                // Clone symbols
325
                if (symbols != null) {
326
                        clone.symbols = createSymbolMap();
327
                        for (Iterator<Entry<Object, ISymbol>> iterator =
328
                                        symbols.entrySet().iterator(); iterator.hasNext();) {
329
                                Entry<Object, ISymbol> entry = iterator.next();
330
                                ISymbol symbolClone =
331
                                                (ISymbol) ((ISymbol) entry.getValue()).clone();
332
                                // Map keys are of type Number or String, so being
333
                                // immutable objects, don't clone them
334
                                clone.addSymbol(entry.getKey(), symbolClone);
335
                        }
336
                }
337

    
338
                return clone;
339
        }
340

    
341

    
342
        private Map<Object, ISymbol> createSymbolMap() {
343
                return new TreeMap<Object, ISymbol>(
344
                                new Comparator<Object>() { 
345
                                        public int compare(Object o1, Object o2) {
346
                                                if ((o1 != null) && (o2 != null)) {
347
                                                        Object v2 = o2;
348
                                                        Object v1 = o1;
349
                                                        if (v1 instanceof Number && v2 instanceof Number) {
350
                                                                return ((Number) v1).intValue()
351
                                                                                - ((Number) v2).intValue();
352
                                                        }
353
                                                        if (v1 instanceof String && v2 instanceof String) {
354
                                                                return ((String) v1).compareTo(((String) v2));
355
                                                        }
356
                                                }
357

    
358
                                                return 0;
359
                                        }
360
                                });
361

    
362
        }
363

    
364
        @SuppressWarnings({ "unchecked", "rawtypes" })
365
        public void loadFromState(PersistentState state)
366
                        throws PersistenceException {
367
                // Set parent properties
368
                super.loadFromState(state);
369
                // Set own properties
370
                keys = new ArrayList<Object>((List) state.get(FIELD_KEYS));
371
                nullValueSymbol = (ISymbol) state.get(FIELD_NULL_VALUE_SYMBOL);
372
                selectedColors =
373
                                (Color[]) state.getArray(FIELD_SELECTED_COLORS, Color.class);
374
                Map persistedSymbolMap = (Map) state.get(FIELD_SYMBOLS);
375
                if (persistedSymbolMap != null) {
376
                        symbols.putAll(persistedSymbolMap);
377
                }
378
                useDefaultSymbol(state.getBoolean(FIELD_USE_DEFAULT_SYMBOL));
379
        }
380

    
381
        public void saveToState(PersistentState state) throws PersistenceException {
382
                // Save parent properties
383
                super.saveToState(state);
384
                // Save own properties
385
                state.set(FIELD_KEYS, keys);
386
                state.set(FIELD_NULL_VALUE_SYMBOL, nullValueSymbol);
387
                state.set(FIELD_SELECTED_COLORS, selectedColors);
388
                state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
389
                state.set(FIELD_SYMBOLS, symbols);
390
        }
391

    
392
        public static class RegisterPersistence implements Callable {
393

    
394
                public Object call() throws Exception {
395
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
396
                        if( manager.getDefinition(VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME)==null ) {
397
                                DynStruct definition = manager.addDefinition(
398
                                                VectorialUniqueValueLegend.class,
399
                                                VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME,
400
                                                VECTORIAL_UNIQUE_VALUE_LEGEND_PERSISTENCE_DEFINITION_NAME+" Persistence definition",
401
                                                null, 
402
                                                null
403
                                );
404
                                // Extend the Classified Vector Legend base definition
405
                                definition.extend(manager.getDefinition(CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME));
406

    
407
                                // Keys
408
                                definition.addDynFieldList(FIELD_KEYS).setClassOfItems(Object.class);
409
                                // Null interval symbol
410
                                definition.addDynFieldObject(FIELD_NULL_VALUE_SYMBOL).setClassOfValue(ISymbol.class);
411
                                // Selected colors
412
                                definition.addDynFieldList(FIELD_SELECTED_COLORS).setClassOfItems(Color.class);
413
                                // Symbols
414
                                definition.addDynFieldMap(FIELD_SYMBOLS).setClassOfItems(ISymbol.class);
415
                                // Use default symbol?
416
                                definition.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
417
                        }
418
                        return Boolean.TRUE;
419
                }
420
                
421
        }
422

    
423
        public static class RegisterLegend implements Callable {
424

    
425
                public Object call() throws Exception {
426
                MapContextManager manager = MapContextLocator.getMapContextManager();
427
                
428
            manager.registerLegend(IVectorialUniqueValueLegend.LEGEND_NAME,
429
                    VectorialUniqueValueLegend.class);
430

    
431
                        return Boolean.TRUE;
432
                }
433
                
434
        }
435
}