Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureQueryOrder.java @ 45968

History | View | Annotate | Download (15.5 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 43020 jjdelcerro
 * 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 40559 jjdelcerro
 *
11 43020 jjdelcerro
 * 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 40559 jjdelcerro
 *
16 43020 jjdelcerro
 * 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 40559 jjdelcerro
 *
20 43020 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40559 jjdelcerro
 */
23 45308 fdiaz
package org.gvsig.fmap.dal.feature.impl;
24 40435 jjdelcerro
25
import java.util.ArrayList;
26 44644 jjdelcerro
import java.util.Collections;
27 40435 jjdelcerro
import java.util.Comparator;
28
import java.util.Iterator;
29
import java.util.List;
30 43020 jjdelcerro
import java.util.NoSuchElementException;
31 43987 jjdelcerro
import org.apache.commons.lang3.StringUtils;
32 44829 omartinez
import org.gvsig.expressionevaluator.Expression;
33 45366 omartinez
import org.gvsig.expressionevaluator.ExpressionEvaluator;
34 40435 jjdelcerro
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
35 45308 fdiaz
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
37 45366 omartinez
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
38 44829 omartinez
import org.gvsig.tools.ToolsLocator;
39
import org.gvsig.tools.dynobject.DynStruct;
40 40435 jjdelcerro
import org.gvsig.tools.evaluator.Evaluator;
41
import org.gvsig.tools.evaluator.EvaluatorData;
42
import org.gvsig.tools.evaluator.EvaluatorException;
43
import org.gvsig.tools.persistence.Persistent;
44
import org.gvsig.tools.persistence.PersistentState;
45
import org.gvsig.tools.persistence.exception.PersistenceException;
46 44829 omartinez
import org.slf4j.LoggerFactory;
47 40435 jjdelcerro
48 45308 fdiaz
public class DefaultFeatureQueryOrder implements FeatureQueryOrder {
49 40435 jjdelcerro
50 45308 fdiaz
    public static class FeatureQueryOrderMemberImpl implements FeatureQueryOrderMember {
51 43026 jjdelcerro
52
        String attributeName = null;
53
        Evaluator evaluator = null;
54 45308 fdiaz
//        Expression expression = null;
55 43026 jjdelcerro
        boolean ascending;
56
57 44829 omartinez
        private final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(FeatureQueryOrderMember.class);
58
59 45308 fdiaz
        public FeatureQueryOrderMemberImpl() {
60 44829 omartinez
61
        }
62
63 45308 fdiaz
        FeatureQueryOrderMemberImpl(String attributeName, boolean ascending) {
64 43026 jjdelcerro
            this.attributeName = attributeName;
65
            this.ascending = ascending;
66
        }
67
68 45308 fdiaz
        FeatureQueryOrderMemberImpl(Evaluator evaluator, boolean ascending) {
69 43026 jjdelcerro
            this.evaluator = evaluator;
70 44829 omartinez
            LOGGER.warn("Creating evaluator that will not be able to persist");
71 43026 jjdelcerro
            this.ascending = ascending;
72
        }
73
74 44712 jjdelcerro
        @Override
75
        public String toString() {
76 44829 omartinez
            if (this.evaluator != null) {
77
                return this.evaluator.getSQL() + " " + (this.ascending ? "ASC" : "DESC");
78
            }
79
            return (this.ascending ? "+" : "-") + this.attributeName;
80 44712 jjdelcerro
        }
81
82 43026 jjdelcerro
        public boolean hasEvaluator() {
83
            return this.evaluator != null;
84
        }
85
86
        public Evaluator getEvaluator() {
87
            return this.evaluator;
88
        }
89
90
        public boolean getAscending() {
91
            return this.ascending;
92
        }
93
94
        public String getAttributeName() {
95
            return this.attributeName;
96
        }
97
98
        @Override
99
        public void loadFromState(PersistentState state)
100
                throws PersistenceException {
101
            this.attributeName = state.getString("attributeName");
102
            this.ascending = state.getBoolean("ascending");
103 45308 fdiaz
            this.evaluator = (Evaluator) state.get("evaluator");
104 43026 jjdelcerro
        }
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 45366 omartinez
            if(evaluator instanceof ExpressionEvaluator){
112 45308 fdiaz
                state.set("evaluator", evaluator);
113
            } else {
114
                state.setNull("evaluator");
115
            }
116 43026 jjdelcerro
        }
117
118
        @Override
119
        public FeatureQueryOrderMember clone() throws CloneNotSupportedException {
120
            // Nothing more to clone
121
            return (FeatureQueryOrderMember) super.clone();
122
        }
123
124 44644 jjdelcerro
        public void setAscending(boolean ascending) {
125
            this.ascending = ascending;
126
        }
127
128 43026 jjdelcerro
    }
129
130 44644 jjdelcerro
    private List<FeatureQueryOrderMember> members = new ArrayList();
131 45308 fdiaz
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureQueryOrder.class);
132 40435 jjdelcerro
133 45308 fdiaz
    public DefaultFeatureQueryOrder() {
134 43026 jjdelcerro
    }
