Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / legend / impl / AbstractIntervalLegend.java @ 42811

History | View | Annotate | Download (20.3 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
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl;
25

    
26
import java.util.ArrayList;
27
import java.util.Comparator;
28
import java.util.Date;
29
import java.util.Iterator;
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Map.Entry;
33
import java.util.TreeMap;
34

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

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

    
65
        public static final String INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME = "IntervalLegend";
66

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

    
80
        // private ISymbol nullIntervalSymbol = null;
81

    
82
        public static final int EQUAL_INTERVALS = 0;
83
        public static final int NATURAL_INTERVALS = 1;
84
        public static final int QUANTILE_INTERVALS = 2;
85
        protected Map<Object, ISymbol> symbols = createSymbolMap();
86
        final static private Logger logger = LoggerFactory.getLogger(AbstractIntervalLegend.class);
87
        
88
        public void addSymbol(Object key, ISymbol symbol) {
89
                if (key == null) {
90
                    // why did we use this?
91
                        // nullIntervalSymbol = symbol;
92
                    logger.info(
93
                        "Warning: tried to add symbol with null key.",
94
                        new Exception("Key is NULL"));
95
                } else {
96
                        symbols.put(key, symbol);
97
                        keys.add(key);
98
                        fireClassifiedSymbolChangeEvent(new SymbolLegendEvent(null, symbol));
99
                }
100
        }
101

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

    
120
        }
121

    
122
        public ISymbol getSymbolByFeature(Feature feat) throws MapContextException {
123
                Object val = feat.get(getClassifyingFieldNames()[0]);
124
                IInterval interval = getInterval(val);
125
                ISymbol theSymbol = getSymbolByInterval(interval);
126

    
127
                if (theSymbol != null) {
128
                        return theSymbol;
129
                } else if (useDefaultSymbol) {
130
                        return getDefaultSymbol();
131
                }
132
                
133
                return null;
134
//                return theSymbol;
135
        }
136

    
137

    
138
        public IInterval[] calculateIntervals(FeatureStore featureStore,
139
                        String fieldName, int numIntervalos, int shapeType)
140
        throws DataException {
141
                logger.debug("elRs.start()");
142
//                recordSet.start();
143

    
144
//                int idField = -1;
145
                FeatureSet set = null;
146
                DisposableIterator iterator = null;
147
                try {
148

    
149
                setClassifyingFieldNames(new String[] {fieldName});
150

    
151
                String[] fieldNames = getClassifyingFieldNames();
152
                FeatureQuery featureQuery=featureStore.createFeatureQuery();
153
                featureQuery.setAttributeNames(fieldNames);
154

    
155
                set = featureStore.getFeatureSet(featureQuery);
156
                iterator = set.fastIterator();
157

    
158

    
159
//                for (int i = 0; i < recordSet.getFieldCount(); i++) {
160
//                        String nomAux = recordSet.getFieldName(i).trim();
161
//
162
//                        if (fieldNames[0].compareToIgnoreCase(nomAux) == 0) {
163
//                                idField = i;
164
//
165
//                                break;
166
//                        }
167
//                }
168

    
169
//                if (idField == -1) {
170
//                        logger.error("Campo no reconocido " + fieldNames);
171
//
172
//                        return null;
173
//                }
174

    
175
                double minValue = Double.MAX_VALUE;
176
                double maxValue = Double.NEGATIVE_INFINITY;
177

    
178
                IVectorialIntervalLegend auxLegend = (IVectorialIntervalLegend) MapContextLocator
179
                                        .getMapContextManager().createLegend("VectorialInterval");
180
                auxLegend.setShapeType(shapeType);
181

    
182
                Object clave;
183

    
184
                while (iterator.hasNext()) {
185
                        Feature feature = (Feature) iterator.next();
186

    
187
//                for (int j = 0; j < recordSet.getRowCount(); j++) {
188
                        clave = feature.get(fieldName);
189

    
190
                        IInterval interval = auxLegend.getInterval(clave);
191

    
192
                        ////Comprobar que no esta repetido y no hace falta introducir en el hashtable el campo junto con el simbolo.
193
                        if (auxLegend.getSymbolByInterval(interval) == null) {
194
                                //si no esta creado el simbolo se crea
195
                                double valor = 0;
196

    
197

    
198
                                if (clave instanceof Number) {
199
                                        valor=((Number)clave).doubleValue();
200
                                }else if (clave instanceof Date) {
201
                                        //TODO POR IMPLEMENTAR
202
                                        ///valorDate = elRs.getFieldValueAsDate(idField);
203
                                        ///if (valorDate.before(minValueDate)) minValueDate = valorDate;
204
                                        ///if (valorDate.after(maxValueDate)) maxValueDate = valorDate;
205
//                                } else if (clave instanceof NullValue) {
206
//                                        continue;
207
                                }
208

    
209
                                if (valor < minValue) {
210
                                        minValue = valor;
211
                                }
212

    
213
                                if (valor > maxValue) {
214
                                        maxValue = valor;
215
                                }
216
                        }
217
                }
218

    
219
                        IInterval[] intervalArray = null;
220
                switch (getIntervalType()) {
221
                case VectorialIntervalLegend.EQUAL_INTERVALS:
222
                        intervalArray = calculateEqualIntervals(numIntervalos,
223
                                        minValue, maxValue, fieldName);
224

    
225
                        break;
226

    
227
                case VectorialIntervalLegend.NATURAL_INTERVALS:
228
                        intervalArray = calculateNaturalIntervals(featureStore, numIntervalos,
229
                                        minValue, maxValue, fieldName);
230

    
231
                        break;
232

    
233
                case VectorialIntervalLegend.QUANTILE_INTERVALS:
234
                        intervalArray = calculateQuantileIntervals(featureStore, numIntervalos,
235
                                        minValue, maxValue, fieldName);
236

    
237
                        break;
238
                }
239
//                recordSet.stop();
240
                return intervalArray;
241
                } finally {
242
                        if (iterator != null) {
243
                                iterator.dispose();
244
                        }
245
                        if (set != null) {
246
                                set.dispose();
247
                        }
248
                }
249
        }
