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

History | View | Annotate | Download (15.5 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.expressionevaluator.ExpressionEvaluator;
34
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
37
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
38
import org.gvsig.tools.ToolsLocator;
39
import org.gvsig.tools.dynobject.DynStruct;
40
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
import org.slf4j.LoggerFactory;
47

    
48
public class DefaultFeatureQueryOrder implements FeatureQueryOrder {
49

    
50
    public static class FeatureQueryOrderMemberImpl implements FeatureQueryOrderMember {
51

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

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

    
59
        public FeatureQueryOrderMemberImpl() {
60

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

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

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

    
82
        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
            this.evaluator = (Evaluator) state.get("evaluator");
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(evaluator instanceof ExpressionEvaluator){
112
                state.set("evaluator", evaluator);
113
            } else {
114
                state.setNull("evaluator");
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(DefaultFeatureQueryOrder.class);
132

    
133
    public DefaultFeatureQueryOrder() {
134
    }
135

    
136
    public void copyFrom(FeatureQueryOrder other) {
137
        List<FeatureQueryOrderMember> theMembers = new ArrayList<>();
138
        for (FeatureQueryOrderMember member : other) {
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 FeatureQueryOrderMemberImpl(
193
                attributeName, ascending);
194
        if (members.add(member)) {
195
            return member;
196
        }
197
        return null;
198
    }
199

    
200
    public Object add(Expression expr, boolean ascending) {
201
        
202
        Evaluator evaluator = new DefaultFeatureExpressionEvaluator(expr);
203
        FeatureQueryOrderMember member = new FeatureQueryOrderMemberImpl(
204
                evaluator,
205
                ascending);
206
        if (members.add(member)) {
207
            return member;
208
        }
209
        return null;
210
        
211
    }
212
    
213
    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
        return new Iterable<FeatureQueryOrderMember>() {
222

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
332
        return clone;
333
    }
334

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

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

    
364
        definitionMember.addDynFieldString("attributeName").setClassOfValue(String.class).setMandatory(false);
365
        definitionMember.addDynFieldObject("evaluator").setClassOfValue(ExpressionEvaluator.class).setMandatory(false);
366
        definitionMember.addDynFieldBoolean("ascending").setMandatory(false);
367

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

    
376
        definition.addDynFieldList("members").setClassOfItems(FeatureQueryOrderMemberImpl.class);
377

    
378
    }
379

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

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

    
394
    }
395

    
396
    private class DefaultFeatureComparator implements Comparator<Feature> {
397

    
398
        private final DefaultFeatureQueryOrder order;
399

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

    
404
        }
405

    
406
        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

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

    
432
        }
433

    
434
        @Override
435
        public int compare(Feature f0, Feature f1) {
436
            Iterator iter = this.order.iterator();
437
            int returnValue = 0;
438
//            Feature f0 = (Feature) arg0;
439
//            Feature f1 = (Feature) arg1;
440
            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

    
462
            return returnValue;
463
        }
464

    
465
    }
466

    
467
}