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

History | View | Annotate | Download (17.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.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 javax.json.JsonArray;
32
import javax.json.JsonObject;
33
import javax.json.JsonValue;
34
import org.apache.commons.lang3.StringUtils;
35
import org.apache.commons.lang3.builder.ToStringBuilder;
36
import org.gvsig.expressionevaluator.Expression;
37
import org.gvsig.expressionevaluator.ExpressionEvaluator;
38
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
39
import org.gvsig.fmap.dal.feature.Feature;
40
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
41
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
42
import org.gvsig.json.Json;
43
import org.gvsig.json.JsonObjectBuilder;
44
import org.gvsig.tools.ToolsLocator;
45
import org.gvsig.tools.dynobject.DynStruct;
46
import org.gvsig.tools.evaluator.Evaluator;
47
import org.gvsig.tools.evaluator.EvaluatorData;
48
import org.gvsig.tools.evaluator.EvaluatorException;
49
import org.gvsig.tools.persistence.PersistentState;
50
import org.gvsig.tools.persistence.exception.PersistenceException;
51
import org.slf4j.LoggerFactory;
52

    
53
public class DefaultFeatureQueryOrder implements FeatureQueryOrder {
54

    
55
    public static class FeatureQueryOrderMemberImpl implements FeatureQueryOrderMember {
56

    
57
        String attributeName = null;
58
        Evaluator evaluator = null;
59
//        Expression expression = null;
60
        boolean ascending;
61

    
62
        private final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(FeatureQueryOrderMember.class);
63

    
64
        public FeatureQueryOrderMemberImpl() {
65

    
66
        }
67
        
68
        FeatureQueryOrderMemberImpl(String attributeName, boolean ascending) {
69
            this.attributeName = attributeName;
70
            this.ascending = ascending;
71
        }
72

    
73
        FeatureQueryOrderMemberImpl(Evaluator evaluator, boolean ascending) {
74
            this.evaluator = evaluator;
75
            LOGGER.warn("Creating evaluator that will not be able to persist");
76
            this.ascending = ascending;
77
        }
78

    
79
        FeatureQueryOrderMemberImpl(ExpressionEvaluator evaluator, boolean ascending) {
80
            this.evaluator = evaluator;
81
            this.ascending = ascending;
82
        }
83

    
84
        @Override
85
        public String toString() {
86
            try {
87
                ToStringBuilder builder = new ToStringBuilder(this);
88
                if( evaluator==null ) {
89
                    builder.append("attributeName", this.attributeName);
90
                } else {
91
                    builder.append("evaluator", this.evaluator.getSQL());
92
                }
93
                builder.append("ascending", this.ascending ? "ASC" : "DESC");
94
                return builder.toString();
95
            } catch (Exception e) {
96
                return super.toString();
97
            }
98
        }        
99
        
100

    
101
        public boolean hasEvaluator() {
102
            return this.evaluator != null;
103
        }
104

    
105
        public Evaluator getEvaluator() {
106
            return this.evaluator;
107
        }
108

    
109
        public boolean getAscending() {
110
            return this.ascending;
111
        }
112

    
113
        public String getAttributeName() {
114
            return this.attributeName;
115
        }
116

    
117
        @Override
118
        public void loadFromState(PersistentState state)
119
                throws PersistenceException {
120
            this.attributeName = state.getString("attributeName");
121
            this.ascending = state.getBoolean("ascending");
122
            this.evaluator = (Evaluator) state.get("evaluator");
123
        }
124

    
125
        @Override
126
        public void saveToState(PersistentState state)
127
                throws PersistenceException {
128
            state.set("attributeName", this.attributeName);
129
            state.set("ascending", this.ascending);
130
            if(evaluator instanceof ExpressionEvaluator){
131
                state.set("evaluator", evaluator);
132
            } else {
133
                state.setNull("evaluator");
134
            }
135
        }
136

    
137
        @Override
138
        public FeatureQueryOrderMember clone() throws CloneNotSupportedException {
139
            // Nothing more to clone
140
            return (FeatureQueryOrderMember) super.clone();
141
        }
142

    
143
        public void setAscending(boolean ascending) {
144
            this.ascending = ascending;
145
        }
146

    
147
        @Override
148
        public void fromJson(JsonObject json) {
149
            this.attributeName = json.getString("attributeName", null);
150
            this.ascending = json.getBoolean("ascending", true);
151
            this.evaluator = (Evaluator) Json.toObject(json, "evaluator");
152
        }
153

    
154
        @Override
155
        public JsonObjectBuilder toJsonBuilder() {
156
            JsonObjectBuilder state = Json.createObjectBuilder();
157
            state.add("attributeName", this.attributeName);
158
            state.add("ascending", this.ascending);
159
            if(evaluator instanceof ExpressionEvaluator){
160
                state.add("evaluator", evaluator);
161
            } else {
162
                state.addNull("evaluator");
163
            }
164
            return state;
165
        }
166

    
167
    }
168

    
169
    private List<FeatureQueryOrderMember> members = new ArrayList();
170
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureQueryOrder.class);
171

    
172
    public DefaultFeatureQueryOrder() {
173
    }
174

    
175
    public void copyFrom(FeatureQueryOrder other) {
176
        List<FeatureQueryOrderMember> theMembers = new ArrayList<>();
177
        for (FeatureQueryOrderMember member : other) {
178
            FeatureQueryOrderMember m;
179
            try {
180
                m = member.clone();
181
            } catch (CloneNotSupportedException ex) {
182
                throw new RuntimeException("Can't copy member (" + member.toString() + ").", ex);
183
            }
184
            theMembers.add(m);
185
        }
186
        this.members = theMembers;
187
    }
188

    
189
    public Object add(String order) {
190
        if (StringUtils.isEmpty(order)) {
191
            return null;
192
        }
193
        Object r = null;
194
        String[] attributes = StringUtils.split(order, ',');
195
        for (String attribute : attributes) {
196
            boolean ascending = true;
197
            if (attribute.startsWith("+")) {
198
                ascending = true;
199
                attribute = attribute.substring(1);
200
            } else if (attribute.startsWith("-")) {
201
                ascending = false;
202
                attribute = attribute.substring(1);
203
            }
204
            attribute = attribute.trim();
205
            r = this.add(attribute, ascending);
206
        }
207
        return r;
208
    }
209

    
210
    public Object add(String attributeName, boolean ascending) {
211
        FeatureQueryOrderMember member = new FeatureQueryOrderMemberImpl(
212
                attributeName, ascending);
213
        if (members.add(member)) {
214
            return member;
215
        }
216
        return null;
217
    }
218

    
219
    public Object add(Expression expr, boolean ascending) {
220
        
221
        Evaluator evaluator = new DefaultFeatureExpressionEvaluator(expr);
222
        FeatureQueryOrderMember member = new FeatureQueryOrderMemberImpl(
223
                evaluator,
224
                ascending);
225
        if (members.add(member)) {
226
            return member;
227
        }
228
        return null;
229
        
230
    }
231
    
232
    public Iterable<FeatureQueryOrderMember> members() {
233
        //    Me hubiese gustado que FeatureQueryOrder fuese Iterable, pero no se deja por 
234
        //    que FeatureQueryOrderMember es una clase interna y no esta definida en el 
235
        //    momento de poner el :
236
        //            implements Iterable<FeatureQueryOrderMember>
237
        //    Y si saco a una clase independiente FeatureQueryOrderMember se pierde 
238
        //    compatibilidad binaria con quien la esta usando.
239
        //    Para rodearlo, he creado el metodo members.
240
        return new Iterable<FeatureQueryOrderMember>() {
241

    
242
            @Override
243
            public Iterator<FeatureQueryOrderMember> iterator() {
244
                return DefaultFeatureQueryOrder.this.iterator();
245
            }
246
        };
247
    }
248

    
249
    public Iterator<FeatureQueryOrderMember> iterator() {
250
        if (members == null) {
251
            return new Iterator<FeatureQueryOrderMember>() {
252
                @Override
253
                public boolean hasNext() {
254
                    return false;
255
                }
256

    
257
                @Override
258
                public FeatureQueryOrderMember next() {
259
                    throw new NoSuchElementException();
260
                }
261

    
262
                @Override
263
                public void remove() {
264
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
265
                }
266
            };
267
        }
268
        return members.iterator();
269
    }
270

    
271
    public boolean remove(FeatureQueryOrderMember member) {
272
        return members.remove(member);
273
    }
274

    
275
    public void remove(int index) {
276
        members.remove(index);
277
    }
278

    
279
    public void clear() {
280
        members.clear();
281
    }
282

    
283
    public int size() {
284
        return this.members.size();
285
    }
286

    
287
    public int getIndex(String attributeName) {
288
        int n = 0;
289
        for (FeatureQueryOrderMember member : members) {
290
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
291
                return n;
292
            }
293
            n++;
294
        }
295
        return -1;
296
    }
