Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / org.gvsig.symbology / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / legend / impl / AbstractIntervalLegend.java @ 31631

History | View | Annotate | Download (19.5 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.util.ArrayList;
25
import java.util.Comparator;
26
import java.util.Date;
27
import java.util.Iterator;
28
import java.util.List;
29
import java.util.Map;
30
import java.util.TreeMap;
31
import java.util.Map.Entry;
32

    
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.DisposableIterator;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureQuery;
37
import org.gvsig.fmap.dal.feature.FeatureReference;
38
import org.gvsig.fmap.dal.feature.FeatureSet;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.mapcontext.MapContextException;
41
import org.gvsig.fmap.mapcontext.MapContextLocator;
42
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
43
import org.gvsig.fmap.mapcontext.rendering.legend.IInterval;
44
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorialIntervalLegend;
45
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
46
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dynobject.DynClass;
49
import org.gvsig.tools.persistence.PersistenceException;
50
import org.gvsig.tools.persistence.PersistentState;
51
import org.slf4j.Logger;
52
import org.slf4j.LoggerFactory;
53

    
54
/**
55
 * @author 2005-2008 jaume dominguez faus - jaume.dominguez@iver.es
56
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
57
 */
58
public abstract class AbstractIntervalLegend extends
59
                AbstractClassifiedVectorLegend implements IVectorialIntervalLegend {
60

    
61
        public static final String INTERVAL_LEGEND_DYNCLASS_NAME = "IntervalLegend";
62

    
63
        private static final String FIELD_KEYS = "keys";
64
        private static final String FIELD_INTERVAL_TYPE = "intervalType";
65
        private static final String FIELD_USE_DEFAULT_SYMBOL = "useDefaultSymbol";
66
        private static final String FIELD_NULL_INTERVAL_SYMBOL =
67
                        "nullIntervalSymbol";
68
        private static final String FIELD_SYMBOLS = "symbols";
69
        
70
        protected List<Object> keys = new ArrayList<Object>(); // <Object>
71
        // protected int index = 0;
72
        // protected int fieldId;
73
        protected ISymbol defaultSymbol;
74
        // protected FeatureStore featureStore;
75
        protected int intervalType = NATURAL_INTERVALS;
76
        protected boolean useDefaultSymbol = false;
77

    
78
        private ISymbol nullIntervalSymbol = null;
79

    
80
        public static final int EQUAL_INTERVALS = 0;
81
        public static final int NATURAL_INTERVALS = 1;
82
        public static final int QUANTILE_INTERVALS = 2;
83
        protected Map<Object, ISymbol> symbols = createSymbolMap();
84
        final static private Logger logger = LoggerFactory.getLogger(AbstractIntervalLegend.class);
85
        
86
        public void addSymbol(Object key, ISymbol symbol) {
87
                if (key == null) {
88
                        nullIntervalSymbol = symbol;
89
                }
90
                else {
91
                        symbols.put(key, symbol);
92
                        keys.add(key);
93
                }
94
                fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(null, symbol));
95
        }
96

    
97
        /*
98
         * @see com.iver.cit.gvsig.fmap.rendering.IVectorialLegend#getSymbol(int)
99
         */
100
        public ISymbol getSymbol(FeatureReference featureID)
101
                        throws MapContextException, DataException {
102
                return getSymbolByFeature(featureID.getFeature());
103
                
104
//                Object val = featureStore.getFeatureByReference(featureID).get(getClassifyingFieldNames()[0]);
105
//                IInterval interval = getInterval(val);
106
//                ISymbol theSymbol = getSymbolByInterval(interval);
107
//
108
//                if (theSymbol != null) {
109
//                        return theSymbol;
110
//                } else if (useDefaultSymbol) {
111
//                        return getDefaultSymbol();
112
//                }
113
//                return null;
114

    
115
        }
116

    
117
        public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
118
                Object val = feat.get(getClassifyingFieldNames()[0]);
119
                IInterval interval = getInterval(val);
120
                ISymbol theSymbol = getSymbolByInterval(interval);
121

    
122
                if (theSymbol != null) {
123
                        return theSymbol;
124
                } else if (useDefaultSymbol) {
125
                        return getDefaultSymbol();
126
                }
127
                
128
                return null;
129
//                return theSymbol;
130
        }
131

    
132

    
133
        public IInterval[] calculateIntervals(FeatureStore featureStore,
134
                        String fieldName, int numIntervalos, int shapeType)
