Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.api / src / main / java / org / gvsig / fmap / dal / feature / FeatureQueryOrder.java @ 44829

History | View | Annotate | Download (15.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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.feature;
24

    
25
import java.util.ArrayList;
26
import java.util.Collections;
27
import java.util.Comparator;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.NoSuchElementException;
31
import org.apache.commons.lang3.StringUtils;
32
import org.gvsig.expressionevaluator.Expression;
33

    
34
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
35
import org.gvsig.tools.ToolsLocator;
36
import org.gvsig.tools.dynobject.DynStruct;
37
import org.gvsig.tools.evaluator.Evaluator;
38
import org.gvsig.tools.evaluator.EvaluatorData;
39
import org.gvsig.tools.evaluator.EvaluatorException;
40
import org.gvsig.tools.lang.Cloneable;
41
import org.gvsig.tools.persistence.Persistent;
42
import org.gvsig.tools.persistence.PersistentState;
43
import org.gvsig.tools.persistence.exception.PersistenceException;
44
import org.slf4j.LoggerFactory;
45

    
46
public class FeatureQueryOrder implements Persistent, Cloneable {
47

    
48
    public static class FeatureQueryOrderMember implements Persistent, org.gvsig.tools.lang.Cloneable {
49

    
50
        String attributeName = null;
51
        Evaluator evaluator = null;
52
        Expression expression = null;
53
        boolean ascending;
54

    
55
        private final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(FeatureQueryOrderMember.class);
56

    
57
        public FeatureQueryOrderMember() {
58

    
59
        }
60
        
61
        FeatureQueryOrderMember(String attributeName, boolean ascending) {
62
            this.attributeName = attributeName;
63
            this.ascending = ascending;
64
        }
65

    
66
        FeatureQueryOrderMember(Evaluator evaluator, boolean ascending) {
67
            this.evaluator = evaluator;
68
            LOGGER.warn("Creating evaluator that will not be able to persist");
69
            this.ascending = ascending;
70
        }
71

    
72
        @Override
73
        public String toString() {
74
            if (this.evaluator != null) {
75
                return this.evaluator.getSQL() + " " + (this.ascending ? "ASC" : "DESC");
76
            }
77
            return (this.ascending ? "+" : "-") + this.attributeName;
78
        }
79

    
80
        public boolean hasEvaluator() {
81
            return this.evaluator != null;
82
        }
83

    
84
        public Evaluator getEvaluator() {
85
            return this.evaluator;
86
        }
87

    
88
        public boolean getAscending() {
89
            return this.ascending;
90
        }
91

    
92
        public String getAttributeName() {
93
            return this.attributeName;
94
        }
95

    
96
        @Override
97
        public void loadFromState(PersistentState state)
98
                throws PersistenceException {
99
            this.attributeName = state.getString("attributeName");
100
            this.ascending = state.getBoolean("ascending");
101
            // Note: evaluator dont persist
102
//            this.evaluator = (Evaluator) state.get("evaluator");
103
//            this.expression = (Expression) state.get("expression");
104
        }
105

    
106
        @Override
107
        public void saveToState(PersistentState state)
108
                throws PersistenceException {
109
            state.set("attributeName", this.attributeName);
110
            state.set("ascending", this.ascending);
111
//            if (this.evaluator != null) {
112
//                state.set("evaluator", evaluator);
113
//            }
114
//            state.set("expression", this.expression);
115

    
116
        }
117

    
118
        @Override
119
        public FeatureQueryOrderMember clone() throws CloneNotSupportedException {
120
            // Nothing more to clone
121
            return (FeatureQueryOrderMember) super.clone();
122
        }
123

    
124
        public void setAscending(boolean ascending) {
125
            this.ascending = ascending;
126
        }
127

    
128
    }
129

    
130
    private List<FeatureQueryOrderMember> members = new ArrayList();
131
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(FeatureQueryOrder.class);
132

    
133
    public FeatureQueryOrder() {
134
    }
135

    
136
    public void copyFrom(FeatureQueryOrder other) {
137
        List<FeatureQueryOrderMember> theMembers = new ArrayList<>();
138
        for (FeatureQueryOrderMember member : other.members) {
139
            FeatureQueryOrderMember m;
140
            try {
141
                m = member.clone();
142
            } catch (CloneNotSupportedException ex) {
143
                throw new RuntimeException("Can't copy member (" + member.toString() + ").", ex);
144
            }
145
            theMembers.add(m);
146
        }
147
        this.members = theMembers;
148
    }
149

    
150
    @Override
151
    public String toString() {
152
        StringBuilder builder = new StringBuilder();
153
        boolean needComma = false;
154
        for (FeatureQueryOrderMember member : members) {
155
            if (member != null && !StringUtils.isBlank(member.getAttributeName())) {
156
                if (needComma) {
157
                    builder.append(",");
158
                }
159
                builder.append(member.toString());
160
                needComma = true;
161
            }
162
        }
163
        String s = builder.toString();
164
        if (StringUtils.isBlank(s)) {
165
            return null;
166
        }
167
        return s;
168
    }
169

    
170
    public Object add(String order) {
171
        if (StringUtils.isEmpty(order)) {
172
            return null;
173
        }
174
        Object r = null;
175
        String[] attributes = StringUtils.split(order, ',');
176
        for (String attribute : attributes) {
177
            boolean ascending = true;
178
            if (attribute.startsWith("+")) {
179
                ascending = true;
180
                attribute = attribute.substring(1);
181
            } else if (attribute.startsWith("-")) {
182
                ascending = false;
183
                attribute = attribute.substring(1);
184
            }
185
            attribute = attribute.trim();
186
            r = this.add(attribute, ascending);
187
        }
188
        return r;
189
    }
190

    
191
    public Object add(String attributeName, boolean ascending) {
192
        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
193
                attributeName, ascending);
194
        if (members.add(member)) {
195
            return member;
196
        }
197
        return null;
198
    }
199

    
200
//    TODO: Nota: hay que a?adir add de un Expression
201
//    public Object add(Evaluator evaluator, boolean ascending) {
202
//        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
203
//                evaluator,
204
//                ascending);
205
//        if (members.add(member)) {
206
//            return member;
207
//        }
208
//        return null;
209
//    }
210
    public Iterable<FeatureQueryOrderMember> members() {
211
        //    Me hubiese gustado que FeatureQueryOrder fuese Iterable, pero no se deja por 
212
        //    que FeatureQueryOrderMember es una clase interna y no esta definida en el 
213
        //    momento de poner el :
214
        //            implements Iterable<FeatureQueryOrderMember>
215
        //    Y si saco a una clase independiente FeatureQueryOrderMember se pierde 
216
        //    compatibilidad binaria con quien la esta usando.
217
        //    Para rodearlo, he creado el metodo members.
218
        return new Iterable<FeatureQueryOrderMember>() {
219

    
220
            @Override
221
            public Iterator<FeatureQueryOrderMember> iterator() {
222
                return FeatureQueryOrder.this.iterator();
223
            }
224
        };
225
    }
226

    
227
    public Iterator<FeatureQueryOrderMember> iterator() {
228
        if (members == null) {
229
            return new Iterator<FeatureQueryOrderMember>() {
230
                @Override
231
                public boolean hasNext() {
232
                    return false;
233
                }
234

    
235
                @Override
236
                public FeatureQueryOrderMember next() {
237
                    throw new NoSuchElementException();
238
                }
239

    
240
                @Override
241
                public void remove() {
242
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
243
                }
244
            };
245
        }
246
        return members.iterator();
247
    }
248

    
249
    public boolean remove(FeatureQueryOrderMember member) {
250
        return members.remove(member);
251
    }
252

    
253
    public void remove(int index) {
254
        members.remove(index);
255
    }
256

    
257
    public void clear() {
258
        members.clear();
259
    }
260

    
261
    public int size() {
262
        return this.members.size();
263
    }
264

    
265
    public int getIndex(String attributeName) {
266
        int n = 0;
267
        for (FeatureQueryOrderMember member : members) {
268
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
269
                return n;
270
            }
271
            n++;
272
        }
273
        return -1;
274
    }