297

    
298
    public void movePrevious(String name) {
299
        int n = this.getIndex(name);
300
        if (n < 1) {
301
            return;
302
        }
303
        Collections.swap(members, n, n - 1);
304
    }
305

    
306
    public void moveNext(String name) {
307
        int n = this.getIndex(name);
308
        if (n >= this.members.size() - 1) {
309
            return;
310
        }
311
        Collections.swap(members, n, n + 1);
312
    }
313

    
314
    public boolean isEmpty() {
315
        return this.members == null || this.members.isEmpty();
316
    }
317

    
318
    public FeatureQueryOrderMember get(String attributeName) {
319
        for (FeatureQueryOrderMember member : members) {
320
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
321
                return member;
322
            }
323
        }
324
        return null;
325
    }
326

    
327
    public boolean contains(String attributeName) {
328
        for (FeatureQueryOrderMember member : members) {
329
            if (member != null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName())) {
330
                return true;
331
            }
332
        }
333
        return false;
334
    }
335

    
336
    public Comparator<Feature> getFeatureComparator() {
337
        return new DefaultFeatureComparator(this);
338
    }
339

    
340
    @Override
341
    public DefaultFeatureQueryOrder clone() throws CloneNotSupportedException {
342
        DefaultFeatureQueryOrder clone = (DefaultFeatureQueryOrder) super.clone();
343

    
344
        if (members != null) {
345
            clone.members = new ArrayList(members.size());
346
            for (int i = 0; i < members.size(); i++) {
347
                clone.members.add((members.get(i)).clone());
348
            }
349
        }
350

    
351
        return clone;
352
    }