135
        throws DataException {
136
                logger.debug("elRs.start()");
137
//                recordSet.start();
138

    
139
//                int idField = -1;
140
                FeatureSet set = null;
141
                DisposableIterator iterator = null;
142
                try {
143

    
144
                setClassifyingFieldNames(new String[] {fieldName});
145

    
146
                String[] fieldNames = getClassifyingFieldNames();
147
                FeatureQuery featureQuery=featureStore.createFeatureQuery();
148
                featureQuery.setAttributeNames(fieldNames);
149

    
150
                set = featureStore.getFeatureSet(featureQuery);
151
                iterator = set.fastIterator();
152

    
153

    
154
//                for (int i = 0; i < recordSet.getFieldCount(); i++) {
155
//                        String nomAux = recordSet.getFieldName(i).trim();
156
//
157
//                        if (fieldNames[0].compareToIgnoreCase(nomAux) == 0) {
158
//                                idField = i;
159
//
160
//                                break;
161
//                        }
162
//                }
163

    
164
//                if (idField == -1) {
165
//                        logger.error("Campo no reconocido " + fieldNames);
166
//
167
//                        return null;
168
//                }
169

    
170
                double minValue = Double.MAX_VALUE;
171
                double maxValue = Double.NEGATIVE_INFINITY;
172

    
173
                IVectorialIntervalLegend auxLegend = (IVectorialIntervalLegend) MapContextLocator
174
                                        .getMapContextManager().createLegend("VectorialInterval");
175
                auxLegend.setShapeType(shapeType);
176

    
177
                Object clave;
178

    
179
                while (iterator.hasNext()) {
180
                        Feature feature = (Feature) iterator.next();
181

    
182
//                for (int j = 0; j < recordSet.getRowCount(); j++) {
183
                        clave = feature.get(fieldName);
184

    
185
                        IInterval interval = auxLegend.getInterval(clave);
186

    
187
                        ////Comprobar que no esta repetido y no hace falta introducir en el hashtable el campo junto con el simbolo.
188
                        if (auxLegend.getSymbolByInterval(interval) == null) {
189
                                //si no esta creado el simbolo se crea
190
                                double valor = 0;
191

    
192

    
193
                                if (clave instanceof Number) {
194
                                        valor=((Number)clave).doubleValue();
195
                                }else if (clave instanceof Date) {
196
                                        //TODO POR IMPLEMENTAR
197
                                        ///valorDate = elRs.getFieldValueAsDate(idField);
198
                                        ///if (valorDate.before(minValueDate)) minValueDate = valorDate;
199
                                        ///if (valorDate.after(maxValueDate)) maxValueDate = valorDate;
200
//                                } else if (clave instanceof NullValue) {
201
//                                        continue;
202
                                }
203

    
204
                                if (valor < minValue) {
205
                                        minValue = valor;
206
                                }
207

    
208
                                if (valor > maxValue) {
209
                                        maxValue = valor;
210
                                }
211
                        }
212
                }
213

    
214
                        IInterval[] intervalArray = null;
215
                switch (getIntervalType()) {
216
                case VectorialIntervalLegend.EQUAL_INTERVALS:
217
                        intervalArray = calculateEqualIntervals(numIntervalos,
218
                                        minValue, maxValue, fieldName);
219

    
220
                        break;
221

    
222
                case VectorialIntervalLegend.NATURAL_INTERVALS:
223
                        intervalArray = calculateNaturalIntervals(featureStore, numIntervalos,
224
                                        minValue, maxValue, fieldName);
225

    
226
                        break;
227

    
228
                case VectorialIntervalLegend.QUANTILE_INTERVALS:
229
                        intervalArray = calculateQuantileIntervals(featureStore, numIntervalos,
230
                                        minValue, maxValue, fieldName);
231

    
232
                        break;
233
                }
234
//                recordSet.stop();
235
                return intervalArray;
236
                } finally {
237
                        if (iterator != null) {
238
                                iterator.dispose();
239
                        }
240
                        if (set != null) {
241
                                set.dispose();
242
                        }
243
                }
244
        }
245

    
246

    
247
    /**
248
     * EQUAL INTERVAL Devuelve un Array con el n?mero de intervalos que se
249
     * quieren crear. Los intervalos se crean con un tama?o igual entre ellos.
250
     * @param numIntervals n?mero de intervalos
251
     * @param minValue Valor m?nimo.
252
     * @param maxValue Valor m?ximo.
253
     * @param fieldName Nombre del campo
254
     *
255
     * @return Array con los intervalos.
256
     */