250

    
251

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

    
268
        if (numIntervals > 1) {
269
            theIntervalArray[0] = new FInterval(minValue, minValue + step);
270

    
271
            for (int i = 1; i < (numIntervals - 1); i++) {
272
                theIntervalArray[i] = new FInterval(minValue + (i * step) +
273
                        0.01, minValue + ((i + 1) * step));
274
            }
275

    
276
            theIntervalArray[numIntervals - 1] = new FInterval(minValue +
277
                    ((numIntervals - 1) * step) + 0.01, maxValue);
278
        } else {
279
            theIntervalArray[0] = new FInterval(minValue, maxValue);
280
        }
281

    
282
        return theIntervalArray;
283
    }
284

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

    
304
        intervalGenerator.generarIntervalos();
305

    
306
        int numIntervalsGen = intervalGenerator.getNumIntervals() - 1;
307

    
308
        if (numIntervalsGen == -1) {
309
            //TODO cuando no puede calcular los intervalos.
310
            numIntervalsGen = 1;
311
        }
312

    
313
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
314

    
315
        if (numIntervalsGen > 1) {
316
            theIntervalArray[0] = new FInterval(minValue,
317
                    intervalGenerator.getValorRuptura(0));
318

    
319
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
320
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
321
                            1), intervalGenerator.getValorRuptura(i));
322
            }
323

    
324
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
325
                        2), maxValue);
326
        } else {
327
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
328
                    maxValue);
329
        }
330

    
331
        return theIntervalArray;
332
    }
333

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

    
353
        intervalGenerator.generarIntervalos();
354

    
355
        int numIntervalsGen = intervalGenerator.getNumIntervalGen();
356
        FInterval[] theIntervalArray = new FInterval[numIntervalsGen];
357

    
358
        if (intervalGenerator.getNumIntervalGen() > 1) {
359
            theIntervalArray[0] = new FInterval(minValue,
360
                    intervalGenerator.getValRuptura(0));
361

    
362
            for (int i = 1; i < (numIntervalsGen - 1); i++) {
363
                theIntervalArray[i] = new FInterval(intervalGenerator.getValInit(i -
364
                            1), intervalGenerator.getValRuptura(i));
365
            }
366

    
367
            theIntervalArray[numIntervalsGen - 1] = new FInterval(intervalGenerator.getValInit(numIntervalsGen -
368
                        2), maxValue);
369
        } else {
370
            theIntervalArray[numIntervalsGen - 1] = new FInterval(minValue,
371
                    maxValue);
372
        }
373

    
374
        return theIntervalArray;
375
    }
