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

History | View | Annotate | Download (21.6 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.EditableFeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureExtraColumn;
40
import org.gvsig.fmap.dal.feature.FeatureQuery;
41
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
42
import org.gvsig.fmap.dal.feature.FeatureStore;
43
import org.gvsig.fmap.dal.feature.FeatureType;
44
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultExpressionEvaluator;
45
import org.gvsig.tools.ToolsLocator;
46
import org.gvsig.tools.dynobject.DynStruct;
47
import org.gvsig.tools.evaluator.AndEvaluator;
48
import org.gvsig.tools.evaluator.Evaluator;
49
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
50
import org.gvsig.tools.persistence.PersistentState;
51
import org.gvsig.tools.persistence.exception.PersistenceException;
52

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

    
85
    public static final String SCALE_PARAM_NAME = "Scale";
86

    
87
    private Map<String,Object> queryParameters = new HashMap();
88

    
89
    private String featureTypeId = null;
90

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

    
93
    private List<String> constantsAttributeNames = new ArrayList();
94

    
95
    private Evaluator filter;
96

    
97
    private FeatureQueryOrder order = new FeatureQueryOrder();
98

    
99
    private long limit;
100

    
101
    private long pageSize;
102

    
103
    private List<String> groupByColumns;
104
    
105
    private Map<String,String> aggregateFunctions;
106
    
107
    private FeatureExtraColumn extraColumn = new DefaultFeatureExtraColumn();
108
    
109
    /**
110
     * Creates a FeatureQuery which will load all available Features of a type.
111
     *
112
     */
113
    public DefaultFeatureQuery() {
114
        super();
115
    }
116

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

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

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

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

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

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

    
206
    @Override
207
    public double getScale() {
208
        Double scale = (Double) this.getQueryParameter(SCALE_PARAM_NAME);
209
        if (scale == null) {
210
            return 0;
211
        }
212
        return scale;
213
    }
214

    
215
    @Override
216
    public void setScale(double scale) {
217
        this.setQueryParameter(SCALE_PARAM_NAME, scale);
218
    }
219

    
220
    @Override
221
    public Object getQueryParameter(String name) {
222
        return queryParameters.get(name);
223
    }
224

    
225
    @Override
226
    public void setQueryParameter(String name, Object value) {
227
        queryParameters.put(name, value);
228
    }
229

    
230
    @Override
231
    public void setFeatureType(FeatureType featureType) {
232
        this.featureTypeId = featureType.getId();
233
    }
234

    
235
    @Override
236
    public String[] getAttributeNames() {
237
        return (String[])attributeNames.toArray(new String[attributeNames.size()]);
238
    }
239

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

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

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

    
317
    @Override
318
    public boolean hasAttributeNames() {
319
        return !this.attributeNames.isEmpty();
320
    }
321

    
322
    @Override
323
    public void clearAttributeNames() {
324
        this.attributeNames = new ArrayList();
325
    }
326

    
327
    @Override
328
    public Evaluator getFilter() {
329
        return filter;
330
    }
331

    
332
    @Override
333
    public Expression getExpressionFilter() {
334
      if( this.filter instanceof ExpressionEvaluator ) {
335
        return ((ExpressionEvaluator)this.filter).getExpression();
336
      }
337
      return null;
338
    }
339

    
340
    @Override
341
    public void setFilter(Expression filter) {
342
        if( filter == null ) {
343
            this.clearFilter();
344
            return;
345
        }
346
        Evaluator x = new DefaultExpressionEvaluator(filter);
347
        this.setFilter(x);
348
    }
349

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

    
363
    @Override
364
    public void setFilter(Evaluator filter) {
365
        if( filter == null ) {
366
            this.clearFilter();
367
            return;
368
        }        
369
        this.filter = filter;
370
        addFilterAttributes(filter);
371
    }
372

    
373
    @Override
374
    public void addFilter(String filter) {
375
        if( StringUtils.isEmpty(filter) ) {
376
            return;
377
        }
378
        this.addFilter(ExpressionUtils.createExpression(filter));
379
    }
380

    
381
    @Override
382
    public void addFilter(Expression filter) {
383
        Evaluator x = new DefaultExpressionEvaluator(filter);
384
        this.addFilter(x);
385
    }
386

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

    
405
    @Override
406
    public void clearFilter() {
407
      this.filter = null;
408
    }
409

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

    
423
            for (int i=0 ; i<fieldNames.length ; i++){
424
                addAttributeName(fieldNames[i]);
425
            }
426
        }
427
    }
428

    
429
    @Override
430
    public FeatureQueryOrder getOrder() {
431
        return order;
432
    }
433

    
434
    @Override
435
    public void setOrder(FeatureQueryOrder order) {
436
        this.order = order;
437
    }
438

    
439
    @Override
440
    public boolean hasFilter() {
441
        return this.filter != null;
442
    }
443

    
444
    @Override
445
    public boolean hasOrder() {
446
        return this.order != null && this.order.size() > 0;
447
    }
448

    
449
    @Override
450
    public Object clone() throws CloneNotSupportedException {
451
        DefaultFeatureQuery clone = (DefaultFeatureQuery) super.clone();
452

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

    
461
        // Clone order
462
        if (order != null) {
463
            clone.order = (FeatureQueryOrder) order.clone();
464
        }
465

    
466
        return clone;
467
    }