257
        private IInterval[] calculateEqualIntervals(int numIntervals,
258
                        double minValue,
259
        double maxValue, String fieldName) {
260
                IInterval[] theIntervalArray = new IInterval[numIntervals];
261
        double step = (maxValue - minValue) / numIntervals;
262

    
263
        if (numIntervals > 1) {
264
            theIntervalArray[0] = new FInterval(minValue, minValue + step);
265

    
266
            for (int i = 1; i < (numIntervals - 1); i++) {
267
                theIntervalArray[i] = new FInterval(minValue + (i * step) +
268
                        0.01, minValue + ((i + 1) * step));
269
            }
270

    
271
            theIntervalArray[numIntervals - 1] = new FInterval(minValue +
272
                    ((numIntervals - 1) * step) + 0.01, maxValue);
273
        } else {
274
            theIntervalArray[0] = new FInterval(minValue, maxValue);
275
        }
276

    
277
        return theIntervalArray;
278
    }
279

    
280
    /**
281
     * NATURAL INTERVAL Devuelve un Array con el n?mero de intervalos que se
282
     * quieren crear. Los intervalos se distribuyen de forma natural.
283
     *
284
     * @param numIntervals n?mero de intervalos
285
     * @param minValue Valor m?nimo.
286
     * @param maxValue Valor m?ximo.
287
     * @param fieldName Nombre del campo
288
     *
289
     * @return Array con los intervalos.
290
     * @throws DataException 
291
     * @throws LegendLayerException
292
     */
293
        private IInterval[] calculateNaturalIntervals(FeatureStore featureStore,
294
                        int numIntervals, double minValue,
295
        double maxValue, String fieldName) throws DataException {
296
        NaturalIntervalGenerator intervalGenerator = new NaturalIntervalGenerator(
297
                        featureStore, fieldName, numIntervals);
298

    
299
        intervalGenerator.generarIntervalos();
300

    
301
        int numIntervalsGen = intervalGenerator.getNumIntervals() - 1;
302

    
303
        if (numIntervalsGen == -1) {
304
            //TODO cuando no puede calcular los intervalos.
305
            numIntervalsGen = 1;
306
        }
307

    
308
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
309

    
310
        if (numIntervalsGen > 1) {
311
            theIntervalArray[0] = new FInterval(minValue,
312
                    intervalGenerator.getValorRuptura(0));
313

    
314
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
315
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
316
                            1), intervalGenerator.getValorRuptura(i));
317
            }
318

    
319
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
320
                        2), maxValue);
321
        } else {
322
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
323
                    maxValue);
324
        }
325

    
326
        return theIntervalArray;
327
    }
328

    
329
    /**
330
     * QUANTILE INTERVAL Devuelve un Array con el n?mero de intervalos que se
331
     * quieren crear. Los intervalos se distribuyen de forma quantile.
332
     * @param recordSet
333
     *
334
     * @param numIntervals n?mero de intervalos
335
     * @param minValue Valor m?nimo.
336
     * @param maxValue Valor m?ximo.
337
     * @param fieldName Nombre del campo
338
     *
339
     * @return Array con los intervalos.
340
     * @throws LegendLayerException
341
     */
342
        private IInterval[] calculateQuantileIntervals(FeatureStore featureStore,
343
                        int numIntervals, double minValue,
344
        double maxValue, String fieldName) throws DataException {
345
        QuantileIntervalGenerator intervalGenerator = new QuantileIntervalGenerator(
346
                        featureStore, fieldName, numIntervals);
347

    
348
        intervalGenerator.generarIntervalos();
349

    
350
        int numIntervalsGen = intervalGenerator.getNumIntervalGen();
351
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
352

    
353
        if (intervalGenerator.getNumIntervalGen() > 1) {
354
            theIntervalArray[0] = new FInterval(minValue,
355
                    intervalGenerator.getValRuptura(0));
356

    
357
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
358
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
359
                            1), intervalGenerator.getValRuptura(i));
360
            }
361

    
362
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
363
                        2), maxValue);
364
        } else {
365
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
366
                    maxValue);
367
        }
368

    
369
        return theIntervalArray;
370
    }
371

    
372
    public ISymbol getSymbolByInterval(IInterval key) {
373

    
374
                if (key == null){
375
                        if (nullIntervalSymbol != null) {
376
                                return nullIntervalSymbol;
377
                        }
378
                        else if (isUseDefaultSymbol()) {
379
                                return defaultSymbol;
380
                        }
381
                        return null;
382
                }
383
                if (symbols.containsKey(key)) {
384
                        return (ISymbol) symbols.get(key);
385
                }
386

    
387
                if (isUseDefaultSymbol()) {
388
                        return defaultSymbol;
389
                }
390

    
391
                return null;
392
        }