135 44829 omartinez
136 44712 jjdelcerro
    public void copyFrom(FeatureQueryOrder other) {
137 44829 omartinez
        List<FeatureQueryOrderMember> theMembers = new ArrayList<>();
138 45308 fdiaz
        for (FeatureQueryOrderMember member : other) {
139 44829 omartinez
            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 44712 jjdelcerro
        }
147 44829 omartinez
        this.members = theMembers;
148 44712 jjdelcerro
    }
149 44829 omartinez
150 44644 jjdelcerro
    @Override
151
    public String toString() {
152
        StringBuilder builder = new StringBuilder();
153
        boolean needComma = false;
154
        for (FeatureQueryOrderMember member : members) {
155 44829 omartinez
            if (member != null && !StringUtils.isBlank(member.getAttributeName())) {
156
                if (needComma) {
157 44644 jjdelcerro
                    builder.append(",");
158
                }
159 44712 jjdelcerro
                builder.append(member.toString());
160 44644 jjdelcerro
                needComma = true;
161
            }
162
        }
163
        String s = builder.toString();
164 44829 omartinez
        if (StringUtils.isBlank(s)) {
165 44644 jjdelcerro
            return null;
166
        }
167
        return s;
168
    }
169 44829 omartinez
170 43987 jjdelcerro
    public Object add(String order) {
171 44829 omartinez
        if (StringUtils.isEmpty(order)) {
172 43987 jjdelcerro
            return null;
173
        }
174
        Object r = null;
175
        String[] attributes = StringUtils.split(order, ',');
176
        for (String attribute : attributes) {
177
            boolean ascending = true;
178 44829 omartinez
            if (attribute.startsWith("+")) {
179 43987 jjdelcerro
                ascending = true;
180
                attribute = attribute.substring(1);
181 44829 omartinez
            } else if (attribute.startsWith("-")) {
182 43987 jjdelcerro
                ascending = false;
183
                attribute = attribute.substring(1);
184
            }
185
            attribute = attribute.trim();
186 44829 omartinez
            r = this.add(attribute, ascending);
187 43987 jjdelcerro
        }
188
        return r;
189
    }
190 44829 omartinez
191 43020 jjdelcerro
    public Object add(String attributeName, boolean ascending) {
192 45308 fdiaz
        FeatureQueryOrderMember member = new FeatureQueryOrderMemberImpl(
193 40435 jjdelcerro
                attributeName, ascending);
194 43020 jjdelcerro
        if (members.add(member)) {
195
            return member;
196
        }
197
        return null;
198
    }
199 40435 jjdelcerro
200 45308 fdiaz
    public Object add(Expression expr, boolean ascending) {
201
202 45366 omartinez
        Evaluator evaluator = new DefaultFeatureExpressionEvaluator(expr);
203 45308 fdiaz
        FeatureQueryOrderMember member = new FeatureQueryOrderMemberImpl(
204
                evaluator,
205
                ascending);
206
        if (members.add(member)) {
207
            return member;
208
        }
209
        return null;
210
211
    }
212
213 43026 jjdelcerro
    public Iterable<FeatureQueryOrderMember> members() {
214
        //    Me hubiese gustado que FeatureQueryOrder fuese Iterable, pero no se deja por
215
        //    que FeatureQueryOrderMember es una clase interna y no esta definida en el
216
        //    momento de poner el :
217
        //            implements Iterable<FeatureQueryOrderMember>
218
        //    Y si saco a una clase independiente FeatureQueryOrderMember se pierde
219
        //    compatibilidad binaria con quien la esta usando.
220
        //    Para rodearlo, he creado el metodo members.
221 44829 omartinez
        return new Iterable<FeatureQueryOrderMember>() {
222 43026 jjdelcerro
223
            @Override
224
            public Iterator<FeatureQueryOrderMember> iterator() {
225 45308 fdiaz
                return DefaultFeatureQueryOrder.this.iterator();
226 43026 jjdelcerro
            }
227
        };
228
    }
229 44829 omartinez
230 43020 jjdelcerro
    public Iterator<FeatureQueryOrderMember> iterator() {
231 43026 jjdelcerro
        if (members == null) {
232 43020 jjdelcerro
            return new Iterator<FeatureQueryOrderMember>() {
233
                @Override
234
                public boolean hasNext() {
235
                    return false;
236
                }
237 40435 jjdelcerro
238 43020 jjdelcerro
                @Override
239
                public FeatureQueryOrderMember next() {
240
                    throw new NoSuchElementException();
241
                }
242 40435 jjdelcerro
243 43020 jjdelcerro
                @Override
244
                public void remove() {
245
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
246
                }
247
            };
248
        }
249
        return members.iterator();
250
    }