353

    
354
    public DefaultFeatureQueryOrder getCopy() {
355
        DefaultFeatureQueryOrder aCopy = new DefaultFeatureQueryOrder();
356
        Iterator iter = this.members.iterator();
357
        FeatureQueryOrderMember member;
358
        while (iter.hasNext()) {
359
            member = (FeatureQueryOrderMember) iter.next();
360
            if (member.hasEvaluator()) {
361
//                aCopy.add(member.getEvaluator(), member.getAscending());
362
                LOGGER.warn("Evaluator is not being added to the filter in a class copy");
363
            } else {
364
                aCopy.add(member.getAttributeName(), member.getAscending());
365
            }
366
        }
367
        return aCopy;
368
    }
369

    
370
    public static void selfRegister() {        
371
        registerPersistent();
372
        Json.registerSerializer(DefaultFeatureQueryOrder.class);                    
373
        Json.registerSerializer(FeatureQueryOrderMemberImpl.class);                    
374
    }
375
    
376
    /**
377
     * Register the class on PersistenceManager
378
     *
379
     */
380
    private static void registerPersistent() {
381
        DynStruct definitionMember
382
                = ToolsLocator.getPersistenceManager()
383
                        .addDefinition(FeatureQueryOrderMemberImpl.class,
384
                                "FeatureQueryOrderMember",
385
                                "FeatureQueryOrderMember Persistent definition",
386
                                null,
387
                                null);
388

    
389
        definitionMember.addDynFieldString("attributeName").setClassOfValue(String.class).setMandatory(false);
390
        definitionMember.addDynFieldObject("evaluator").setClassOfValue(ExpressionEvaluator.class).setMandatory(false);
391
        definitionMember.addDynFieldBoolean("ascending").setMandatory(false);
392

    
393
        DynStruct definition
394
                = ToolsLocator.getPersistenceManager()
395
                        .addDefinition(DefaultFeatureQueryOrder.class,
396
                                "FeatureQueryOrder",
397
                                "FeatureQueryOrder Persistent definition",
398
                                null,
399
                                null);
400

    
401
        definition.addDynFieldList("members").setClassOfItems(FeatureQueryOrderMemberImpl.class);
402

    
403
    }