393

    
394

    
395
        public String[] getDescriptions() {
396
                String[] descriptions = new String[symbols.size()];
397
                ISymbol[] auxSym = getSymbols();
398

    
399
                for (int i = 0; i < descriptions.length; i++) {
400
                        descriptions[i] = auxSym[i].getDescription();
401
                }
402

    
403
                return descriptions;
404
        }
405

    
406

    
407
        public Object[] getValues() {
408
                return symbols.keySet().toArray();
409
        }
410

    
411
        public void clear() {
412
                // index = 0;
413
                keys.clear();
414
                symbols.clear();
415
        }
416

    
417
        public ISymbol[] getSymbols() {
418
                ISymbol[] symbolList;
419
                if (nullIntervalSymbol == null) {
420
                        symbolList = new ISymbol[symbols.size()];
421
                        return (ISymbol[]) symbols.values().toArray(symbolList);
422
                }
423
                else {
424
                        symbolList = new ISymbol[symbols.size() + 1];
425
                        symbolList[0] = nullIntervalSymbol;
426
                        int i = 1;
427
                        for (Iterator<ISymbol> iterator = symbols.values().iterator(); iterator.hasNext();) {
428
                                symbolList[i] = iterator.next();
429
                                i++;
430
                        }
431
                        return symbolList;
432
                }
433
        }
434

    
435
        public void setDefaultSymbol(ISymbol s) {
436
            ISymbol old = defaultSymbol;
437
                if (s == null) {
438
                        throw new NullPointerException("Default symbol cannot be null");
439
                }
440
                defaultSymbol = s;
441
                fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
442
        }
443

    
444
        public ISymbol getDefaultSymbol() {
445
//                NullIntervalValue niv=new NullIntervalValue();
446
//                if (symbols.containsKey(niv)) {
447
//                        return (ISymbol)symbols.get(niv);
448
//                }
449

    
450
                if(defaultSymbol==null) {
451
                        defaultSymbol = getSymbolManager().createSymbol(getShapeType());
452
                }
453
                return defaultSymbol;
454
        }
455

    
456

    
457

    
458
//    public void setFeatureStore(FeatureStore featureStore)
459
//        throws DataException {
460
//                    /*
461
//                     * when we move definitely to feature iterators this
462
//                     * method
463
//                     */
464
//                    this.featureStore = featureStore;
465
////                    fieldId = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(fieldNames[0]);
466
//    }
467

    
468

    
469
        public IInterval getInterval(Object v) {
470
                if (v != null ) {
471
                        for (int i = 0; i < keys.size(); i++) {
472
                                if (((IInterval) keys.get(i)).isInInterval(v)) {
473
                                        return (IInterval) keys.get(i);
474
                                }
475
                        }
476
                }
477

    
478
                return null;
479
        }
480

    
481
        public void setIntervalType(int intervalType) {
482
                this.intervalType = intervalType;
483
        }
484

    
485

    
486
        public int getIntervalType() {
487
                return intervalType;
488
        }
489

    
490
        public void useDefaultSymbol(boolean b) {
491
                useDefaultSymbol = b;
492
        }
493

    
494

    
495
        public boolean isUseDefaultSymbol() {
496
                return useDefaultSymbol;
497
        }
498

    
499

    
500
        public void delSymbol(Object obj) {
501
                keys.remove(obj);
502
                symbols.remove(obj);
503
                fireClassifiedSymbolChangeEvent(
504
                                new SymbolLegendEvent(
505
                                                (ISymbol)symbols.remove(obj),
506
                                                null));
507
        }
508

    
509

    
510
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
511
                if (symbols.containsValue(oldSymbol)) {
512
                        Iterator<Object> it = symbols.keySet().iterator();
513
                        while (it.hasNext()) {
514
                                Object key = it.next();
515
                                if (symbols.get(key).equals(oldSymbol)) {
516
                                        symbols.remove(key);
517
                                        symbols.put(key, newSymbol);
518
                                        fireClassifiedSymbolChangeEvent(
519
                                                        new SymbolLegendEvent(oldSymbol, newSymbol));
520
                                }
521
                        }
522
                }
523
        }
