Statistics
| Revision:

gvsig-sldtools / org.gvsig.sld / org.gvsig.sldconverter / org.gvsig.sldconverter.lib / org.gvsig.sldconverter.lib.impl / src / main / java / org / gvsig / sldconverter / impl / legend / IntervalsLegendUtils.java @ 46

History | View | Annotate | Download (14.8 KB)

1
/*******************************************************************************
2
 *
3
 *   gvSIG. Desktop Geographic Information System.
4
 *  
5
 *   Copyright (C) 2007-2013 gvSIG Association.
6
 *  
7
 *   This program is free software; you can redistribute it and/or
8
 *   modify it under the terms of the GNU General Public License
9
 *   as published by the Free Software Foundation; either version 3
10
 *   of the License, or (at your option) any later version.
11
 *  
12
 *   This program is distributed in the hope that it will be useful,
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *   GNU General Public License for more details.
16
 *  
17
 *   You should have received a copy of the GNU General Public License
18
 *   along with this program; if not, write to the Free Software
19
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
 *   MA  02110-1301, USA.
21
 *  
22
 *   For any additional information, do not hesitate to contact us
23
 *   at info AT gvsig.com, or visit our website www.gvsig.com.
24
 *   
25
 *******************************************************************************/
26
package org.gvsig.sldconverter.impl.legend;
27

    
28
import java.util.HashMap;
29
import java.util.Iterator;
30
import java.util.List;
31
import java.util.Map;
32

    
33
import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
34
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialIntervalLegend;
35
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
36
import org.gvsig.sldconverter.exception.UnsupportedSymbolException;
37
import org.gvsig.sldconverter.impl.util.BasicUtils;
38
import org.gvsig.sldsupport.exception.UnsupportedSLDObjectException;
39
import org.gvsig.sldsupport.sld.filter.FilterTags;
40
import org.gvsig.sldsupport.sld.filter.SLDFilter;
41
import org.gvsig.sldsupport.sld.filter.SLDFilterOperator;
42
import org.gvsig.sldsupport.sld.filter.expression.SLDExpression;
43
import org.gvsig.sldsupport.sld.filter.expression.operator.SLDLiteral;
44
import org.gvsig.sldsupport.sld.filter.expression.operator.SLDPropertyName;
45
import org.gvsig.sldsupport.sld.filter.operator.SLDComparisonOperator;
46
import org.gvsig.sldsupport.sld.filter.operator.comparison.SLDBinaryComparisonOperator;
47
import org.gvsig.sldsupport.sld.filter.operator.comparison.SLDIsBetweenOperator;
48
import org.gvsig.sldsupport.sld.layer.SLDLayer;
49
import org.gvsig.sldsupport.sld.layer.SLDNamedLayer;
50
import org.gvsig.sldsupport.sld.rule.SLDRule;
51
import org.gvsig.sldsupport.sld.style.SLDFeatureStyle;
52
import org.gvsig.sldsupport.sld.style.layer.SLDUserStyle;
53
import org.gvsig.sldsupport.sld.symbol.SLDSymbol;
54
import org.gvsig.tools.dataTypes.CoercionException;
55
import org.gvsig.tools.dataTypes.DataType;
56

    
57
public class IntervalsLegendUtils {
58
        
59
        
60
        public static IVectorialIntervalLegend toIntervalsLegend(List<SLDRule> rules)
61
                        throws UnsupportedSLDObjectException {
62
                
63
                IVectorialIntervalLegend intleg = (IVectorialIntervalLegend) 
64
                                BasicUtils.mapMan().createLegend(
65
                                                IVectorialIntervalLegend.LEGEND_NAME);
66
                
67
                String pname = BasicUtils.getFirstPropertyName(rules);
68
                if (pname == null || pname.length() == 0) {
69
                        throw new UnsupportedSLDObjectException(
70
                                        "SLDFeatureStyle", "Cannot interpret rules (no property name)");
71
                }
72
                List<SLDLiteral> lits = BasicUtils.getComparisonLiterals(rules);
73
                if (lits == null || lits.size() == 0) {
74
                        throw new UnsupportedSLDObjectException(
75
                                        "SLDFeatureStyle", "Cannot interpret rules (no literals)");
76
                }
77
                DataType dt = BasicUtils.guessDataType(lits);
78
                ISymbol sym = BasicUtils.getElseSymbol(rules);
79
                // sym can be null
80
                Map<IInterval, ISymbol> map =
81
                                IntervalsLegendUtils.getIntervalToSymbol(rules, dt, pname);
82
                Iterator iter = map.keySet().iterator();
83
                Object k = null;
84
                while (iter.hasNext()) {
85
                        k = iter.next();
86
                        intleg.addSymbol(k, map.get(k));
87
                }
88
                // Setting Default symbol
89
                if (sym != null) {
90
                        sym.setDescription("Default");
91
                        intleg.setDefaultSymbol(sym);
92
                        intleg.useDefaultSymbol(true);
93
                        // String among the intervals
94
                        intleg.addSymbol(sym.getDescription(), sym);
95
                } else {
96
                        intleg.useDefaultSymbol(false);
97
                }
98
                
99
                String[] atts = new String[1];
100
                atts[0] = pname;
101
                intleg.setClassifyingFieldNames(atts);
102
                int[] typs = new int[1];
103
                typs[0] = dt.getType();
104
                intleg.setClassifyingFieldTypes(typs);
105
                return intleg;        
106
        
107
        }
108
        
109
        
110
        public static boolean areRulesOfIntervals(List<SLDRule> rules) {
111

    
112
                if (rules == null || rules.size() == 0) {
113
                        return false;
114
                }
115
                
116
                SLDRule rule = null;
117
                String fieldName = null;
118
                for (int i=0; i<rules.size(); i++) {
119
                        rule = rules.get(i);
120
                        fieldName = getComparisonToNumericLiteralFieldName(rule);
121
                        if (fieldName != null) {
122
                                break;
123
                        }
124
                }
125
                
126
                if (fieldName == null) {
127
                        // The filter of first rule is not of type "field name equals literal"
128
                        return false;
129
                }
130
                int elsecount = 0;
131
                for (int i=1; i<rules.size(); i++) {
132
                        rule = rules.get(i);
133
                        if (!BasicUtils.isElse(rule)) {
134
                                String fname = getComparisonToNumericLiteralFieldName(rule);
135
                                if (fname == null || fname.compareTo(fieldName) != 0) {
136
                                        // Not a equals operation based on the same field
137
                                        return false;
138
                                }
139
                        } else {
140
                                elsecount++;
141
                        }
142
                                
143
                }
144
                // Found no reason to deny it's a interval legend
145
                // (if number of else filters is 0 or 1)
146
                return elsecount < 2;
147
        }
148
        
149
        
150
        /**
151
         * Returns the name of the field name on which the rule
152
         * is based if the rule is a interval comparison and the
153
         * operand is a literal. Otherwise returns null.
154
         *    
155
         * @param rule
156
         * @return
157
         */
158
        private static String getComparisonToNumericLiteralFieldName(SLDRule rule) {
159
                
160
                SLDFilter filt = rule.getFilter();
161
                if (filt == null) {
162
                        return null;
163
                }
164
                SLDFilterOperator oper = filt.getFilterOperator();
165
                if (!(oper instanceof SLDComparisonOperator)) {
166
                        // interval has to be SLDComparisonOperator
167
                        return null;
168
                }
169
                SLDComparisonOperator cop = (SLDComparisonOperator) oper;
170
                SLDPropertyName pname = null;
171
                if (cop instanceof SLDBinaryComparisonOperator) {
172
                        SLDBinaryComparisonOperator bco = (SLDBinaryComparisonOperator) cop;
173
                        String opname = bco.getComparisonOperator();
174
                        if (opname.compareTo(FilterTags.PROPERTYISGREATEROREQUALTHAN) == 0
175
                                        || opname.compareTo(FilterTags.PROPERTYISGREATERTHAN) == 0
176
                                        || opname.compareTo(FilterTags.PROPERTYISLESSOREQUALTHAN) == 0
177
                                        || opname.compareTo(FilterTags.PROPERTYISLESSTHAN) == 0) {
178

    
179
                                if (bco.getFirstExpression() instanceof SLDLiteral &&
180
                                                bco.getSecondExpression() instanceof SLDPropertyName) {
181
                                        
182
                                        pname = (SLDPropertyName) bco.getSecondExpression(); 
183
                                        if (BasicUtils.isNumeric((SLDLiteral) bco.getFirstExpression())) {
184
                                                return pname.getPropertyName();
185
                                        } else {
186
                                                return null;
187
                                        }
188
                                        
189
                                }
190
                                if (bco.getFirstExpression() instanceof SLDPropertyName &&
191
                                                bco.getSecondExpression() instanceof SLDLiteral) {
192
                                        
193
                                        pname = (SLDPropertyName) bco.getFirstExpression(); 
194
                                        if (BasicUtils.isNumeric((SLDLiteral) bco.getSecondExpression())) {
195
                                                return pname.getPropertyName();
196
                                        } else {
197
                                                return null;
198
                                        }
199
                                }
200
                        }
201
                } else {
202
                        if (cop instanceof SLDIsBetweenOperator) {
203
                                
204
                                SLDIsBetweenOperator beop = (SLDIsBetweenOperator) cop;
205
                                if (beop.getExpression() instanceof SLDPropertyName
206
                                                // Limits must be literals
207
                                                && beop.getLowerBoundary() instanceof SLDLiteral
208
                                                && beop.getUpperBoundary() instanceof SLDLiteral) {
209
                                        
210
                                        pname = (SLDPropertyName) beop.getExpression();
211
                                        if (BasicUtils.isNumeric((SLDLiteral) beop.getLowerBoundary())
212
                                                        && BasicUtils.isNumeric((SLDLiteral) beop.getUpperBoundary())) {
213
                                                return pname.getPropertyName();
214
                                        } else {
215
                                                return null;
216
                                        }
217
                                }
218
                        }
219
                }
220
                // Not the type we are looking for
221
                return null;
222
        }                
223
        
224
        
225
        public static SLDLayer toSLDLayer(IVectorialIntervalLegend legend)
226
                        throws UnsupportedSymbolException {
227
                
228
                String fname = legend.getClassifyingFieldNames()[0];
229
                SLDSymbol sldsym = null;
230
                SLDRule rule = null;
231
                SLDFeatureStyle fstyle = new SLDFeatureStyle();
232
                
233
                IInterval iival = null;
234
                String valstr = null;
235
                Object[] vals = legend.getValues();
236
                ISymbol[] syms = legend.getSymbols();
237
                int n = Math.min(vals.length, syms.length);
238
                SLDFilter filt = null;
239
                SLDComparisonOperator oper = null;
240
                ISymbol elsesym = null; 
241

    
242
                for (int i=0; i<n; i++) {
243
                        rule = new SLDRule();
244
                        // =====================
245
                        sldsym = BasicUtils.sldMan().toSLDSymbol(syms[i]);
246
                        rule.getSymbols().add(sldsym);
247
                        // =====================
248
                        if (vals[i] instanceof IInterval) {
249
                                filt = BasicUtils.supMan().createFilter();
250
                                filt.setIsElse(false);
251
                                iival = (IInterval) vals[i];
252
                                oper = intervalToComparisonOperator(iival, fname);
253
                                filt.setFilterOperator(oper);
254
                                // =====================
255
                                rule.setFilter(filt);
256
                                // ======================
257
                                fstyle.getRules().add(rule);
258
                        } else {
259
                                // assuming "Default"
260
                                elsesym = syms[i]; 
261
                        }
262
                }
263
                // ================ Default symbol
264
                
265
                // No "Default" value was found in intervals
266
                // but default sym is enabled
267
                if (elsesym == null && legend.isUseDefaultSymbol()) {
268
                        elsesym = legend.getDefaultSymbol();
269
                }
270

    
271
                if (elsesym != null) {
272
                        rule = new SLDRule();
273
                        sldsym = BasicUtils.sldMan().toSLDSymbol(elsesym);
274
                        rule.getSymbols().add(sldsym);
275
                        filt = BasicUtils.supMan().createFilter();
276
                        filt.setIsElse(true);
277
                        rule.setFilter(filt);
278
                        fstyle.getRules().add(rule);
279
                }
280
                // ======================
281
                SLDUserStyle usty = new SLDUserStyle();
282
                usty.getFeatureStyles().add(fstyle);
283
                
284
                SLDNamedLayer nlayer = new SLDNamedLayer();
285
                nlayer.setName("Name");
286
                nlayer.getStyles().add(usty);
287
                return nlayer;        
288
                
289
        }
290
        
291
        
292
        private static SLDComparisonOperator intervalToComparisonOperator(
293
                        IInterval iival, String fieldName) {
294
                
295
                double max = iival.getMax();
296
                double min = iival.getMin();
297
                if (max == Double.MAX_VALUE && min != -Double.MAX_VALUE) {
298
                        // greater than min
299
                        SLDBinaryComparisonOperator resp = new SLDBinaryComparisonOperator();
300
                        resp.setComparisonOperator(FilterTags.PROPERTYISGREATEROREQUALTHAN);
301
                        resp.setFirstExpression(new SLDPropertyName(fieldName));
302
                        
303
                        resp.setSecondExpression(new SLDLiteral(BasicUtils.df.format(min)));
304
                        return resp;
305
                        
306
                } else {
307
                        if (min == -Double.MAX_VALUE && max != Double.MAX_VALUE) {
308
                                // less than max
309
                                SLDBinaryComparisonOperator resp = new SLDBinaryComparisonOperator();
310
                                resp.setComparisonOperator(FilterTags.PROPERTYISLESSOREQUALTHAN);
311
                                resp.setFirstExpression(new SLDPropertyName(fieldName));
312
                                resp.setSecondExpression(new SLDLiteral(BasicUtils.df.format(max)));
313
                                return resp;
314
                                
315
                        } else {
316
                                // normal (between)
317
                                SLDIsBetweenOperator resp = new SLDIsBetweenOperator();
318
                                resp.setExpression(new SLDPropertyName(fieldName));
319
                                resp.setLowerBoundary(new SLDLiteral(BasicUtils.df.format(min)));
320
                                resp.setUpperBoundary(new SLDLiteral(BasicUtils.df.format(max)));
321
                                return resp;
322
                        }
323
                }
324
        }        
325
        
326
        
327
        
328
        /**
329
         * Translates rules to a interval-symbol correspondence.
330
         * 
331
         * @param rules
332
         * @param dt
333
         * @return
334
         * @throws UnsupportedSLDObjectException 
335
         * @throws CoercionException 
336
         */
337
        public static Map<IInterval, ISymbol> getIntervalToSymbol(
338
                        List<SLDRule> rules, DataType dt, String pname)
339
                                        throws UnsupportedSLDObjectException {
340
                
341
                Map<IInterval, ISymbol> resp = new HashMap<IInterval, ISymbol>();
342
                if (rules == null || rules.size() == 0) {
343
                        return resp;
344
                }
345
                SLDFilter filt = null;
346
                List<SLDSymbol> symList = null;
347
                SLDFilterOperator oper = null;
348
                SLDBinaryComparisonOperator binoper = null;
349
                ISymbol sym = null;
350
                SLDPropertyName sldpname = null;
351
                SLDLiteral sldlit = null;
352
                Object val = null;
353
                for (int i=0; i<rules.size(); i++) {
354
                        symList = rules.get(i).getSymbols();
355
                        if (symList == null || symList.size() == 0) {
356
                                /*
357
                                 * No symbols found
358
                                 */
359
                                continue;
360
                        }
361
                        filt = rules.get(i).getFilter();
362
                        if (filt == null) {
363
                                continue;
364
                        }
365
                        if (!filt.isElse()) {
366
                                oper = filt.getFilterOperator();
367
                                if (oper instanceof SLDComparisonOperator) {
368
                                        sym = BasicUtils.sldMan().toSymbol(symList.get(0));
369
                                        if (sym != null) {
370
                                                IInterval ival = getIntervalForSymbol(
371
                                                                (SLDComparisonOperator) oper, pname, sym);
372
                                                if (ival != null) {
373
                                                        resp.put(ival, sym);
374
                                                }
375
                                        }
376
                                }
377
                        } else {
378
                                // filter is else
379
                        }
380
                }
381
                return resp;
382
        }
383
        
384
        private static IInterval getIntervalForSymbol(
385
                        SLDComparisonOperator oper, String pname, ISymbol sym) {
386
                
387
                double min = 0;
388
                double max = 0;
389
                SLDBinaryComparisonOperator bc = null;
390
                SLDIsBetweenOperator bw = null;
391
                SLDLiteral lit = null;
392
                if (oper instanceof SLDBinaryComparisonOperator) {
393
                        bc = (SLDBinaryComparisonOperator) oper;
394
                        if (isGreaterComparison(bc)) {
395
                                lit = BasicUtils.getLiteral(bc.getExpressions());
396
                                try {
397
                                        min = Double.parseDouble(lit.getValue());
398
                                        max = Double.MAX_VALUE;
399
                                        sym.setDescription("> " + lit.getValue());
400
                                } catch (Exception exc) {
401
                                        return null;
402
                                }
403
                                
404
                        } else {
405
                                if (isLessThanComparison(bc)) {
406
                                        lit = BasicUtils.getLiteral(bc.getExpressions());
407
                                        try {
408
                                                max = Double.parseDouble(lit.getValue());
409
                                                min = -Double.MAX_VALUE;
410
                                                sym.setDescription("< " + lit.getValue());
411
                                        } catch (Exception exc) {
412
                                                return null;
413
                                        }
414
                                } else {
415
                                        return null;
416
                                }
417
                        }
418
                } else {
419
                        if (oper instanceof SLDIsBetweenOperator) {
420
                                bw = (SLDIsBetweenOperator) oper;
421
                                SLDExpression lower = bw.getLowerBoundary();
422
                                SLDExpression upper = bw.getUpperBoundary();
423
                                if (lower instanceof SLDLiteral && upper instanceof SLDLiteral) {
424
                                        String lowerstr = ((SLDLiteral) lower).getValue();
425
                                        String upperstr = ((SLDLiteral) upper).getValue();
426
                                        try {
427
                                                min = Double.parseDouble(lowerstr);
428
                                                max = Double.parseDouble(upperstr);
429
                                                sym.setDescription(lowerstr + " - " + upperstr);
430
                                        } catch (Exception exc) {
431
                                                return null;
432
                                        }
433
                                } else {
434
                                        return null;
435
                                }
436
                                
437
                        } else {
438
                                return null;
439
                        }
440
                }
441
                return BasicUtils.symMan().createInterval(min, max);
442
        }
443
        
444
        
445
        private static boolean isLessThanComparison(SLDBinaryComparisonOperator bc) {
446
                if (bc == null) {
447
                        return false;
448
                } else {
449
                        String comp = bc.getComparisonOperator();
450
                        return comp != null &&
451
                                        (comp.compareTo(FilterTags.PROPERTYISLESSOREQUALTHAN) == 0
452
                                        || comp.compareTo(FilterTags.PROPERTYISLESSTHAN) == 0);
453
                }
454
        }
455

    
456
        private static boolean isGreaterComparison(SLDBinaryComparisonOperator bc) {
457
                if (bc == null) {
458
                        return false;
459
                } else {
460
                        String comp = bc.getComparisonOperator();
461
                        return comp != null &&
462
                                        (comp.compareTo(FilterTags.PROPERTYISGREATEROREQUALTHAN) == 0
463
                                        || comp.compareTo(FilterTags.PROPERTYISGREATERTHAN) == 0);
464
                }
465
        }        
466
        
467
}