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

History | View | Annotate | Download (12.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;
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

    
33
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
34
import org.gvsig.tools.evaluator.Evaluator;
35
import org.gvsig.tools.evaluator.EvaluatorData;
36
import org.gvsig.tools.evaluator.EvaluatorException;
37
import org.gvsig.tools.lang.Cloneable;
38
import org.gvsig.tools.persistence.Persistent;
39
import org.gvsig.tools.persistence.PersistentState;
40
import org.gvsig.tools.persistence.exception.PersistenceException;
41

    
42
public class FeatureQueryOrder implements Persistent, Cloneable {
43

    
44
    public class FeatureQueryOrderMember implements Persistent, org.gvsig.tools.lang.Cloneable {
45

    
46
        String attributeName = null;
47
        Evaluator evaluator = null;
48
        boolean ascending;
49

    
50
        FeatureQueryOrderMember(String attributeName, boolean ascending) {
51
            this.attributeName = attributeName;
52
            this.ascending = ascending;
53
        }
54

    
55
        FeatureQueryOrderMember(Evaluator evaluator, boolean ascending) {
56
            this.evaluator = evaluator;
57
            this.ascending = ascending;
58
        }
59

    
60
        public boolean hasEvaluator() {
61
            return this.evaluator != null;
62
        }
63

    
64
        public Evaluator getEvaluator() {
65
            return this.evaluator;
66
        }
67

    
68
        public boolean getAscending() {
69
            return this.ascending;
70
        }
71

    
72
        public String getAttributeName() {
73
            return this.attributeName;
74
        }
75

    
76
        @Override
77
        public void loadFromState(PersistentState state)
78
                throws PersistenceException {
79
            this.attributeName = state.getString("attributeName");
80
            this.ascending = state.getBoolean("ascending");
81
            this.evaluator = (Evaluator) state.get("evaluator");
82
        }
83

    
84
        @Override
85
        public void saveToState(PersistentState state)
86
                throws PersistenceException {
87
            state.set("attributeName", this.attributeName);
88
            state.set("ascending", this.ascending);
89
            if (this.evaluator != null) {
90
                state.set("evaluator", evaluator);
91
            }
92

    
93
        }
94

    
95
        @Override
96
        public FeatureQueryOrderMember clone() throws CloneNotSupportedException {
97
            // Nothing more to clone
98
            return (FeatureQueryOrderMember) super.clone();
99
        }
100

    
101
        public void setAscending(boolean ascending) {
102
            this.ascending = ascending;
103
        }
104

    
105
    }
106

    
107
    private List<FeatureQueryOrderMember> members = new ArrayList();
108

    
109
    public FeatureQueryOrder() {
110
    }
111
        
112
    @Override
113
    public String toString() {
114
        StringBuilder builder = new StringBuilder();
115
        boolean needComma = false;
116
        for (FeatureQueryOrderMember member : members) {
117
            if( member!=null && !StringUtils.isBlank(member.getAttributeName()) ) {
118
                if( needComma ) {
119
                    builder.append(",");
120
                }
121
                if( member.ascending ) {
122
                    builder.append("+");
123
                } else {
124
                    builder.append("-");
125
                }
126
                builder.append(member.getAttributeName());
127
                needComma = true;
128
            }
129
        }
130
        String s = builder.toString();
131
        if( StringUtils.isBlank(s) ) {
132
            return null;
133
        }
134
        return s;
135
    }
136
    
137
    public Object add(String order) {
138
        if( StringUtils.isEmpty(order) ) {
139
            return null;
140
        }
141
        Object r = null;
142
        String[] attributes = StringUtils.split(order, ',');
143
        for (String attribute : attributes) {
144
            boolean ascending = true;
145
            if( attribute.startsWith("+") ) {
146
                ascending = true;
147
                attribute = attribute.substring(1);
148
            } else if( attribute.startsWith("-") ) {
149
                ascending = false;
150
                attribute = attribute.substring(1);
151
            }
152
            attribute = attribute.trim();
153
            r = this.add(attribute,ascending);
154
        }
155
        return r;
156
    }
157
    
158
    public Object add(String attributeName, boolean ascending) {
159
        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
160
                attributeName, ascending);
161
        if (members.add(member)) {
162
            return member;
163
        }
164
        return null;
165
    }
166

    
167
    public Object add(Evaluator evaluator, boolean ascending) {
168
        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
169
                evaluator,
170
                ascending);
171
        if (members.add(member)) {
172
            return member;
173
        }
174
        return null;
175
    }
176

    
177
    public Iterable<FeatureQueryOrderMember> members() {
178
        //    Me hubiese gustado que FeatureQueryOrder fuese Iterable, pero no se deja por 
179
        //    que FeatureQueryOrderMember es una clase interna y no esta definida en el 
180
        //    momento de poner el :
181
        //            implements Iterable<FeatureQueryOrderMember>
182
        //    Y si saco a una clase independiente FeatureQueryOrderMember se pierde 
183
        //    compatibilidad binaria con quien la esta usando.
184
        //    Para rodearlo, he creado el metodo members.
185
        return new Iterable<FeatureQueryOrderMember> () {
186

    
187
            @Override
188
            public Iterator<FeatureQueryOrderMember> iterator() {
189
                return FeatureQueryOrder.this.iterator();
190
            }
191
        };
192
    }
193
    