376

    
377
    public ISymbol getSymbolByInterval(IInterval key) {
378

    
379
                if (key == null){
380
                        if (isUseDefaultSymbol()) {
381
                                return defaultSymbol;
382
                        }
383
                        return null;
384
                }
385
                if (symbols.containsKey(key)) {
386
                        return (ISymbol) symbols.get(key);
387
                }
388

    
389
                if (isUseDefaultSymbol()) {
390
                        return defaultSymbol;
391
                }
392

    
393
                return null;
394
        }
395

    
396

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

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

    
405
                return descriptions;
406
        }
407

    
408

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

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

    
419
        public ISymbol[] getSymbols() {
420
                ISymbol[] symbolList;
421
        symbolList = new ISymbol[symbols.size()];
422
        return (ISymbol[]) symbols.values().toArray(symbolList);
423
        }
424

    
425
        public void setDefaultSymbol(ISymbol s) {
426
            ISymbol old = defaultSymbol;
427
                if (s == null) {
428
                        throw new NullPointerException("Default symbol cannot be null");
429
                }
430
                defaultSymbol = s;
431
                fireDefaultSymbolChangedEvent(new SymbolLegendEvent(old, defaultSymbol));
432
        }
433

    
434
        @Override
435
        public ISymbol getDefaultSymbol() {
436
//                NullIntervalValue niv=new NullIntervalValue();
437
//                if (symbols.containsKey(niv)) {
438
//                        return (ISymbol)symbols.get(niv);
439
//                }
440

    
441
                if(defaultSymbol==null) {
442
                        defaultSymbol = getSymbolManager().createSymbol(getShapeType());
443
                }
444
                return defaultSymbol;
445
        }
446

    
447

    
448

    
449
//    public void setFeatureStore(FeatureStore featureStore)
450
//        throws DataException {
451
//                    /*
452
//                     * when we move definitely to feature iterators this
453
//                     * method
454
//                     */
455
//                    this.featureStore = featureStore;
456
////                    fieldId = ((FeatureType)featureStore.getFeatureTypes().get(0)).getIndex(fieldNames[0]);
457
//    }
458

    
459

    
460
        public IInterval getInterval(Object v) {
461
                if (v != null ) {
462
                        for (int i = 0; i < keys.size(); i++) {
463
                            
464
                            Object obj_key = keys.get(i);
465
                            if (obj_key instanceof IInterval) {
466
                        if (((IInterval) obj_key).isInInterval(v)) {
467
                            return (IInterval) obj_key;
468
                        }
469
                            }
470
                        }
471
                }
472

    
473
                return null;
474
        }
475

    
476
        public void setIntervalType(int intervalType) {
477
                this.intervalType = intervalType;
478
        }
479

    
480

    
481
        public int getIntervalType() {
482
                return intervalType;
483
        }
484

    
485
        public void useDefaultSymbol(boolean b) {
486
                useDefaultSymbol = b;
487
        }
488

    
489

    
490
        public boolean isUseDefaultSymbol() {
491
                return useDefaultSymbol;
492
        }
493

    
494

    
495
        public void delSymbol(Object obj) {
496
                keys.remove(obj);
497
                symbols.remove(obj);
498
                fireClassifiedSymbolChangeEvent(
499
                                new SymbolLegendEvent(
500
                                                (ISymbol)symbols.remove(obj),
501
                                                null));
502
        }
503

    
504

    
505
        public void replace(ISymbol oldSymbol, ISymbol newSymbol) {
506
                if (symbols.containsValue(oldSymbol)) {
507
                    
508
                        Iterator<Object> it = symbols.keySet().iterator();
509
                        List key_list = new ArrayList();
510
                        
511
                        while (it.hasNext()) {
512
                                Object key = it.next();
513
                                if (symbols.get(key).equals(oldSymbol)) {
514
                                    key_list.add(key);
515
                                    // symbols.remove(key);
516
                                }
517
                        }
518
                        
519
                        for (int i=0; i<key_list.size(); i++) {
520
                            Object k = key_list.get(i);
521
                            symbols.put(k, newSymbol);
522
                        }
523
            fireClassifiedSymbolChangeEvent(
524
                new SymbolLegendEvent(oldSymbol, newSymbol));
525

    
526
                }
527
        }
