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

History | View | Annotate | Download (29.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
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 java.util.logging.Level;
31
import org.apache.commons.lang3.ArrayUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.gvsig.expressionevaluator.Expression;
34
import org.gvsig.expressionevaluator.ExpressionUtils;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.DataManager;
37
import org.gvsig.fmap.dal.DataTypes;
38
import org.gvsig.fmap.dal.exception.DataException;
39
import org.gvsig.fmap.dal.exception.InitializeException;
40
import org.gvsig.expressionevaluator.ExpressionEvaluator;
41
import org.gvsig.expressionevaluator.MutableSymbolTable;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureQuery;
44
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
45
import org.gvsig.fmap.dal.feature.FeatureStore;
46
import org.gvsig.fmap.dal.feature.FeatureType;
47
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
48
import org.gvsig.tools.ToolsLocator;
49
import org.gvsig.tools.dynobject.DynStruct;
50
import org.gvsig.tools.evaluator.AndEvaluator;
51
import org.gvsig.tools.evaluator.Evaluator;
52
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
53
import org.gvsig.tools.persistence.PersistentState;
54
import org.gvsig.tools.persistence.exception.PersistenceException;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
58

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

    
93
    public static final String SCALE_PARAM_NAME = "Scale";
94

    
95
    private Map<String,Object> queryParameters = new HashMap();
96

    
97
    private String featureTypeId = null;
98

    
99
    private List<String> attributeNames = new ArrayList();
100

    
101
    private List<String> constantsAttributeNames = new ArrayList();
102

    
103
    private Evaluator filter;
104

    
105
    private FeatureQueryOrder order = new DefaultFeatureQueryOrder();
106

    
107
    private long limit;
108

    
109
    private long pageSize;
110

    
111
    private List<String> groupByColumns;
112
    
113
    private Map<String,String> aggregateFunctions;
114
    
115
    private FeatureExtraColumns extraColumn = new DefaultFeatureExtraColumns();
116
    
117
    private MutableSymbolTable symbolTable;
118
        private String storeName;
119
    
120
    /**
121
     * Creates a FeatureQuery which will load all available Features of a type.
122
     *
123
     */
124
    public DefaultFeatureQuery() {
125
                super();
126
        }
127
        
128
    public DefaultFeatureQuery(String storeName) {
129
        this();
130
                this.storeName = storeName;
131
                
132
    }
133

    
134
    /**
135
     * Creates a FeatureQuery which will load all available Features of a type.
136
     *
137
     * @param featureType
138
     *            the type of Features of the query
139
     */
140
    public DefaultFeatureQuery(FeatureType featureType) {
141
        super();
142
        this.setFeatureType(featureType);
143
    }
144

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

    
160
    /**
161
     * Creates a FeatureQuery with the type of features, a filter, the order for
162
     * the FeatureCollection and the view scale.
163
     *
164
     * @param featureType
165
     *            the type of Features of the query
166
     * @param filter
167
     *            based on the properties of the Features
168
     * @param scale
169
     *            to view the Features.
170
     */
171
    public DefaultFeatureQuery(FeatureType featureType, Evaluator filter,
172
        double scale) {
173
        this.setFeatureType(featureType);
174
        this.filter = filter;
175
        this.setScale(scale);
176
    }
177

    
178
    /**
179
     * Creates a FeatureQuery which will load a list of attribute names of all
180
     * available Features.
181
     *
182
     * @param attributeNames
183
     *            the list of attribute names to load
184
     */
185
    public DefaultFeatureQuery(String[] attributeNames) {
186
        super();
187
        setAttributeNames(attributeNames);
188
    }
189

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

    
205
    /**
206
     * Creates a FeatureQuery with the list of attribute names of feature, a
207
     * filter, the order for the FeatureCollection and the view scale.
208
     *
209
     * @param attributeNames
210
     *            the list of attribute names to load
211
     * @param filter
212
     *            based on the properties of the Features
213
     * @param scale
214
     *            to view the Features.
215
     */
216
    public DefaultFeatureQuery(String[] attributeNames, Evaluator filter,
217
        double scale) {
218
        setAttributeNames(attributeNames);
219
        this.filter = filter;
220
        this.setScale(scale);
221
    }
222

    
223
    @Override
224
    public double getScale() {
225
        Double scale = (Double) this.getQueryParameter(SCALE_PARAM_NAME);
226
        if (scale == null) {
227
            return 0;
228
        }
229
        return scale;
230
    }
231

    
232
    @Override
233
    public void setScale(double scale) {
234
        this.setQueryParameter(SCALE_PARAM_NAME, scale);
235
    }
236

    
237
    @Override
238
    public Object getQueryParameter(String name) {
239
        return queryParameters.get(name);
240
    }
241

    
242
    @Override
243
    public void setQueryParameter(String name, Object value) {
244
        queryParameters.put(name, value);
245
    }
246

    
247
    @Override
248
    public void setFeatureType(FeatureType featureType) {
249
        this.featureTypeId = featureType.getId();
250
    }
251

    
252
    @Override
253
    public String[] getAttributeNames() {
254
        if (this.hasExtraColumnDeclaredAsGroupByField()) {
255
            this.retrievesAllAttributes();
256
        }
257
        return (String[])attributeNames.toArray(new String[attributeNames.size()]);
258
    }
259
    
260
    private boolean hasExtraColumnDeclaredAsGroupByField() {
261
        // indica si un campo de agrupaciones es una columna calculada
262
        if (this.hasGroupByColumns()) {
263
            for (String groupByColumn : groupByColumns) {
264
                if (this.extraColumn.get(groupByColumn)!=null) {
265
                    return true;
266
                }
267
            }
268
        }
269
        return false;
270
    }
271

    
272
    @Override
273
    public void setAttributeNames(String[] attributeNames) {
274
        this.attributeNames.clear();
275
        if (attributeNames != null){
276
            for (int i=0 ; i<attributeNames.length ; i++){
277
                this.attributeNames.add(attributeNames[i]);
278
            }
279
        }
280
    }
281

    
282
    @Override
283
    public void retrievesAllAttributes() {
284
        this.attributeNames.clear();
285
    } 
286
    
287
    @Override
288
    public void addAttributeName(String attributeName){
289
        //If the attribute exists finish the method
290
        for (int i=0 ; i<attributeNames.size() ; i++){
291
            if (attributeNames.get(i).equals(attributeName)){
292
                return;
293
            }
294
        }
295
        this.attributeNames.add(attributeName);
296
    }
297

    
298
    @Override
299
    public void addEssentialAttributeNames(FeatureStore store) {
300
        FeatureType storeType;
301
        try {
302
            storeType = store.getDefaultFeatureType();
303
        } catch (DataException ex) {
304
            throw new RuntimeException("Can't access to the default feature type of tghe store", ex);
305
        }
306
        FeatureAttributeDescriptor[] pks = storeType.getPrimaryKey();
307
        if( storeType.hasOID() || ArrayUtils.isEmpty(pks) ) {
308
            FeatureAttributeDescriptor attrInt = null;
309
            FeatureAttributeDescriptor attrStr = null;
310
            FeatureAttributeDescriptor attrNotGeom = null;
311
            for (FeatureAttributeDescriptor attr : storeType) {
312
                if( attrInt == null && (attr.getType()==DataTypes.INT || attr.getType()==DataTypes.LONG) ) {
313
                    attrInt = attr;
314
                } else if( attrStr == null && attr.getType()==DataTypes.STRING ) {
315
                    attrStr = attr;
316
                } else if( attrNotGeom == null && attr.getType()!=DataTypes.GEOMETRY ) {
317
                    attrNotGeom = attr;
318
                }
319
            }
320
            if( attrInt != null ) {
321
                this.addAttributeName(attrInt.getName());
322
            } else if( attrStr != null ) {
323
                this.addAttributeName(attrStr.getName());
324
            } else if( attrNotGeom != null ) {
325
                this.addAttributeName(attrNotGeom.getName());
326
            } else {
327
                this.addAttributeName(storeType.getAttributeDescriptor(0).getName());
328
            }
329
        } else {
330
            for(FeatureAttributeDescriptor attr : pks ) {
331
                this.addAttributeName(attr.getName());
332
            }
333
        }
334
    }
335
    
336
    @Override
337
    public void addPrimaryKeyAttributeNames(FeatureStore store) {
338
        FeatureType storeType;
339
        try {
340
            storeType = store.getDefaultFeatureType();
341
        } catch (DataException ex) {
342
            throw new RuntimeException("Can't access to the default feature type of tghe store", ex);
343
        }
344
        for(FeatureAttributeDescriptor attr : storeType.getPrimaryKey() ) {
345
            this.addAttributeName(attr.getName());
346
        }
347
    }
348

    
349
    @Override
350
    public boolean hasAttributeNames() {
351
        if (hasExtraColumnDeclaredAsGroupByField()) {
352
            return true;
353
        }
354
        return !this.attributeNames.isEmpty();
355
    }
356

    
357
    @Override
358
    public void clearAttributeNames() {
359
        this.attributeNames = new ArrayList();
360
    }
361

    
362
    @Override
363
    public Evaluator getFilter() {
364
      if( this.filter instanceof ExpressionEvaluator ) {
365
        ExpressionEvaluator ee = (ExpressionEvaluator) this.filter;
366
        ee.addSymbolTable(symbolTable);
367
      }
368
      return filter;
369
    }
370

    
371
    @Override
372
    public Expression getExpressionFilter() {
373
      if( this.filter instanceof ExpressionEvaluator ) {
374
        ExpressionEvaluator ee = (ExpressionEvaluator) this.filter;
375
        ee.addSymbolTable(symbolTable);
376
        return ee.toExpression();
377
      }
378
      return null;
379
    }
380

    
381
    @Override
382
    public void setFilter(Expression filter) {
383
        if( filter == null ) {
384
            this.clearFilter();
385
            return;
386
        }
387
        Evaluator x = new DefaultFeatureExpressionEvaluator(storeName, filter);
388
        this.setFilter(x);
389
    }
390

    
391
   @Override
392
    public void setFilter(String filter) {
393
        if( StringUtils.isEmpty(filter) ) {
394
            this.clearFilter();
395
            return;
396
        }
397
        try {
398
            this.setFilter(ExpressionUtils.createExpression(filter));
399
        } catch (Exception ex) {
400
            throw new RuntimeException("Can't create filter from '"+filter+"'",ex);
401
        }
402
    }
403

    
404
    @Override
405
    public void setFilter(Evaluator filter) {
406
        if( filter == null ) {
407
            this.clearFilter();
408
            return;
409
        }        
410
        this.filter = filter;
411
        addFilterAttributes(filter);
412
    }
413

    
414
    @Override
415
    public void addFilter(String filter) {
416
        if( StringUtils.isEmpty(filter) ) {
417
            return;
418
        }
419
        this.addFilter(ExpressionUtils.createExpression(filter));
420
    }
421

    
422
    @Override
423
    public void addFilter(Expression filter) {
424
        Evaluator x = new DefaultFeatureExpressionEvaluator(filter);
425
        this.addFilter(x);
426
    }
427

    
428
    @Override
429
    public void addFilter(Evaluator evaluator) {
430
        if (evaluator == null) {
431
            return;
432
        }
433
        if (this.filter == null) {
434
            this.filter = evaluator;
435
        } else {
436
            if (this.filter instanceof AndEvaluator) {
437
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
438
            } else {
439
                this.filter = new AndEvaluator(this.filter);
440
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
441
            }
442
        }
443
        addFilterAttributes(evaluator);
444
    }
445

    
446
    @Override
447
    public void clearFilter() {
448
      this.filter = null;
449
    }
450

    
451
    private void addFilterAttributes(Evaluator evaluator){
452
        if (evaluator != null){
453
            EvaluatorFieldsInfo fieldsInfo = evaluator.getFieldsInfo();
454
            if (fieldsInfo == null){
455
                // FieldsInfo is not available in this evaluator
456
                return;
457
            }
458
            String[] fieldNames = fieldsInfo.getFieldNames();
459
            if (fieldNames== null){
460
                // fieldNames is not available in this evaluator
461
                return;
462
            }
463

    
464
            for (int i=0 ; i<fieldNames.length ; i++){
465
                addAttributeName(fieldNames[i]);
466
            }
467
        }
468
    }
469

    
470
    @Override
471
    public FeatureQueryOrder getOrder() {
472
        return order;
473
    }
474

    
475
    @Override
476
    public void setOrder(FeatureQueryOrder order) {
477
        if(order == null){
478
            this.order = new DefaultFeatureQueryOrder();
479
        } else {
480
            this.order = order;
481
        }
482
    }
483

    
484
    @Override
485
    public boolean hasFilter() {
486
        return this.filter != null;
487
    }
488

    
489
    @Override
490
    public boolean hasOrder() {
491
        return this.order != null && this.order.size() > 0;
492
    }
493

    
494
    @Override
495
    public Object clone() throws CloneNotSupportedException {
496
        DefaultFeatureQuery clone = (DefaultFeatureQuery) super.clone();
497

    
498
        // Clone attribute names array
499
        if (attributeNames != null) {
500
            clone.attributeNames = new ArrayList();
501
            for (int i=0 ; i<attributeNames.size() ; i++){
502
                clone.attributeNames.add(attributeNames.get(i));
503
            }
504
        }
505

    
506
        // Clone order
507
        if (order != null) {
508
            clone.order = (FeatureQueryOrder) order.clone();
509
        }
510
        
511
        clone.extraColumn = extraColumn.getCopy();
512
        
513
        if( this.filter instanceof ExpressionEvaluator ) {
514
            Expression exp = ((ExpressionEvaluator)this.filter).toExpression();
515
            clone.filter =  new DefaultFeatureExpressionEvaluator(exp);
516
        }
517
        
518
        if (groupByColumns!=null) {
519
            clone.groupByColumns = new ArrayList<String>();
520
            for (String value : groupByColumns) {
521
                clone.groupByColumns.add(value);
522
            }
523
        } else {
524
            clone.groupByColumns = null;
525
        }
526
                
527
                
528
        if (aggregateFunctions!=null) {
529
            clone.aggregateFunctions = new HashMap<String, String>();
530
            for (String key : aggregateFunctions.keySet()) {
531
                clone.aggregateFunctions.put(key, aggregateFunctions.get(key));
532
            }
533
        } else {
534
            clone.aggregateFunctions = null;
535
        }
536
        if( this.symbolTable!=null ) {
537
            clone.symbolTable = this.symbolTable.clone();
538
        }
539
        
540
        return clone;
541
    }
542

    
543
    @Override
544
    public FeatureQuery getCopy() {
545
        try {
546
            return (FeatureQuery) clone();
547
        } catch (CloneNotSupportedException e) {
548
            LOGGER.debug("Can't clone feature query",e);
549
            return null;
550
        }
551
        // DefaultFeatureQuery aCopy = new DefaultFeatureQuery();
552
        //
553
        // aCopy.featureTypeId = this.featureTypeId;
554
        //
555
        // if (this.attributeNames != null) {
556
        // aCopy.attributeNames = (String[]) Arrays
557
        // .asList(this.attributeNames).toArray(new String[0]);
558
        // }
559
        //
560
        // aCopy.filter = this.filter;
561
        //
562
        // if (this.order != null) {
563
        // aCopy.order = this.order.getCopy();
564
        // }
565
        //
566
        // return aCopy;
567
    }
568

    
569
    @Override
570
    public String getFeatureTypeId() {
571
        return featureTypeId;
572
    }
573

    
574
    @Override
575
    public void setFeatureTypeId(String featureTypeId) {
576
        this.featureTypeId = featureTypeId;
577
    }
578

    
579
    @Override
580
    public void saveToState(PersistentState state) throws PersistenceException {
581
        // FIXME: falta por terminar de implementar
582
        state.set("queryParameters", this.queryParameters);
583
        state.set("featureTypeId", this.featureTypeId);
584
        state.set("attributeNames", this.attributeNames);
585
        
586
        ArrayList<Expression> filterList = new ArrayList<>();
587
        if (this.filter instanceof DefaultFeatureExpressionEvaluator) {
588
            DefaultFeatureExpressionEvaluator filterExpression = (DefaultFeatureExpressionEvaluator) this.filter;
589
           filterList.add(filterExpression.toExpression());
590
        } else if (this.filter instanceof AndEvaluator) {
591
            AndEvaluator filterAnd = (AndEvaluator) this.filter;
592
            List<Evaluator> evaluators = filterAnd.getEvaluators();
593
            for (Evaluator evaluator : evaluators) {
594
                if (evaluator instanceof DefaultFeatureExpressionEvaluator) {
595
                    DefaultFeatureExpressionEvaluator expressionEvaluator = (DefaultFeatureExpressionEvaluator) evaluator;
596
                    filterList.add(expressionEvaluator.toExpression());
597
                } else {
598
                    filterList.clear();
599
                    LOGGER.warn(StringUtils.join("Filters in this FeatureQuery will not persist:", this.toString()));
600
                    break;
601
                }
602
            }
603
        } else {
604
            filterList.clear();
605
            LOGGER.warn(StringUtils.join("Filters in this FeatureQuery will not persist:", this.toString()));
606
        }
607
        
608
        state.set("filter", filterList);
609
        state.set("limit", this.limit);
610
        state.set("pageSize", this.pageSize);
611
        
612
        state.set("order", this.order);
613
        state.set("groupByColumns", this.groupByColumns);
614
        state.set("aggregateFunctions", this.aggregateFunctions);
615
        state.set("extraColumn", this.extraColumn);
616
                state.set("storeName", this.storeName);
617
        
618

    
619
    }
620
    
621

    
622
    @Override
623
    public void loadFromState(PersistentState state) throws PersistenceException {
624
        // FIXME: falta por terminar de implementar
625
        this.queryParameters = (Map) state.get("queryParameters");
626
        this.featureTypeId = state.getString("featureTypeId");
627
        this.attributeNames = state.getList("attributeNames");
628
        List<Expression> filterList = state.getList("filter");
629
        String stateFilter = "";
630
        DataManager dataManager = DALLocator.getDataManager();
631
        if (filterList.size() == 0) {
632
            this.filter = null;
633
        } else if (filterList.size() == 1) {
634
            Expression expression = filterList.get(0);
635
            Evaluator evaluator;
636
            try {
637
                evaluator = dataManager.createFilter(expression);
638
            } catch (InitializeException ex) {
639
                LOGGER.warn("Can't create evaluator", ex);
640
                evaluator = null;
641
            }
642
            this.filter = evaluator;
643
        } else {
644
            AndEvaluator andEvaluator = null;
645
            for (Expression expression : filterList) {
646
                Evaluator evaluator;
647
                try {
648
                    evaluator = dataManager.createFilter(expression);
649

    
650
                    if (andEvaluator == null) {
651
                        andEvaluator = new AndEvaluator(evaluator);
652
                    } else {
653
                        andEvaluator.addEvaluator(evaluator);
654
                    }
655
                } catch (InitializeException ex) {
656
                    LOGGER.warn("Can't create AndEvaluator", ex);//TODO evaluator a null
657
                    break;
658
                }
659
                this.filter = evaluator;
660

    
661
            }
662
        }
663
        this.limit = state.getLong("limit");
664
        this.pageSize = state.getLong("pageSize");
665
                this.storeName = state.getString("storeName");
666
        
667
        
668
        this.order = (FeatureQueryOrder) state.get("order");
669
        List asListGroupByColumns = (List) state.getList("groupByColumns");
670
        if (asListGroupByColumns!=null) {
671
            this.groupByColumns = new ArrayList<>(asListGroupByColumns);
672
        } else {
673
            this.groupByColumns = null;
674
        }
675
        Map asMapAggregateFunctions = (Map) state.getMap("aggregateFunctions");
676
        if (asMapAggregateFunctions!=null) {
677
            this.aggregateFunctions = new HashMap<>(asMapAggregateFunctions);
678
        } else {
679
            this.aggregateFunctions = null;
680
        }
681
        this.extraColumn = (FeatureExtraColumns) state.get("extraColumn");
682

    
683
    
684
    }
685

    
686
    /**
687
     * Register the class on PersistenceManager
688
     *
689
     */
690
    public static void registerPersistent() {
691
        DynStruct definition =
692
            ToolsLocator.getPersistenceManager()
693
            .addDefinition(DefaultFeatureQuery.class,
694
                "DefaultFeatureQuery",
695
                "DefaultFeatureQuery Persistent definition",
696
                null,
697
                null);
698

    
699
        definition.addDynFieldMap("queryParameters")
700
                .setClassOfItems(Object.class)
701
                .setMandatory(true);
702

    
703
        definition.addDynFieldString("featureTypeId").setMandatory(false);
704

    
705
        definition.addDynFieldList("attributeNames")
706
                .setClassOfItems(String.class)
707
                .setMandatory(false);
708

    
709
        definition.addDynFieldList("filter")
710
                .setClassOfItems(Expression.class)
711
                .setMandatory(false);
712

    
713
        definition.addDynFieldObject("order")
714
                .setClassOfValue(FeatureQueryOrder.class)
715
                .setMandatory(false);
716

    
717
        definition.addDynFieldLong("limit").setMandatory(false);
718

    
719
        definition.addDynFieldLong("pageSize").setMandatory(false);
720
        
721
       
722
        definition.addDynFieldList("groupByColumns")
723
                .setClassOfItems(String.class);
724

    
725
        definition.addDynFieldMap("aggregateFunctions")
726
                .setClassOfItems(String.class)
727
                .setClassOfValue(String.class);
728
    
729
        definition.addDynFieldObject("extraColumn")
730
                .setClassOfValue(DefaultFeatureExtraColumns.class);
731
                        
732
                definition.addDynFieldString("storeName").setMandatory(false);
733

    
734
    }
735

    
736
    @Override
737
    public long getLimit() {
738
        return limit;
739
    }
740

    
741
    @Override
742
    public long getPageSize() {
743
        return pageSize;
744
    }
745

    
746
    @Override
747
    public void setLimit(long limit) {
748
        this.limit = limit;
749
    }
750

    
751
    @Override
752
    public void setPageSize(long pageSize) {
753
        this.pageSize = pageSize;
754
    }
755

    
756
    @Override
757
    public String[] getConstantsAttributeNames() {
758
        return (String[])constantsAttributeNames.toArray(new String[constantsAttributeNames.size()]);
759
    }
760

    
761
    @Override
762
    public void setConstantsAttributeNames(String[] constantsAttributeNames) {
763
        this.constantsAttributeNames.clear();
764
        if (constantsAttributeNames != null){
765
            for (int i=0 ; i<constantsAttributeNames.length ; i++){
766
                this.constantsAttributeNames.add(constantsAttributeNames[i]);
767
            }
768
        }
769
    }
770

    
771
    @Override
772
    public void addConstantAttributeName(String attributeName) {
773
        //If the attribute exists finish the method
774
        for (int i=0 ; i<constantsAttributeNames.size() ; i++){
775
            if (constantsAttributeNames.get(i).equals(attributeName)){
776
                return;
777
            }
778
        }
779
        this.constantsAttributeNames.add(attributeName);
780
    }
781

    
782
    @Override
783
    public boolean hasConstantsAttributeNames() {
784
        return !this.constantsAttributeNames.isEmpty();
785
    }
786

    
787
    @Override
788
    public void clearConstantsAttributeNames() {
789
        this.constantsAttributeNames = new ArrayList();
790
    }
791

    
792
  @Override
793
  public boolean isAGroupByColumn(String name) {
794
    for (String columnName : groupByColumns) {
795
      if( StringUtils.equalsIgnoreCase(name, columnName) ) {
796
        return true;
797
      }
798
    }
799
    return false;
800
  }
801

    
802
  @Override
803
  public List<String> getGroupByColumns() {
804
    if( this.groupByColumns == null ) {
805
      this.groupByColumns = new ArrayList<>();
806
    }
807
    return this.groupByColumns;
808
  }
809

    
810
  @Override
811
  public void addAggregate(String funcName, String columnName) {
812
        Map<String, String> aggregateds = this.getAggregateFunctions();
813
        aggregateds.put(columnName, funcName);
814
  }
815

    
816
  @Override
817
  public Map<String, String> getAggregateFunctions() {
818
    if( this.aggregateFunctions == null ) {
819
      this.aggregateFunctions = new HashMap<>();
820
    }
821
    return this.aggregateFunctions;
822
  }
823

    
824
  @Override
825
  public String getAggregate(String name) {    
826
      String fn = this.getAggregateFunctions().get(name);
827
      if( StringUtils.isAlphanumeric(fn) ) {
828
        return fn + "(\""+ name + "\")";
829
      }
830
      return fn;
831
  }
832
  
833
  @Override
834
  public String getAggregate(String tableName, String name) {    
835
      String fn = this.getAggregateFunctions().get(name);
836
      if (!tableName.startsWith("\"")) {
837
         tableName = "\""+tableName+"\"";
838
      }
839
      if( StringUtils.isAlphanumeric(fn) ) {
840
        return fn + "("+tableName+".\""+ name + "\")";
841
      }
842
      return fn;
843
  }
844
  
845
  @Override
846
  public boolean hasAggregateFunctions() {
847
    return this.aggregateFunctions != null && !this.aggregateFunctions.isEmpty();
848
  }
849

    
850
  @Override
851
  public boolean hasGroupByColumns() {
852
    return this.groupByColumns != null && !this.groupByColumns.isEmpty();
853
  }
854

    
855
  @Override
856
  public void copyFrom(FeatureQuery query) {
857
    DefaultFeatureQuery other = (DefaultFeatureQuery) query;
858
    this.queryParameters = new HashMap();
859
    this.queryParameters.putAll(other.queryParameters);
860
    
861
    this.featureTypeId = other.featureTypeId;
862

    
863
    this.attributeNames.clear();
864
    this.attributeNames.addAll(other.attributeNames);
865

    
866
    this.constantsAttributeNames.clear();
867
    this.constantsAttributeNames.addAll(other.constantsAttributeNames);
868

    
869
    this.filter = other.filter;
870

    
871
    this.order.copyFrom(other.order);
872

    
873
    this.limit = other.limit;
874

    
875
    this.pageSize = other.pageSize;
876

    
877
    if( this.groupByColumns!=null && other.groupByColumns!=null ) {
878
      this.groupByColumns.clear();
879
      this.groupByColumns.addAll(other.groupByColumns);
880
    } else if( other.groupByColumns!=null ) {
881
      this.groupByColumns = new ArrayList<>();
882
      this.groupByColumns.addAll(other.groupByColumns);
883
    } else if( this.groupByColumns!=null ) {
884
      this.groupByColumns = null;
885
    }
886
    
887
    if( this.aggregateFunctions!=null && other.aggregateFunctions!=null ) {
888
      this.aggregateFunctions.clear();
889
      this.aggregateFunctions.putAll(other.aggregateFunctions);
890
    } else if( other.aggregateFunctions!=null ) {
891
      this.aggregateFunctions = new HashMap<>(other.aggregateFunctions);
892
    } else if( this.aggregateFunctions!=null ) {
893
      this.aggregateFunctions=null;
894
    }
895
    this.extraColumn.copyFrom(other.extraColumn);
896
    if( other.symbolTable!=null ) {
897
        try {
898
            this.symbolTable = other.symbolTable.clone();
899
        } catch (CloneNotSupportedException ex) {
900
            LOGGER.debug("Can't clone symbol table",ex);
901
        }
902
    }
903
        this.storeName = other.storeName;
904
  }
905

    
906
    @Override
907
    public FeatureExtraColumns getExtraColumn() {
908
        return this.extraColumn;
909
    }
910

    
911
    @Override
912
    public MutableSymbolTable getSymbolTable() {
913
        return symbolTable;
914
    }
915

    
916
    @Override
917
    public void setSymbolTable(MutableSymbolTable symbolTable) {
918
        this.symbolTable = symbolTable;
919
    }
920

    
921
    @Override
922
    public void setVar(String name, Object value) {
923
        if( this.symbolTable==null ) {
924
            this.symbolTable = ExpressionUtils.createSymbolTable();
925
        }
926
        this.symbolTable.setVar(name, value);
927
    }
928

    
929
    
930
}