194
    public Iterator<FeatureQueryOrderMember> iterator() {
195
        if (members == null) {
196
            return new Iterator<FeatureQueryOrderMember>() {
197
                @Override
198
                public boolean hasNext() {
199
                    return false;
200
                }
201

    
202
                @Override
203
                public FeatureQueryOrderMember next() {
204
                    throw new NoSuchElementException();
205
                }
206

    
207
                @Override
208
                public void remove() {
209
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
210
                }
211
            };
212
        }
213
        return members.iterator();
214
    }
215

    
216
    public boolean remove(FeatureQueryOrderMember member) {
217
        return members.remove(member);
218
    }
219

    
220
    public void remove(int index) {
221
        members.remove(index);
222
    }
223

    
224
    public void clear() {
225
        members.clear();
226
    }
227

    
228
    public int size() {
229
        return this.members.size();
230
    }
231
    
232
    public int getIndex(String attributeName) {
233
        int n = 0;
234
        for (FeatureQueryOrderMember member : members) {
235
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
236
                return n;
237
            }
238
            n++;
239
        }
240
        return -1;
241
    }
242
    
243
    public void movePrevious(String name) {
244
        int n = this.getIndex(name);
245
        if( n<1 ) {
246
            return;
247
        }
248
        Collections.swap(members, n, n-1);
249
    }
250

    
251
    public void moveNext(String name) {
252
        int n = this.getIndex(name);
253
        if( n>=this.members.size()-1 ) {
254
            return;
255
        }
256
        Collections.swap(members, n, n+1);
257
    }
258

    
259
    public boolean isEmpty() {
260
        return this.members==null || this.members.isEmpty();
261
    }
262
    
263
    public FeatureQueryOrderMember get(String attributeName) {
264
        for (FeatureQueryOrderMember member : members) {
265
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
266
                return member;
267
            }
268
        }
269
        return null;
270
    }
271
    
272
    public boolean contains(String attributeName) {
273
        for (FeatureQueryOrderMember member : members) {
274
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
275
                return true;
276
            }
277
        }
278
        return false;
279
    }
280
    
281
    public Comparator<Feature> getFeatureComparator() {
282
        return new DefaultFeatureComparator(this);
283
    }
284

    
285
    @Override
286
    public FeatureQueryOrder clone() throws CloneNotSupportedException {
287
        FeatureQueryOrder clone = (FeatureQueryOrder) super.clone();
288

    
289
        if (members != null) {
290
            clone.members = new ArrayList(members.size());
291
            for (int i = 0; i < members.size(); i++) {
292
                clone.members.add((members.get(i)).clone());
293
            }
294
        }
295

    
296
        return clone;
297
    }
298

    
299
    public FeatureQueryOrder getCopy() {
300
        FeatureQueryOrder aCopy = new FeatureQueryOrder();
301
        Iterator iter = this.members.iterator();
302
        FeatureQueryOrderMember member;
303
        while (iter.hasNext()) {
304
            member = (FeatureQueryOrderMember) iter.next();
305
            if (member.hasEvaluator()) {
306
                aCopy.add(member.getEvaluator(), member.getAscending());
307
            } else {
308
                aCopy.add(member.getAttributeName(), member.getAscending());
309
            }
310
        }
311
        return aCopy;
312
    }
313

    
314
    @Override
315
    public void loadFromState(PersistentState state)
316
            throws PersistenceException {
317
        this.members = (List) state.get("menbers");
318
    }
319

    
320
    @Override
321
    public void saveToState(PersistentState state) throws PersistenceException {
322
        state.set("menbers", members);
323
    }
324

    
325
    private class DefaultFeatureComparator implements Comparator<Feature> {
326

    
327
        private final FeatureQueryOrder order;
328

    
329
        public DefaultFeatureComparator(FeatureQueryOrder order) {
330
            this.order = order;
331
            // TODO optimizar en un array???
332

    
333
        }
334

    
335
        private int myCompare(Object arg0, Object arg1) {
336
            if (arg0 == null) {
337
                if (arg1 == null) {
338
                    return 0;
339
                } else {
340
                    return 1;
341
                }
342
            } else if (arg1 == null) {
343
                if (arg0 == null) {
344
                    return 0;
345
                } else {
346
                    return 1;
347
                }
348
            }
349
            if (arg0 instanceof Comparable) {
350
                return ((Comparable) arg0).compareTo(arg1);
351
            } else if (arg1 instanceof Comparable) {
352
                return ((Comparable) arg1).compareTo(arg0) * -1;
353
            }
354

    
355
            if (arg0.equals(arg1)) {
356
                return 0;
357
            } else {
358
                return -1;
359
            }
360

    
361
        }
362

    
363
        @Override
364
        public int compare(Feature f0, Feature f1) {
365
            Iterator iter = this.order.iterator();
366
            int returnValue = 0;
367
//            Feature f0 = (Feature) arg0;
368
//            Feature f1 = (Feature) arg1;
369
            Object item;
370
            String attrName;
371
            Evaluator evaluator;
372
            while (returnValue == 0 && iter.hasNext()) {
373
                item = iter.next();
374
                if (item instanceof String) {
375
                    attrName = (String) item;
376
                    returnValue = this
377
                            .myCompare(f0.get(attrName), f1
378
                                    .get(attrName));
379
                } else {
380
                    evaluator = (Evaluator) item;
381
                    try {
382
                        returnValue = this.myCompare(evaluator
383
                                .evaluate((EvaluatorData) f0), evaluator
384
                                .evaluate((EvaluatorData) f1));
385
                    } catch (EvaluatorException e) {
386
                        throw new DataEvaluatorRuntimeException(e);
387
                    }
388
                }
389
            }
390

    
391
            return returnValue;
392
        }
393

    
394
    }
395

    
396
}