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

History | View | Annotate | Download (13 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 java.util.logging.Level;
32
import java.util.logging.Logger;
33
import org.apache.commons.lang3.StringUtils;
34

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

    
44
public class FeatureQueryOrder implements Persistent, Cloneable {
45

    
46
    public class FeatureQueryOrderMember implements Persistent, org.gvsig.tools.lang.Cloneable {
47

    
48
        String attributeName = null;
49
        Evaluator evaluator = null;
50
        boolean ascending;
51

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

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

    
62
        @Override
63
        public String toString() {
64
          if( this.evaluator!=null ) {
65
            return this.evaluator.getSQL() + " " + (this.ascending? "ASC":"DESC");
66
          }
67
          return (this.ascending? "+":"-")+this.attributeName;
68
        }
69

    
70
        public boolean hasEvaluator() {
71
            return this.evaluator != null;
72
        }
73

    
74
        public Evaluator getEvaluator() {
75
            return this.evaluator;
76
        }
77

    
78
        public boolean getAscending() {
79
            return this.ascending;
80
        }
81

    
82
        public String getAttributeName() {
83
            return this.attributeName;
84
        }
85

    
86
        @Override
87
        public void loadFromState(PersistentState state)
88
                throws PersistenceException {
89
            this.attributeName = state.getString("attributeName");
90
            this.ascending = state.getBoolean("ascending");
91
            this.evaluator = (Evaluator) state.get("evaluator");
92
        }
93

    
94
        @Override
95
        public void saveToState(PersistentState state)
96
                throws PersistenceException {
97
            state.set("attributeName", this.attributeName);
98
            state.set("ascending", this.ascending);
99
            if (this.evaluator != null) {
100
                state.set("evaluator", evaluator);
101
            }
102

    
103
        }
104

    
105
        @Override
106
        public FeatureQueryOrderMember clone() throws CloneNotSupportedException {
107
            // Nothing more to clone
108
            return (FeatureQueryOrderMember) super.clone();
109
        }
110

    
111
        public void setAscending(boolean ascending) {
112
            this.ascending = ascending;
113
        }
114

    
115
    }
116

    
117
    private List<FeatureQueryOrderMember> members = new ArrayList();
118

    
119
    public FeatureQueryOrder() {
120
    }
121
        
122
    public void copyFrom(FeatureQueryOrder other) {
123
      List<FeatureQueryOrderMember>theMembers = new ArrayList<>();
124
      for (FeatureQueryOrderMember member : other.members) {
125
        FeatureQueryOrderMember m;
126
        try {
127
          m = member.clone();
128
        } catch (CloneNotSupportedException ex) {
129
          throw new RuntimeException("Can't copy member ("+member.toString()+").",ex);
130
        }
131
        theMembers.add(m);
132
      }
133
      this.members = theMembers;
134
    }
135
    
136
    @Override
137
    public String toString() {
138
        StringBuilder builder = new StringBuilder();
139
        boolean needComma = false;
140
        for (FeatureQueryOrderMember member : members) {
141
            if( member!=null && !StringUtils.isBlank(member.getAttributeName()) ) {
142
                if( needComma ) {
143
                    builder.append(",");
144
                }
145
                builder.append(member.toString());
146
                needComma = true;
147
            }
148
        }
149
        String s = builder.toString();
150
        if( StringUtils.isBlank(s) ) {
151
            return null;
152
        }
153
        return s;
154
    }
155
    
156
    public Object add(String order) {
157
        if( StringUtils.isEmpty(order) ) {
158
            return null;
159
        }
160
        Object r = null;
161
        String[] attributes = StringUtils.split(order, ',');
162
        for (String attribute : attributes) {
163
            boolean ascending = true;
164
            if( attribute.startsWith("+") ) {
165
                ascending = true;
166
                attribute = attribute.substring(1);
167
            } else if( attribute.startsWith("-") ) {
168
                ascending = false;
169
                attribute = attribute.substring(1);
170
            }
171
            attribute = attribute.trim();
172
            r = this.add(attribute,ascending);
173
        }
174
        return r;
175
    }
176
    
177
    public Object add(String attributeName, boolean ascending) {
178
        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
179
                attributeName, ascending);
180
        if (members.add(member)) {
181
            return member;
182
        }
183
        return null;
184
    }
185

    
186
    public Object add(Evaluator evaluator, boolean ascending) {
187
        FeatureQueryOrderMember member = new FeatureQueryOrderMember(
188
                evaluator,
189
                ascending);
190
        if (members.add(member)) {
191
            return member;
192
        }
193
        return null;
194
    }
195

    
196
    public Iterable<FeatureQueryOrderMember> members() {
197
        //    Me hubiese gustado que FeatureQueryOrder fuese Iterable, pero no se deja por 
198
        //    que FeatureQueryOrderMember es una clase interna y no esta definida en el 
199
        //    momento de poner el :
200
        //            implements Iterable<FeatureQueryOrderMember>
201
        //    Y si saco a una clase independiente FeatureQueryOrderMember se pierde 
202
        //    compatibilidad binaria con quien la esta usando.
203
        //    Para rodearlo, he creado el metodo members.
204
        return new Iterable<FeatureQueryOrderMember> () {
205

    
206
            @Override
207
            public Iterator<FeatureQueryOrderMember> iterator() {
208
                return FeatureQueryOrder.this.iterator();
209
            }
210
        };
211
    }
212
    
213
    public Iterator<FeatureQueryOrderMember> iterator() {
214
        if (members == null) {
215
            return new Iterator<FeatureQueryOrderMember>() {
216
                @Override
217
                public boolean hasNext() {
218
                    return false;
219
                }
220

    
221
                @Override
222
                public FeatureQueryOrderMember next() {
223
                    throw new NoSuchElementException();
224
                }
225

    
226
                @Override
227
                public void remove() {
228
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
229
                }
230
            };
231
        }
232
        return members.iterator();
233
    }
234

    
235
    public boolean remove(FeatureQueryOrderMember member) {
236
        return members.remove(member);
237
    }
238

    
239
    public void remove(int index) {
240
        members.remove(index);
241
    }
242

    
243
    public void clear() {
244
        members.clear();
245
    }
246

    
247
    public int size() {
248
        return this.members.size();
249
    }
250
    
251
    public int getIndex(String attributeName) {
252
        int n = 0;
253
        for (FeatureQueryOrderMember member : members) {
254
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
255
                return n;
256
            }
257
            n++;
258
        }
259
        return -1;
260
    }