468

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

    
496
    @Override
497
    public String getFeatureTypeId() {
498
        return featureTypeId;
499
    }
500

    
501
    @Override
502
    public void setFeatureTypeId(String featureTypeId) {
503
        this.featureTypeId = featureTypeId;
504
    }
505

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

    
516
    }
517

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

    
528
    }
529

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

    
543
        definition.addDynFieldMap("queryParameters")
544
        .setClassOfItems(Object.class)
545
        .setMandatory(true);
546

    
547
        definition.addDynFieldString("featureTypeId").setMandatory(false);
548

    
549
        definition.addDynFieldList("attributeNames")
550
        .setClassOfItems(String.class)
551
        .setMandatory(false);
552

    
553
        definition.addDynFieldObject("filter")
554
        .setClassOfValue(Evaluator.class)
555
        .setMandatory(false);
556

    
557
        definition.addDynFieldObject("order")
558
        .setClassOfValue(FeatureQueryOrder.class)
559
        .setMandatory(false);
560

    
561
        definition.addDynFieldLong("limit").setMandatory(false);
562

    
563
        definition.addDynFieldLong("pageSize").setMandatory(false);
564

    
565
    }
566

    
567
    @Override
568
    public long getLimit() {
569
        return limit;
570
    }
571

    
572
    @Override
573
    public long getPageSize() {
574
        return pageSize;
575
    }
576

    
577
    @Override
578
    public void setLimit(long limit) {
579
        this.limit = limit;
580
    }
581

    
582
    @Override
583
    public void setPageSize(long pageSize) {
584
        this.pageSize = pageSize;
585
    }
586

    
587
    @Override
588
    public String[] getConstantsAttributeNames() {
589
        return (String[])constantsAttributeNames.toArray(new String[constantsAttributeNames.size()]);
590
    }
591

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

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

    
613
    @Override
614
    public boolean hasConstantsAttributeNames() {
615
        return !this.constantsAttributeNames.isEmpty();
616
    }
617

    
618
    @Override
619
    public void clearConstantsAttributeNames() {
620
        this.constantsAttributeNames = new ArrayList();
621
    }
622

    
623
  @Override
624
  public boolean isAGroupByColumn(String name) {
625
    for (String columnName : groupByColumns) {
626
      if( StringUtils.equalsIgnoreCase(name, columnName) ) {
627
        return true;
628
      }
629
    }
630
    return false;
631
  }
632

    
633
  @Override
634
  public List<String> getGroupByColumns() {
635
    if( this.groupByColumns == null ) {
636
      this.groupByColumns = new ArrayList<>();
637
    }
638
    return this.groupByColumns;
639
  }
640

    
641
  @Override
642
  public Map<String, String> getAggregateFunctions() {
643
    if( this.aggregateFunctions == null ) {
644
      this.aggregateFunctions = new HashMap<>();
645
    }
646
    return this.aggregateFunctions;
647
  }
648

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

    
663
  @Override
664
  public boolean hasGroupByColumns() {
665
    return this.groupByColumns != null && !this.groupByColumns.isEmpty();
666
  }
667

    
668
  @Override
669
  public void copyFrom(FeatureQuery query) {
670
    DefaultFeatureQuery other = (DefaultFeatureQuery) query;
671
    this.queryParameters.clear();
672
    this.queryParameters.putAll(other.queryParameters);
673
    
674
    this.featureTypeId = other.featureTypeId;
675

    
676
    this.attributeNames.clear();
677
    this.attributeNames.addAll(other.attributeNames);
678

    
679
    this.constantsAttributeNames.clear();
680
    this.constantsAttributeNames.addAll(other.constantsAttributeNames);
681

    
682
    this.filter = other.filter;
683

    
684
    this.order.copyFrom(other.order);
685

    
686
    this.limit = other.limit;
687

    
688
    this.pageSize = other.pageSize;
689

    
690
    if( this.groupByColumns!=null && other.groupByColumns!=null ) {
691
      this.groupByColumns.clear();
692
      this.groupByColumns.addAll(other.groupByColumns);
693
    } else if( other.groupByColumns!=null ) {
694
      this.groupByColumns = new ArrayList<>();
695
      this.groupByColumns.addAll(other.groupByColumns);
696
    } else if( this.groupByColumns!=null ) {
697
      this.groupByColumns = null;
698
    }
699
    
700
    if( this.aggregateFunctions!=null && other.aggregateFunctions!=null ) {
701
      this.aggregateFunctions.clear();
702
      this.aggregateFunctions.putAll(other.aggregateFunctions);
703
    } else if( other.aggregateFunctions!=null ) {
704
      this.aggregateFunctions = new HashMap<>();
705
      this.aggregateFunctions.putAll(other.aggregateFunctions);
706
    } else if( this.aggregateFunctions!=null ) {
707
      this.aggregateFunctions=null;
708
    }
709
    this.extraColumn.copyFrom(other.extraColumn);
710
  }
711

    
712
  public FeatureExtraColumn getExtraColumn() {
713
      return this.extraColumn;
714
  }
715
  
716
}