275

    
276
    public void movePrevious(String name) {
277
        int n = this.getIndex(name);
278
        if (n < 1) {
279
            return;
280
        }
281
        Collections.swap(members, n, n - 1);
282
    }
283

    
284
    public void moveNext(String name) {
285
        int n = this.getIndex(name);
286
        if (n >= this.members.size() - 1) {
287
            return;
288
        }
289
        Collections.swap(members, n, n + 1);
290
    }
291

    
292
    public boolean isEmpty() {
293
        return this.members == null || this.members.isEmpty();
294
    }
295

    
296
    public FeatureQueryOrderMember get(String attributeName) {
297
        for (FeatureQueryOrderMember member : members) {
298
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
299
                return member;
300
            }
301
        }
302
        return null;
303
    }
304

    
305
    public boolean contains(String attributeName) {
306
        for (FeatureQueryOrderMember member : members) {
307
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
308
                return true;
309
            }
310
        }
311
        return false;
312
    }
313

    
314
    public Comparator<Feature> getFeatureComparator() {
315
        return new DefaultFeatureComparator(this);
316
    }
317

    
318
    @Override
319
    public FeatureQueryOrder clone() throws CloneNotSupportedException {
320
        FeatureQueryOrder clone = (FeatureQueryOrder) super.clone();
321

    
322
        if (members != null) {
323
            clone.members = new ArrayList(members.size());
324
            for (int i = 0; i < members.size(); i++) {
325
                clone.members.add((members.get(i)).clone());
326
            }
327
        }
328

    
329
        return clone;
330
    }
