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 @ 45308

History | View | Annotate | Download (15.4 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.impl;
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
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
36
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultExpressionEvaluator;
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dynobject.DynStruct;
39
import org.gvsig.tools.evaluator.Evaluator;
40
import org.gvsig.tools.evaluator.EvaluatorData;
41
import org.gvsig.tools.evaluator.EvaluatorException;
42
import org.gvsig.tools.persistence.Persistent;
43
import org.gvsig.tools.persistence.PersistentState;
44
import org.gvsig.tools.persistence.exception.PersistenceException;
45
import org.slf4j.LoggerFactory;
46

    
47
public class DefaultFeatureQueryOrder implements FeatureQueryOrder {
48

    
49
    public static class FeatureQueryOrderMemberImpl implements FeatureQueryOrderMember {
50

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

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

    
58
        public FeatureQueryOrderMemberImpl() {
59

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

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

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

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

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

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

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

    
97
        @Override
98
        public void loadFromState(PersistentState state)
99
                throws PersistenceException {
100
            this.attributeName = state.getString("attributeName");
101
            this.ascending = state.getBoolean("ascending");
102
            this.evaluator = (Evaluator) state.get("evaluator");
103
        }
104

    
105
        @Override
106
        public void saveToState(PersistentState state)
107
                throws PersistenceException {
108
            state.set("attributeName", this.attributeName);
109
            state.set("ascending", this.ascending);
110
            if(evaluator instanceof Persistent){
111
                state.set("evaluator", evaluator);
112
            } else {
113
                state.setNull("evaluator");
114
            }
115
        }
116

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

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

    
127
    }
128

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

    
132
    public DefaultFeatureQueryOrder() {
133
    }
134

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

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

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

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

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

    
222
            @Override
223
            public Iterator<FeatureQueryOrderMember> iterator() {
224
                return DefaultFeatureQueryOrder.this.iterator();
225
            }
226
        };
227
    }
228

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

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

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

    
251
    public boolean remove(FeatureQueryOrderMember member) {
252
        return members.remove(member);
253
    }
254

    
255
    public void remove(int index) {
256
        members.remove(index);
257
    }
258

    
259
    public void clear() {
260
        members.clear();
261
    }
262

    
263
    public int size() {
264
        return this.members.size();
265
    }
266

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

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

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

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

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

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

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

    
320
    @Override
321
    public DefaultFeatureQueryOrder clone() throws CloneNotSupportedException {
322
        DefaultFeatureQueryOrder clone = (DefaultFeatureQueryOrder) super.clone();
323

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

    
331
        return clone;
332
    }
333

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

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

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

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

    
375
        definition.addDynFieldList("members").setClassOfItems(FeatureQueryOrderMember.class);
376

    
377
    }
378

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

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

    
393
    }
394

    
395
    private class DefaultFeatureComparator implements Comparator<Feature> {
396

    
397
        private final DefaultFeatureQueryOrder order;
398

    
399
        public DefaultFeatureComparator(DefaultFeatureQueryOrder order) {
400
            this.order = order;
401
            // TODO optimizar en un array???
402

    
403
        }
404

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

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

    
431
        }
432

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

    
461
            return returnValue;
462
        }
463

    
464
    }
465

    
466
}