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 / DefaultFeatureQuery.java @ 44727

History | View | Annotate | Download (21.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
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.feature.impl;
25

    
26
import java.util.ArrayList;
27
import java.util.HashMap;
28
import java.util.List;
29
import java.util.Map;
30
import org.apache.commons.lang3.ArrayUtils;
31
import org.apache.commons.lang3.StringUtils;
32
import org.gvsig.expressionevaluator.Expression;
33
import org.gvsig.expressionevaluator.ExpressionUtils;
34
import org.gvsig.fmap.dal.DataTypes;
35
import org.gvsig.fmap.dal.exception.DataException;
36
import org.gvsig.fmap.dal.expressionevaluator.ExpressionEvaluator;
37
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureQuery;
39
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultExpressionEvaluator;
43
import org.gvsig.tools.ToolsLocator;
44
import org.gvsig.tools.dynobject.DynStruct;
45
import org.gvsig.tools.evaluator.AndEvaluator;
46
import org.gvsig.tools.evaluator.Evaluator;
47
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
48
import org.gvsig.tools.persistence.PersistentState;
49
import org.gvsig.tools.persistence.exception.PersistenceException;
50

    
51
/**
52
 * Defines the properties of a collection of Features, as a result of a query
53
 * through a FeatureStore.
54
 * <p>
55
 * A FeatureQuery is always defined by a FeatureType, or by the list of
56
 * attribute names of the FeatureStore to return.
57
 * </p>
58
 * <p>
59
 * The filter allows to select Features whose properties have values with the
60
 * characteristics defined by the filter.
61
 * </p>
62
 * <p>
63
 * The order is used to set the order of the result FeatureCollection, based on
64
 * the values of the properties of the Features.
65
 * </p>
66
 * <p>
67
 * The scale parameter can be used by the FeatureStore as a hint about the
68
 * quality or resolution of the data needed to view or operate with the data
69
 * returned. As an example, the FeatureStore may use the scale to return only a
70
 * representative subset of the data, or maybe to return Features with less
71
 * detail, like a point or a line instead of a polygon.
72
 * </p>
73
 * <p>
74
 * If an implementation of FeatureStore is able to get other parameters to
75
 * customize the behavior of the getDataCollection methods, there is an option
76
 * to set more parameters through the setAttribute method.
77
 * </p>
78
 *
79
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
80
 */
81
public class DefaultFeatureQuery implements FeatureQuery {
82

    
83
    public static final String SCALE_PARAM_NAME = "Scale";
84

    
85
    private Map<String,Object> queryParameters = new HashMap();
86

    
87
    private String featureTypeId = null;
88

    
89
    private List<String> attributeNames = new ArrayList();
90

    
91
    private List<String> constantsAttributeNames = new ArrayList();
92

    
93
    private Evaluator filter;
94

    
95
    private FeatureQueryOrder order = new FeatureQueryOrder();
96

    
97
    private long limit;
98

    
99
    private long pageSize;
100

    
101
    private List<String> groupByColumns;
102
    
103
    private Map<String,String> aggregateFunctions;
104
    
105
    /**
106
     * Creates a FeatureQuery which will load all available Features of a type.
107
     *
108
     */
109
    public DefaultFeatureQuery() {
110
        super();
111
    }
112

    
113
    /**
114
     * Creates a FeatureQuery which will load all available Features of a type.
115
     *
116
     * @param featureType
117
     *            the type of Features of the query
118
     */
119
    public DefaultFeatureQuery(FeatureType featureType) {
120
        super();
121
        this.setFeatureType(featureType);
122
    }
123

    
124
    /**
125
     * Creates a FeatureQuery with the type of features, a filter and the order
126
     * for the FeatureCollection.
127
     *
128
     * @param featureType
129
     *            the type of Features of the query
130
     * @param filter
131
     *            based on the properties of the Features
132
     */
133
    public DefaultFeatureQuery(FeatureType featureType, Evaluator filter) {
134
        super();
135
        this.setFeatureType(featureType);
136
        this.filter = filter;
137
    }
138

    
139
    /**
140
     * Creates a FeatureQuery with the type of features, a filter, the order for
141
     * the FeatureCollection and the view scale.
142
     *
143
     * @param featureType
144
     *            the type of Features of the query
145
     * @param filter
146
     *            based on the properties of the Features
147
     * @param scale
148
     *            to view the Features.
149
     */
150
    public DefaultFeatureQuery(FeatureType featureType, Evaluator filter,
151
        double scale) {
152
        this.setFeatureType(featureType);
153
        this.filter = filter;
154
        this.setScale(scale);
155
    }
156

    
157
    /**
158
     * Creates a FeatureQuery which will load a list of attribute names of all
159
     * available Features.
160
     *
161
     * @param attributeNames
162
     *            the list of attribute names to load
163
     */
164
    public DefaultFeatureQuery(String[] attributeNames) {
165
        super();
166
        setAttributeNames(attributeNames);
167
    }
168

    
169
    /**
170
     * Creates a FeatureQuery with the list of attribute names of feature, a
171
     * filter and the order for the FeatureCollection.
172
     *
173
     * @param attributeNames
174
     *            the list of attribute names to load
175
     * @param filter
176
     *            based on the properties of the Features
177
     */
178
    public DefaultFeatureQuery(String[] attributeNames, Evaluator filter) {
179
        super();
180
        setAttributeNames(attributeNames);
181
        this.filter = filter;
182
    }
183

    
184
    /**
185
     * Creates a FeatureQuery with the list of attribute names of feature, a
186
     * filter, the order for the FeatureCollection and the view scale.
187
     *
188
     * @param attributeNames
189
     *            the list of attribute names to load
190
     * @param filter
191
     *            based on the properties of the Features
192
     * @param scale
193
     *            to view the Features.
194
     */
195
    public DefaultFeatureQuery(String[] attributeNames, Evaluator filter,
196
        double scale) {
197
        setAttributeNames(attributeNames);
198
        this.filter = filter;
199
        this.setScale(scale);
200
    }
201

    
202
    @Override
203
    public double getScale() {
204
        Double scale = (Double) this.getQueryParameter(SCALE_PARAM_NAME);
205
        if (scale == null) {
206
            return 0;
207
        }
208
        return scale;
209
    }
210

    
211
    @Override
212
    public void setScale(double scale) {
213
        this.setQueryParameter(SCALE_PARAM_NAME, scale);
214
    }
215

    
216
    @Override
217
    public Object getQueryParameter(String name) {
218
        return queryParameters.get(name);
219
    }
220

    
221
    @Override
222
    public void setQueryParameter(String name, Object value) {
223
        queryParameters.put(name, value);
224
    }
225

    
226
    @Override
227
    public void setFeatureType(FeatureType featureType) {
228
        this.featureTypeId = featureType.getId();
229
    }
230

    
231
    @Override
232
    public String[] getAttributeNames() {
233
        return (String[])attributeNames.toArray(new String[attributeNames.size()]);
234
    }
235

    
236
    @Override
237
    public void setAttributeNames(String[] attributeNames) {
238
        this.attributeNames.clear();
239
        if (attributeNames != null){
240
            for (int i=0 ; i<attributeNames.length ; i++){
241
                this.attributeNames.add(attributeNames[i]);
242
            }
243
        }
244
    }
245

    
246
    @Override
247
    public void retrievesAllAttributes() {
248
        this.attributeNames.clear();
249
    } 
250
    
251
    @Override
252
    public void addAttributeName(String attributeName){
253
        //If the attribute exists finish the method
254
        for (int i=0 ; i<attributeNames.size() ; i++){
255
            if (attributeNames.get(i).equals(attributeName)){
256
                return;
257
            }
258
        }
259
        this.attributeNames.add(attributeName);
260
    }
261

    
262
    @Override
263
    public void addEssentialAttributeNames(FeatureStore store) {
264
        FeatureType storeType;
265
        try {
266
            storeType = store.getDefaultFeatureType();
267
        } catch (DataException ex) {
268
            throw new RuntimeException("Can't access to the default feature type of tghe store", ex);
269
        }
270
        FeatureAttributeDescriptor[] pks = storeType.getPrimaryKey();
271
        if( storeType.hasOID() || ArrayUtils.isEmpty(pks) ) {
272
            FeatureAttributeDescriptor attrInt = null;
273
            FeatureAttributeDescriptor attrStr = null;
274
            FeatureAttributeDescriptor attrNotGeom = null;
275
            for (FeatureAttributeDescriptor attr : storeType) {
276
                if( attrInt == null && (attr.getType()==DataTypes.INT || attr.getType()==DataTypes.LONG) ) {
277
                    attrInt = attr;
278
                } else if( attrStr == null && attr.getType()==DataTypes.STRING ) {
279
                    attrStr = attr;
280
                } else if( attrNotGeom == null && attr.getType()!=DataTypes.GEOMETRY ) {
281
                    attrNotGeom = attr;
282
                }
283
            }
284
            if( attrInt != null ) {
285
                this.addAttributeName(attrInt.getName());
286
            } else if( attrStr != null ) {
287
                this.addAttributeName(attrStr.getName());
288
            } else if( attrNotGeom != null ) {
289
                this.addAttributeName(attrNotGeom.getName());
290
            } else {
291
                this.addAttributeName(storeType.getAttributeDescriptor(0).getName());
292
            }
293
        } else {
294
            for(FeatureAttributeDescriptor attr : pks ) {
295
                this.addAttributeName(attr.getName());
296
            }
297
        }
298
    }
299
    
300
    @Override
301
    public void addPrimaryKeyAttributeNames(FeatureStore store) {
302
        FeatureType storeType;
303
        try {
304
            storeType = store.getDefaultFeatureType();
305
        } catch (DataException ex) {
306
            throw new RuntimeException("Can't access to the default feature type of tghe store", ex);
307
        }
308
        for(FeatureAttributeDescriptor attr : storeType.getPrimaryKey() ) {
309
            this.addAttributeName(attr.getName());
310
        }
311
    }
312

    
313
    @Override
314
    public boolean hasAttributeNames() {
315
        return !this.attributeNames.isEmpty();
316
    }
317

    
318
    @Override
319
    public void clearAttributeNames() {
320
        this.attributeNames = new ArrayList();
321
    }
322

    
323
    @Override
324
    public Evaluator getFilter() {
325
        return filter;
326
    }
327

    
328
    @Override
329
    public Expression getExpressionFilter() {
330
      if( this.filter instanceof ExpressionEvaluator ) {
331
        return ((ExpressionEvaluator)this.filter).getExpression();
332
      }
333
      return null;
334
    }
335

    
336
    @Override
337
    public void setFilter(Expression filter) {
338
        if( filter == null ) {
339
            this.clearFilter();
340
            return;
341
        }
342
        Evaluator x = new DefaultExpressionEvaluator(filter);
343
        this.setFilter(x);
344
    }
345

    
346
   @Override
347
    public void setFilter(String filter) {
348
        if( StringUtils.isEmpty(filter) ) {
349
            this.clearFilter();
350
            return;
351
        }
352
        try {
353
            this.setFilter(ExpressionUtils.createExpression(filter));
354
        } catch (Exception ex) {
355
            throw new RuntimeException("Can't create filter from '"+filter+"'",ex);
356
        }
357
    }
358

    
359
    @Override
360
    public void setFilter(Evaluator filter) {
361
        if( filter == null ) {
362
            this.clearFilter();
363
            return;
364
        }        
365
        this.filter = filter;
366
        addFilterAttributes(filter);
367
    }
368

    
369
    @Override
370
    public void addFilter(String filter) {
371
        if( StringUtils.isEmpty(filter) ) {
372
            return;
373
        }
374
        this.addFilter(ExpressionUtils.createExpression(filter));
375
    }
376

    
377
    @Override
378
    public void addFilter(Expression filter) {
379
        Evaluator x = new DefaultExpressionEvaluator(filter);
380
        this.addFilter(x);
381
    }
382

    
383
    @Override
384
    public void addFilter(Evaluator evaluator) {
385
        if (evaluator == null) {
386
            return;
387
        }
388
        if (this.filter == null) {
389
            this.filter = evaluator;
390
        } else {
391
            if (this.filter instanceof AndEvaluator) {
392
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
393
            } else {
394
                this.filter = new AndEvaluator(this.filter);
395
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
396
            }
397
        }
398
        addFilterAttributes(evaluator);
399
    }
400

    
401
    @Override
402
    public void clearFilter() {
403
      this.filter = null;
404
    }
405

    
406
    private void addFilterAttributes(Evaluator evaluator){
407
        if (evaluator != null){
408
            EvaluatorFieldsInfo fieldsInfo = evaluator.getFieldsInfo();
409
            if (fieldsInfo == null){
410
                // FieldsInfo is not available in this evaluator
411
                return;
412
            }
413
            String[] fieldNames = fieldsInfo.getFieldNames();
414
            if (fieldNames== null){
415
                // fieldNames is not available in this evaluator
416
                return;
417
            }
418

    
419
            for (int i=0 ; i<fieldNames.length ; i++){
420
                addAttributeName(fieldNames[i]);
421
            }
422
        }
423
    }
424

    
425
    @Override
426
    public FeatureQueryOrder getOrder() {
427
        return order;
428
    }
429

    
430
    @Override
431
    public void setOrder(FeatureQueryOrder order) {
432
        this.order = order;
433
    }
434

    
435
    @Override
436
    public boolean hasFilter() {
437
        return this.filter != null;
438
    }
439

    
440
    @Override
441
    public boolean hasOrder() {
442
        return this.order != null && this.order.size() > 0;
443
    }
444

    
445
    @Override
446
    public Object clone() throws CloneNotSupportedException {
447
        DefaultFeatureQuery clone = (DefaultFeatureQuery) super.clone();
448

    
449
        // Clone attribute names array
450
        if (attributeNames != null) {
451
            clone.attributeNames = new ArrayList();
452
            for (int i=0 ; i<attributeNames.size() ; i++){
453
                clone.attributeNames.add(attributeNames.get(i));
454
            }
455
        }
456

    
457
        // Clone order
458
        if (order != null) {
459
            clone.order = (FeatureQueryOrder) order.clone();
460
        }
461

    
462
        return clone;
463
    }
464

    
465
    @Override
466
    public FeatureQuery getCopy() {
467
        try {
468
            return (FeatureQuery) clone();
469
        } catch (CloneNotSupportedException e) {
470
            // TODO Auto-generated catch block
471
            e.printStackTrace();
472
            return null;
473
        }
474
        // DefaultFeatureQuery aCopy = new DefaultFeatureQuery();
475
        //
476
        // aCopy.featureTypeId = this.featureTypeId;
477
        //
478
        // if (this.attributeNames != null) {
479
        // aCopy.attributeNames = (String[]) Arrays
480
        // .asList(this.attributeNames).toArray(new String[0]);
481
        // }
482
        //
483
        // aCopy.filter = this.filter;
484
        //
485
        // if (this.order != null) {
486
        // aCopy.order = this.order.getCopy();
487
        // }
488
        //
489
        // return aCopy;
490
    }
491

    
492
    @Override
493
    public String getFeatureTypeId() {
494
        return featureTypeId;
495
    }
496

    
497
    @Override
498
    public void setFeatureTypeId(String featureTypeId) {
499
        this.featureTypeId = featureTypeId;
500
    }
501

    
502
    @Override
503
    public void saveToState(PersistentState state) throws PersistenceException {
504
        // FIXME: falta por terminar de implementar
505
        state.set("queryParameters", this.queryParameters);
506
        state.set("featureTypeId", this.featureTypeId);
507
        state.set("attributeNames", this.attributeNames);
508
        // state.set("filter", this.filter);
509
        state.set("limit", this.limit);
510
        state.set("pageSize", this.pageSize);
511

    
512
    }
513

    
514
    @Override
515
    public void loadFromState(PersistentState state) throws PersistenceException {
516
        // FIXME: falta por terminar de implementar
517
        this.queryParameters = (Map) state.get("queryParameters");
518
        this.featureTypeId = state.getString("featureTypeId");
519
        this.attributeNames = state.getList("attributeNames");
520
        this.filter = (Evaluator) state.get("filter");
521
        this.limit = state.getLong("limit");
522
        this.pageSize = state.getLong("pageSize");
523

    
524
    }
525

    
526
    /**
527
     * Register the class on PersistenceManager
528
     *
529
     */
530
    public static void registerPersistent() {
531
        DynStruct definition =
532
            ToolsLocator.getPersistenceManager()
533
            .addDefinition(DefaultFeatureQuery.class,
534
                "DefaultFeatureQuery",
535
                "DefaultFeatureQuery Persistent definition",
536
                null,
537
                null);
538

    
539
        definition.addDynFieldMap("queryParameters")
540
        .setClassOfItems(Object.class)
541
        .setMandatory(true);
542

    
543
        definition.addDynFieldString("featureTypeId").setMandatory(false);
544

    
545
        definition.addDynFieldList("attributeNames")
546
        .setClassOfItems(String.class)
547
        .setMandatory(false);
548

    
549
        definition.addDynFieldObject("filter")
550
        .setClassOfValue(Evaluator.class)
551
        .setMandatory(false);
552

    
553
        definition.addDynFieldObject("order")
554
        .setClassOfValue(FeatureQueryOrder.class)
555
        .setMandatory(false);
556

    
557
        definition.addDynFieldLong("limit").setMandatory(false);
558

    
559
        definition.addDynFieldLong("pageSize").setMandatory(false);
560

    
561
    }
562

    
563
    @Override
564
    public long getLimit() {
565
        return limit;
566
    }
567

    
568
    @Override
569
    public long getPageSize() {
570
        return pageSize;
571
    }
572

    
573
    @Override
574
    public void setLimit(long limit) {
575
        this.limit = limit;
576
    }
577

    
578
    @Override
579
    public void setPageSize(long pageSize) {
580
        this.pageSize = pageSize;
581
    }
582

    
583
    @Override
584
    public String[] getConstantsAttributeNames() {
585
        return (String[])constantsAttributeNames.toArray(new String[constantsAttributeNames.size()]);
586
    }
587

    
588
    @Override
589
    public void setConstantsAttributeNames(String[] constantsAttributeNames) {
590
        this.constantsAttributeNames.clear();
591
        if (constantsAttributeNames != null){
592
            for (int i=0 ; i<constantsAttributeNames.length ; i++){
593
                this.constantsAttributeNames.add(constantsAttributeNames[i]);
594
            }
595
        }
596
    }
597

    
598
    @Override
599
    public void addConstantAttributeName(String attributeName) {
600
        //If the attribute exists finish the method
601
        for (int i=0 ; i<constantsAttributeNames.size() ; i++){
602
            if (constantsAttributeNames.get(i).equals(attributeName)){
603
                return;
604
            }
605
        }
606
        this.constantsAttributeNames.add(attributeName);
607
    }
608

    
609
    @Override
610
    public boolean hasConstantsAttributeNames() {
611
        return !this.constantsAttributeNames.isEmpty();
612
    }
613

    
614
    @Override
615
    public void clearConstantsAttributeNames() {
616
        this.constantsAttributeNames = new ArrayList();
617
    }
618

    
619
  @Override
620
  public boolean isAGroupByColumn(String name) {
621
    for (String columnName : groupByColumns) {
622
      if( StringUtils.equalsIgnoreCase(name, columnName) ) {
623
        return true;
624
      }
625
    }
626
    return false;
627
  }
628

    
629
  @Override
630
  public List<String> getGroupByColumns() {
631
    if( this.groupByColumns == null ) {
632
      this.groupByColumns = new ArrayList<>();
633
    }
634
    return this.groupByColumns;
635
  }
636

    
637
  @Override
638
  public Map<String, String> getAggregateFunctions() {
639
    if( this.aggregateFunctions == null ) {
640
      this.aggregateFunctions = new HashMap<>();
641
    }
642
    return this.aggregateFunctions;
643
  }
644

    
645
  @Override
646
  public String getAggregate(String name) {    
647
      String fn = this.aggregateFunctions.get(name);
648
      if( StringUtils.isAlphanumeric(fn) ) {
649
        return fn + "(\""+ name + "\")";
650
      }
651
      return fn;
652
  }
653
  
654
  @Override
655
  public boolean hasAggregateFunctions() {
656
    return this.aggregateFunctions == null || this.aggregateFunctions.isEmpty();
657
  }
658

    
659
  @Override
660
  public boolean hasGroupByColumns() {
661
    return this.groupByColumns != null && !this.groupByColumns.isEmpty();
662
  }
663

    
664
  @Override
665
  public void copyFrom(FeatureQuery query) {
666
    DefaultFeatureQuery other = (DefaultFeatureQuery) query;
667
    this.queryParameters.clear();
668
    this.queryParameters.putAll(other.queryParameters);
669
    
670
    this.featureTypeId = other.featureTypeId;
671

    
672
    this.attributeNames.clear();
673
    this.attributeNames.addAll(other.attributeNames);
674

    
675
    this.constantsAttributeNames.clear();
676
    this.constantsAttributeNames.addAll(other.constantsAttributeNames);
677

    
678
    this.filter = other.filter;
679

    
680
    this.order.copyFrom(other.order);
681

    
682
    this.limit = other.limit;
683

    
684
    this.pageSize = other.pageSize;
685

    
686
    if( this.groupByColumns!=null && other.groupByColumns!=null ) {
687
      this.groupByColumns.clear();
688
      this.groupByColumns.addAll(other.groupByColumns);
689
    } else if( other.groupByColumns!=null ) {
690
      this.groupByColumns = new ArrayList<>();
691
      this.groupByColumns.addAll(other.groupByColumns);
692
    } else if( this.groupByColumns!=null ) {
693
      this.groupByColumns = null;
694
    }
695
    
696
    if( this.aggregateFunctions!=null && other.groupByColumns!=null ) {
697
      this.aggregateFunctions.clear();
698
      this.aggregateFunctions.putAll(other.aggregateFunctions);
699
    } else if( other.groupByColumns!=null ) {
700
      this.aggregateFunctions = new HashMap<>();
701
      this.aggregateFunctions.putAll(other.aggregateFunctions);
702
    } else if( this.groupByColumns!=null ) {
703
      this.groupByColumns=null;
704
    }
705
  }
706

    
707
}