404

    
405
    @Override
406
    public void loadFromState(PersistentState state)
407
            throws PersistenceException {
408
        List<FeatureQueryOrderMember> stateMembers = (List) state.get("members");
409
        this.members = new ArrayList<>();
410
        for (FeatureQueryOrderMember stateMember : stateMembers) {
411
            this.members.add(stateMember);
412
        }
413
    }
414

    
415
    @Override
416
    public void saveToState(PersistentState state) throws PersistenceException {
417
        state.set("members", members);
418

    
419
    }
420

    
421
    private class DefaultFeatureComparator implements Comparator<Feature> {
422

    
423
        private final DefaultFeatureQueryOrder order;
424

    
425
        public DefaultFeatureComparator(DefaultFeatureQueryOrder order) {
426
            this.order = order;
427
            // TODO optimizar en un array???
428

    
429
        }
430

    
431
        private int myCompare(Object arg0, Object arg1) {
432
            if (arg0 == null) {
433
                if (arg1 == null) {
434
                    return 0;
435
                } else {
436
                    return 1;
437
                }
438
            } else if (arg1 == null) {
439
                if (arg0 == null) {
440
                    return 0;
441
                } else {
442
                    return 1;
443
                }
444
            }
445
            if (arg0 instanceof Comparable) {
446
                return ((Comparable) arg0).compareTo(arg1);
447
            } else if (arg1 instanceof Comparable) {
448
                return ((Comparable) arg1).compareTo(arg0) * -1;
449
            }
450

    
451
            if (arg0.equals(arg1)) {
452
                return 0;
453
            } else {
454
                return -1;
455
            }
456

    
457
        }
458

    
459
        @Override
460
        public int compare(Feature f0, Feature f1) {
461
            Iterator iter = this.order.iterator();
462
            int returnValue = 0;
463
//            Feature f0 = (Feature) arg0;
464
//            Feature f1 = (Feature) arg1;
465
            Object item;
466
            String attrName;
467
            Evaluator evaluator;
468
            while (returnValue == 0 && iter.hasNext()) {
469
                item = iter.next();
470
                if (item instanceof String) {
471
                    attrName = (String) item;
472
                    returnValue = this
473
                            .myCompare(f0.get(attrName), f1
474
                                    .get(attrName));
475
                } else {
476
                    evaluator = (Evaluator) item;
477
                    try {
478
                        returnValue = this.myCompare(evaluator
479
                                .evaluate((EvaluatorData) f0), evaluator
480
                                .evaluate((EvaluatorData) f1));
481
                    } catch (EvaluatorException e) {
482
                        throw new DataEvaluatorRuntimeException(e);
483
                    }
484
                }
485
            }
486

    
487
            return returnValue;
488
        }
489

    
490
    }
491

    
492
    @Override
493
    public void fromJson(JsonObject json) {
494
        JsonArray stateMembers = json.getJsonArray("members");
495
        this.members = new ArrayList<>();
496
        for (JsonValue stateMember : stateMembers) {
497
            this.members.add((FeatureQueryOrderMember) Json.toObject(stateMember));
498
        }
499
    }
500

    
501
    @Override
502
    public JsonObjectBuilder toJsonBuilder() {
503
        JsonObjectBuilder state = Json.createObjectBuilder();
504
        state.add("members", members);
505
        return state;
506
    }
507
    
508
    @Override
509
    public String toString() {
510
        try {
511
            ToStringBuilder builder = new ToStringBuilder(this);
512
            builder.append("members", this.members, true);
513
            return builder.toString();
514
        } catch (Exception e) {
515
            return super.toString();
516
        }
517
    }
518
}