251 40435 jjdelcerro
252 43020 jjdelcerro
    public boolean remove(FeatureQueryOrderMember member) {
253
        return members.remove(member);
254
    }
255 40435 jjdelcerro
256 43020 jjdelcerro
    public void remove(int index) {
257
        members.remove(index);
258
    }
259 40435 jjdelcerro
260 43020 jjdelcerro
    public void clear() {
261
        members.clear();
262
    }
263 40435 jjdelcerro
264 43020 jjdelcerro
    public int size() {
265
        return this.members.size();
266
    }
267 44829 omartinez
268 44644 jjdelcerro
    public int getIndex(String attributeName) {
269
        int n = 0;
270
        for (FeatureQueryOrderMember member : members) {
271 44829 omartinez
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
272 44644 jjdelcerro
                return n;
273
            }
274
            n++;
275
        }
276
        return -1;
277
    }
278 44829 omartinez
279 44644 jjdelcerro
    public void movePrevious(String name) {
280
        int n = this.getIndex(name);
281 44829 omartinez
        if (n < 1) {
282 44644 jjdelcerro
            return;
283
        }
284 44829 omartinez
        Collections.swap(members, n, n - 1);
285 44644 jjdelcerro
    }
286 40435 jjdelcerro
287 44644 jjdelcerro
    public void moveNext(String name) {
288
        int n = this.getIndex(name);
289 44829 omartinez
        if (n >= this.members.size() - 1) {
290 44644 jjdelcerro
            return;
291
        }
292 44829 omartinez
        Collections.swap(members, n, n + 1);
293 44644 jjdelcerro
    }
294
295
    public boolean isEmpty() {
296 44829 omartinez
        return this.members == null || this.members.isEmpty();
297 44644 jjdelcerro
    }
298 44829 omartinez
299 44644 jjdelcerro
    public FeatureQueryOrderMember get(String attributeName) {
300
        for (FeatureQueryOrderMember member : members) {
301 44829 omartinez
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
302 44644 jjdelcerro
                return member;
303
            }
304
        }
305
        return null;
306
    }
307 44829 omartinez
308 44644 jjdelcerro
    public boolean contains(String attributeName) {
309
        for (FeatureQueryOrderMember member : members) {
310 44829 omartinez
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
311 44644 jjdelcerro
                return true;
312
            }
313
        }
314
        return false;
315
    }
316 44829 omartinez
317 44644 jjdelcerro
    public Comparator<Feature> getFeatureComparator() {
318 43020 jjdelcerro
        return new DefaultFeatureComparator(this);
319
    }
320 40435 jjdelcerro
321 44644 jjdelcerro
    @Override
322 45308 fdiaz
    public DefaultFeatureQueryOrder clone() throws CloneNotSupportedException {
323
        DefaultFeatureQueryOrder clone = (DefaultFeatureQueryOrder) super.clone();
324 40435 jjdelcerro
325 43020 jjdelcerro
        if (members != null) {
326
            clone.members = new ArrayList(members.size());
327
            for (int i = 0; i < members.size(); i++) {
328 44644 jjdelcerro
                clone.members.add((members.get(i)).clone());
329 43020 jjdelcerro
            }
330
        }
331 40435 jjdelcerro
332 43020 jjdelcerro
        return clone;
333
    }
334 40435 jjdelcerro
335 45308 fdiaz
    public DefaultFeatureQueryOrder getCopy() {
336
        DefaultFeatureQueryOrder aCopy = new DefaultFeatureQueryOrder();
337 43020 jjdelcerro
        Iterator iter = this.members.iterator();
338
        FeatureQueryOrderMember member;
339
        while (iter.hasNext()) {
340
            member = (FeatureQueryOrderMember) iter.next();
341
            if (member.hasEvaluator()) {
342 44829 omartinez
//                aCopy.add(member.getEvaluator(), member.getAscending());
343
                LOGGER.warn("Evaluator is not being added to the filter in a class copy");
344 43020 jjdelcerro
            } else {
345
                aCopy.add(member.getAttributeName(), member.getAscending());
346
            }
347
        }
348
        return aCopy;
349
    }
350 40435 jjdelcerro
351 44829 omartinez
    /**
352
     * Register the class on PersistenceManager
353
     *
354
     */