524

    
525
        public Object clone() throws CloneNotSupportedException {
526
                AbstractIntervalLegend clone = (AbstractIntervalLegend) super.clone();
527

    
528
                // Clone null interval symbol
529
                if (nullIntervalSymbol != null) {
530
                        clone.nullIntervalSymbol = (ISymbol) nullIntervalSymbol.clone();
531
                }
532
                
533
                // Clone default symbol
534
                if (defaultSymbol != null) {
535
                        clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
536
                }
537
                // Clone keys
538
                clone.keys = new ArrayList<Object>();
539
                
540
                // Clone symbols
541
                if (symbols != null) {
542
                        clone.symbols = createSymbolMap();
543
                        for (Iterator<Entry<Object, ISymbol>> iterator =
544
                                        symbols.entrySet().iterator(); iterator.hasNext();) {
545
                                Entry<Object, ISymbol> entry = iterator.next();
546
                                IInterval intervalClone =
547
                                                (IInterval) ((IInterval) entry.getKey()).clone();
548
                                ISymbol symbolClone =
549
                                                (ISymbol) ((ISymbol) entry.getValue()).clone();
550
                                clone.addSymbol(intervalClone, symbolClone);
551
                        }
552
                }
553

    
554
                return clone;
555
        }
556

    
557
        @SuppressWarnings("unchecked")
558
        public void loadFromState(PersistentState state)
559
                        throws PersistenceException {
560
                // Set parent properties
561
                super.loadFromState(state);
562
                // Set own properties
563
                setIntervalType(state.getInt(FIELD_INTERVAL_TYPE));
564
                keys = new ArrayList<Object>(state.getList(FIELD_KEYS));
565
                nullIntervalSymbol = (ISymbol) state.get(FIELD_NULL_INTERVAL_SYMBOL);
566
                useDefaultSymbol(state.getBoolean(FIELD_USE_DEFAULT_SYMBOL));
567
                Map persistedSymbolMap = (Map) state.get(FIELD_SYMBOLS);
568
                if (persistedSymbolMap != null) {
569
                        symbols.putAll(persistedSymbolMap);
570
                }
571
        }
572

    
573
        public void saveToState(PersistentState state) throws PersistenceException {
574
                // Save parent properties
575
                super.saveToState(state);
576
                // Save own properties
577
                state.set(FIELD_INTERVAL_TYPE, getIntervalType());
578
                state.set(FIELD_KEYS, keys);
579
                state.set(FIELD_NULL_INTERVAL_SYMBOL, nullIntervalSymbol);
580
                state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
581
                state.set(FIELD_SYMBOLS, symbols);
582
        }
583

    
584
        public static void registerPersistence() {
585
                // Add the DynClass definition.
586
                DynClass dynClass =
587
                                ToolsLocator.getDynObjectManager().add(
588
                                                INTERVAL_LEGEND_DYNCLASS_NAME);
589

    
590
                // Extend the Classified Vector Legend base definition
591
                dynClass.extend(CLASSIFIED_VECTOR_LEGEND_DYNCLASS_NAME);
592

    
593
                // Interval type
594
                dynClass.addDynFieldInt(FIELD_INTERVAL_TYPE).setMandatory(true);
595
                // Keys
596
                dynClass.addDynFieldList(FIELD_KEYS);
597
                // Null interval symbol
598
                dynClass.addDynFieldObject(FIELD_NULL_INTERVAL_SYMBOL);
599
                // Use default symbol?
600
                dynClass.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
601
                // Symbols
602
                dynClass.addDynFieldMap(FIELD_SYMBOLS);
603
        }
604

    
605
        private Map<Object, ISymbol> createSymbolMap() {
606
                return new TreeMap<Object, ISymbol>
607
                (new Comparator<Object>() { 
608
                                        public int compare(Object o1, Object o2) {
609
                                                if ((o1 != null) && (o2 != null)) {
610
                                                        // if (o1 instanceof NullIntervalValue &&
611
                                                        // o2 instanceof NullIntervalValue) {
612
                                                        // return 0;
613
                                                        // }
614
                                                        //
615
                                                        // if (o2 instanceof NullIntervalValue) {
616
                                                        // return 1;
617
                                                        // }
618
                                                        //
619
                                                        // if (o1 instanceof NullIntervalValue) {
620
                                                        // return -1;
621
                                                        // }
622

    
623
                                                        FInterval i2 = (FInterval) o2;
624
                                                        FInterval i1 = (FInterval) o1;
625

    
626
                                                        if (i1.getMin() > i2.getMin()) {
627
                                                                return 1;
628
                                                        }
629

    
630
                                                        if (i1.getMin() < i2.getMin()) {
631
                                                                return -1;
632
                                                        }
633
                                                        if (i1.getMax() < i2.getMax()) {
634
                                                                return -1;
635
                                                        }
636
                                                        if (i1.getMax() > i2.getMax()) {
637
                                                                return 1;
638
                                                        }
639
                                                }
640

    
641
                                                return 0;
642
                                        }
643
                                });
644
        }
645
}