528

    
529
        public Object clone() throws CloneNotSupportedException {
530
                AbstractIntervalLegend clone = (AbstractIntervalLegend) super.clone();
531

    
532
                // Clone default symbol
533
                if (defaultSymbol != null) {
534
                        clone.defaultSymbol = (ISymbol) defaultSymbol.clone();
535
                }
536
                // Clone keys
537
                clone.keys = new ArrayList<Object>();
538
                
539
                // Clone symbols
540
                if (symbols != null) {
541
                        clone.symbols = createSymbolMap();
542
                        for (Iterator<Entry<Object, ISymbol>> iterator =
543
                                        symbols.entrySet().iterator(); iterator.hasNext();) {
544
                                Entry<Object, ISymbol> entry = iterator.next();
545
                                
546
                                Object key = entry.getKey();
547
                                IInterval key_interval = null;
548
                                if (key instanceof IInterval) {
549
                                    key_interval = (IInterval) key;
550
                                    key = key_interval.clone();
551
                                }
552
                                ISymbol symbolClone =
553
                                                (ISymbol) ((ISymbol) entry.getValue()).clone();
554
                                clone.addSymbol(key, symbolClone);
555
                        }
556
                }
557
                
558
                clone.setIntervalType(this.getIntervalType());
559

    
560
                return clone;
561
        }
562

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

    
578
        public void saveToState(PersistentState state) throws PersistenceException {
579
                // Save parent properties
580
                super.saveToState(state);
581
                // Save own properties
582
                state.set(FIELD_INTERVAL_TYPE, getIntervalType());
583
                state.set(FIELD_KEYS, keys);
584
                state.set(FIELD_USE_DEFAULT_SYMBOL, isUseDefaultSymbol());
585
                state.set(FIELD_SYMBOLS, symbols);
586
        }
587

    
588
        public static class RegisterPersistence implements Callable {
589

    
590
                public Object call() throws Exception {
591
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
592
                        if( manager.getDefinition(INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME)==null ) {
593
                                DynStruct definition = manager.addDefinition(
594
                                                AbstractIntervalLegend.class,
595
                                                INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME,
596
                                                INTERVAL_LEGEND_PERSISTENCE_DEFINITION_NAME+" Persistence definition (FIXME check keys type)",
597
                                                null, 
598
                                                null
599
                                );
600
                                
601
                                // Extend the Classified Vector Legend base definition
602
                                definition.extend(manager.getDefinition(CLASSIFIED_VECTOR_LEGEND_PERSISTENCE_DEFINITION_NAME));
603

    
604
                                // Interval type
605
                                definition.addDynFieldInt(FIELD_INTERVAL_TYPE).setMandatory(true);
606
                                // Keys
607
                                definition.addDynFieldList(FIELD_KEYS)
608
                                        .setClassOfItems(int.class);
609
                                // Use default symbol?
610
                                definition.addDynFieldBoolean(FIELD_USE_DEFAULT_SYMBOL);
611
                                // Symbols
612
                                definition.addDynFieldMap(FIELD_SYMBOLS).setClassOfItems(ISymbol.class);
613
                        }
614
                        return Boolean.TRUE;
615
                }
616
                
617
        }
618
        
619

    
620
        
621
        
622
        private Map<Object, ISymbol> createSymbolMap() {
623
                return new TreeMap<Object, ISymbol>
624
                (new Comparator<Object>() { 
625
                                        public int compare(Object o1, Object o2) {
626
                                                if ((o1 != null) && (o2 != null)) {
627
                                                    
628
                                                    boolean o1_inte = (o1 instanceof FInterval);
629
                            boolean o2_inte = (o2 instanceof FInterval);
630
                            
631
                            if (!o1_inte && !o2_inte) {
632
                                return 0;
633
                            } else {
634
                                if (o1_inte && !o2_inte) {
635
                                    return 1;
636
                                } else {
637
                                    if (!o1_inte && o2_inte) {
638
                                        return -1;
639
                                    }
640
                                }
641
                            }
642

    
643
                                                        FInterval i2 = (FInterval) o2;
644
                                                        FInterval i1 = (FInterval) o1;
645

    
646
                                                        if (i1.getMin() > i2.getMin()) {
647
                                                                return 1;
648
                                                        }
649

    
650
                                                        if (i1.getMin() < i2.getMin()) {
651
                                                                return -1;
652
                                                        }
653
                                                        if (i1.getMax() < i2.getMax()) {
654
                                                                return -1;
655
                                                        }
656
                                                        if (i1.getMax() > i2.getMax()) {
657
                                                                return 1;
658
                                                        }
659
                                                }
660

    
661
                                                return 0;
662
                                        }
663
                                });
664
        }
665
}