355
    public static void registerPersistent() {
356
        DynStruct definitionMember
357
                = ToolsLocator.getPersistenceManager()
358 45366 omartinez
                        .addDefinition(FeatureQueryOrderMemberImpl.class,
359 44829 omartinez
                                "FeatureQueryOrderMember",
360
                                "FeatureQueryOrderMember Persistent definition",
361
                                null,
362
                                null);
363
364
        definitionMember.addDynFieldString("attributeName").setClassOfValue(String.class).setMandatory(false);
365 45366 omartinez
        definitionMember.addDynFieldObject("evaluator").setClassOfValue(ExpressionEvaluator.class).setMandatory(false);
366 44829 omartinez
        definitionMember.addDynFieldBoolean("ascending").setMandatory(false);
367
368
        DynStruct definition
369
                = ToolsLocator.getPersistenceManager()
370 45308 fdiaz
                        .addDefinition(DefaultFeatureQueryOrder.class,
371 44829 omartinez
                                "FeatureQueryOrder",
372
                                "FeatureQueryOrder Persistent definition",
373
                                null,
374
                                null);
375
376 45366 omartinez
        definition.addDynFieldList("members").setClassOfItems(FeatureQueryOrderMemberImpl.class);
377 44829 omartinez
378
    }
379
380 44644 jjdelcerro
    @Override
381 43020 jjdelcerro
    public void loadFromState(PersistentState state)
382
            throws PersistenceException {
383 44829 omartinez
        List<FeatureQueryOrderMember> stateMembers = (List) state.get("members");
384
        this.members = new ArrayList<>();
385
        for (FeatureQueryOrderMember stateMember : stateMembers) {
386
            this.members.add(stateMember);
387
        }
388 43020 jjdelcerro
    }
389 40435 jjdelcerro
390 44644 jjdelcerro
    @Override
391 43020 jjdelcerro
    public void saveToState(PersistentState state) throws PersistenceException {
392 44829 omartinez
        state.set("members", members);
393
394 43020 jjdelcerro
    }
395 40435 jjdelcerro
396 44644 jjdelcerro
    private class DefaultFeatureComparator implements Comparator<Feature> {
397 40435 jjdelcerro
398 45308 fdiaz
        private final DefaultFeatureQueryOrder order;
399 40435 jjdelcerro
400 45308 fdiaz
        public DefaultFeatureComparator(DefaultFeatureQueryOrder order) {
401 43020 jjdelcerro
            this.order = order;
402
            // TODO optimizar en un array???
403 40435 jjdelcerro
404 43020 jjdelcerro
        }
405 40435 jjdelcerro
406 43020 jjdelcerro
        private int myCompare(Object arg0, Object arg1) {
407
            if (arg0 == null) {
408
                if (arg1 == null) {
409
                    return 0;
410
                } else {
411
                    return 1;
412
                }
413
            } else if (arg1 == null) {
414
                if (arg0 == null) {
415
                    return 0;
416
                } else {
417
                    return 1;
418
                }
419
            }
420
            if (arg0 instanceof Comparable) {
421
                return ((Comparable) arg0).compareTo(arg1);
422
            } else if (arg1 instanceof Comparable) {
423
                return ((Comparable) arg1).compareTo(arg0) * -1;
424
            }
425 40435 jjdelcerro
426 43020 jjdelcerro
            if (arg0.equals(arg1)) {
427
                return 0;
428
            } else {
429
                return -1;
430
            }
431 40435 jjdelcerro
432 43020 jjdelcerro
        }
433 40435 jjdelcerro
434 44644 jjdelcerro
        @Override
435
        public int compare(Feature f0, Feature f1) {
436 43020 jjdelcerro
            Iterator iter = this.order.iterator();
437
            int returnValue = 0;
438 44644 jjdelcerro
//            Feature f0 = (Feature) arg0;
439
//            Feature f1 = (Feature) arg1;
440 43020 jjdelcerro
            Object item;
441
            String attrName;
442
            Evaluator evaluator;
443
            while (returnValue == 0 && iter.hasNext()) {
444
                item = iter.next();
445
                if (item instanceof String) {
446
                    attrName = (String) item;
447
                    returnValue = this
448
                            .myCompare(f0.get(attrName), f1
449
                                    .get(attrName));
450
                } else {
451
                    evaluator = (Evaluator) item;
452
                    try {
453
                        returnValue = this.myCompare(evaluator
454
                                .evaluate((EvaluatorData) f0), evaluator
455
                                .evaluate((EvaluatorData) f1));
456
                    } catch (EvaluatorException e) {
457
                        throw new DataEvaluatorRuntimeException(e);
458
                    }
459
                }
460
            }
461 40435 jjdelcerro
462 43020 jjdelcerro
            return returnValue;
463
        }
464 40435 jjdelcerro
465 43020 jjdelcerro
    }
466
467
}