331

    
332
    public FeatureQueryOrder getCopy() {
333
        FeatureQueryOrder aCopy = new FeatureQueryOrder();
334
        Iterator iter = this.members.iterator();
335
        FeatureQueryOrderMember member;
336
        while (iter.hasNext()) {
337
            member = (FeatureQueryOrderMember) iter.next();
338
            if (member.hasEvaluator()) {
339
//                aCopy.add(member.getEvaluator(), member.getAscending());
340
                LOGGER.warn("Evaluator is not being added to the filter in a class copy");
341
            } else {
342
                aCopy.add(member.getAttributeName(), member.getAscending());
343
            }
344
        }
345
        return aCopy;
346
    }
347

    
348
    /**
349
     * Register the class on PersistenceManager
350
     *
351
     */
352
    public static void registerPersistent() {
353
        DynStruct definitionMember
354
                = ToolsLocator.getPersistenceManager()
355
                        .addDefinition(FeatureQueryOrderMember.class,
356
                                "FeatureQueryOrderMember",
357
                                "FeatureQueryOrderMember Persistent definition",
358
                                null,
359
                                null);
360

    
361
        definitionMember.addDynFieldString("attributeName").setClassOfValue(String.class).setMandatory(false);
362
        definitionMember.addDynFieldObject("expression").setClassOfValue(Expression.class).setMandatory(false);
363
        definitionMember.addDynFieldBoolean("ascending").setMandatory(false);
364

    
365
        DynStruct definition
366
                = ToolsLocator.getPersistenceManager()
367
                        .addDefinition(FeatureQueryOrder.class,
368
                                "FeatureQueryOrder",
369
                                "FeatureQueryOrder Persistent definition",
370
                                null,
371
                                null);
372

    
373
        definition.addDynFieldList("members").setClassOfItems(FeatureQueryOrderMember.class);
374

    
375
    }
376

    
377
    @Override
378
    public void loadFromState(PersistentState state)
379
            throws PersistenceException {
380
        List<FeatureQueryOrderMember> stateMembers = (List) state.get("members");
381
        this.members = new ArrayList<>();
382
        for (FeatureQueryOrderMember stateMember : stateMembers) {
383
            this.members.add(stateMember);
384
        }
385
    }
386

    
387
    @Override
388
    public void saveToState(PersistentState state) throws PersistenceException {
389
        state.set("members", members);
390

    
391
    }
392

    
393
    private class DefaultFeatureComparator implements Comparator<Feature> {
394

    
395
        private final FeatureQueryOrder order;
396

    
397
        public DefaultFeatureComparator(FeatureQueryOrder order) {
398
            this.order = order;
399
            // TODO optimizar en un array???
400

    
401
        }
402

    
403
        private int myCompare(Object arg0, Object arg1) {
404
            if (arg0 == null) {
405
                if (arg1 == null) {
406
                    return 0;
407
                } else {
408
                    return 1;
409
                }
410
            } else if (arg1 == null) {
411
                if (arg0 == null) {
412
                    return 0;
413
                } else {
414
                    return 1;
415
                }
416
            }
417
            if (arg0 instanceof Comparable) {
418
                return ((Comparable) arg0).compareTo(arg1);
419
            } else if (arg1 instanceof Comparable) {
420
                return ((Comparable) arg1).compareTo(arg0) * -1;
421
            }
422

    
423
            if (arg0.equals(arg1)) {
424
                return 0;
425
            } else {
426
                return -1;
427
            }
428

    
429
        }
430

    
431
        @Override
432
        public int compare(Feature f0, Feature f1) {
433
            Iterator iter = this.order.iterator();
434
            int returnValue = 0;
435
//            Feature f0 = (Feature) arg0;
436
//            Feature f1 = (Feature) arg1;
437
            Object item;
438
            String attrName;
439
            Evaluator evaluator;
440
            while (returnValue == 0 && iter.hasNext()) {
441
                item = iter.next();
442
                if (item instanceof String) {
443
                    attrName = (String) item;
444
                    returnValue = this
445
                            .myCompare(f0.get(attrName), f1
446
                                    .get(attrName));
447
                } else {
448
                    evaluator = (Evaluator) item;
449
                    try {
450
                        returnValue = this.myCompare(evaluator
451
                                .evaluate((EvaluatorData) f0), evaluator
452
                                .evaluate((EvaluatorData) f1));
453
                    } catch (EvaluatorException e) {
454
                        throw new DataEvaluatorRuntimeException(e);
455
                    }
456
                }
457
            }
458

    
459
            return returnValue;
460
        }
461

    
462
    }
463

    
464
}