261
    
262
    public void movePrevious(String name) {
263
        int n = this.getIndex(name);
264
        if( n<1 ) {
265
            return;
266
        }
267
        Collections.swap(members, n, n-1);
268
    }
269

    
270
    public void moveNext(String name) {
271
        int n = this.getIndex(name);
272
        if( n>=this.members.size()-1 ) {
273
            return;
274
        }
275
        Collections.swap(members, n, n+1);
276
    }
277

    
278
    public boolean isEmpty() {
279
        return this.members==null || this.members.isEmpty();
280
    }
281
    
282
    public FeatureQueryOrderMember get(String attributeName) {
283
        for (FeatureQueryOrderMember member : members) {
284
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
285
                return member;
286
            }
287
        }
288
        return null;
289
    }
290
    
291
    public boolean contains(String attributeName) {
292
        for (FeatureQueryOrderMember member : members) {
293
            if( member!=null && StringUtils.equalsIgnoreCase(attributeName, member.getAttributeName()) ) {
294
                return true;
295
            }
296
        }
297
        return false;
298
    }
299
    
300
    public Comparator<Feature> getFeatureComparator() {
301
        return new DefaultFeatureComparator(this);
302
    }
303

    
304
    @Override
305
    public FeatureQueryOrder clone() throws CloneNotSupportedException {
306
        FeatureQueryOrder clone = (FeatureQueryOrder) super.clone();
307

    
308
        if (members != null) {
309
            clone.members = new ArrayList(members.size());
310
            for (int i = 0; i < members.size(); i++) {
311
                clone.members.add((members.get(i)).clone());
312
            }
313
        }
314

    
315
        return clone;
316
    }
317

    
318
    public FeatureQueryOrder getCopy() {
319
        FeatureQueryOrder aCopy = new FeatureQueryOrder();
320
        Iterator iter = this.members.iterator();
321
        FeatureQueryOrderMember member;
322
        while (iter.hasNext()) {
323
            member = (FeatureQueryOrderMember) iter.next();
324
            if (member.hasEvaluator()) {
325
                aCopy.add(member.getEvaluator(), member.getAscending());
326
            } else {
327
                aCopy.add(member.getAttributeName(), member.getAscending());
328
            }
329
        }
330
        return aCopy;
331
    }
332

    
333
    @Override
334
    public void loadFromState(PersistentState state)
335
            throws PersistenceException {
336
        this.members = (List) state.get("menbers");
337
    }
338

    
339
    @Override
340
    public void saveToState(PersistentState state) throws PersistenceException {
341
        state.set("menbers", members);
342
    }
343

    
344
    private class DefaultFeatureComparator implements Comparator<Feature> {
345

    
346
        private final FeatureQueryOrder order;
347

    
348
        public DefaultFeatureComparator(FeatureQueryOrder order) {
349
            this.order = order;
350
            // TODO optimizar en un array???
351

    
352
        }
353

    
354
        private int myCompare(Object arg0, Object arg1) {
355
            if (arg0 == null) {
356
                if (arg1 == null) {
357
                    return 0;
358
                } else {
359
                    return 1;
360
                }
361
            } else if (arg1 == null) {
362
                if (arg0 == null) {
363
                    return 0;
364
                } else {
365
                    return 1;
366
                }
367
            }
368
            if (arg0 instanceof Comparable) {
369
                return ((Comparable) arg0).compareTo(arg1);
370
            } else if (arg1 instanceof Comparable) {
371
                return ((Comparable) arg1).compareTo(arg0) * -1;
372
            }
373

    
374
            if (arg0.equals(arg1)) {
375
                return 0;
376
            } else {
377
                return -1;
378
            }
379

    
380
        }
381

    
382
        @Override
383
        public int compare(Feature f0, Feature f1) {
384
            Iterator iter = this.order.iterator();
385
            int returnValue = 0;
386
//            Feature f0 = (Feature) arg0;
387
//            Feature f1 = (Feature) arg1;
388
            Object item;
389
            String attrName;
390
            Evaluator evaluator;
391
            while (returnValue == 0 && iter.hasNext()) {
392
                item = iter.next();
393
                if (item instanceof String) {
394
                    attrName = (String) item;
395
                    returnValue = this
396
                            .myCompare(f0.get(attrName), f1
397
                                    .get(attrName));
398
                } else {
399
                    evaluator = (Evaluator) item;
400
                    try {
401
                        returnValue = this.myCompare(evaluator
402
                                .evaluate((EvaluatorData) f0), evaluator
403
                                .evaluate((EvaluatorData) f1));
404
                    } catch (EvaluatorException e) {
405
                        throw new DataEvaluatorRuntimeException(e);
406
                    }
407
                }
408
            }
409

    
410
            return returnValue;
411
        }
412

    
413
    }
414

    
415
}