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

History | View | Annotate | Download (27.7 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.DALLocator;
35
import org.gvsig.fmap.dal.DataManager;
36
import org.gvsig.fmap.dal.DataTypes;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.exception.InitializeException;
39
import org.gvsig.expressionevaluator.ExpressionEvaluator;
40
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
41
import org.gvsig.fmap.dal.feature.FeatureQuery;
42
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44
import org.gvsig.fmap.dal.feature.FeatureType;
45
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
46
import org.gvsig.tools.ToolsLocator;
47
import org.gvsig.tools.dynobject.DynStruct;
48
import org.gvsig.tools.evaluator.AndEvaluator;
49
import org.gvsig.tools.evaluator.Evaluator;
50
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
51
import org.gvsig.tools.persistence.PersistentState;
52
import org.gvsig.tools.persistence.exception.PersistenceException;
53
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
55
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
56

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

    
91
    public static final String SCALE_PARAM_NAME = "Scale";
92

    
93
    private Map<String,Object> queryParameters = new HashMap();
94

    
95
    private String featureTypeId = null;
96

    
97
    private List<String> attributeNames = new ArrayList();
98

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

    
101
    private Evaluator filter;
102

    
103
    private FeatureQueryOrder order = new DefaultFeatureQueryOrder();
104

    
105
    private long limit;
106

    
107
    private long pageSize;
108

    
109
    private List<String> groupByColumns;
110
    
111
    private Map<String,String> aggregateFunctions;
112
    
113
    private FeatureExtraColumns extraColumn = new DefaultFeatureExtraColumns();
114
    
115
    /**
116
     * Creates a FeatureQuery which will load all available Features of a type.
117
     *
118
     */
119
    public DefaultFeatureQuery() {
120
        super();
121
    }
122

    
123
    /**
124
     * Creates a FeatureQuery which will load all available Features of a type.
125
     *
126
     * @param featureType
127
     *            the type of Features of the query
128
     */
129
    public DefaultFeatureQuery(FeatureType featureType) {
130
        super();
131
        this.setFeatureType(featureType);
132
    }
133

    
134
    /**
135
     * Creates a FeatureQuery with the type of features, a filter and the order
136
     * for the FeatureCollection.
137
     *
138
     * @param featureType
139
     *            the type of Features of the query
140
     * @param filter
141
     *            based on the properties of the Features
142
     */
143
    public DefaultFeatureQuery(FeatureType featureType, Evaluator filter) {
144
        super();
145
        this.setFeatureType(featureType);
146
        this.filter = filter;
147
    }
148

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

    
167
    /**
168
     * Creates a FeatureQuery which will load a list of attribute names of all
169
     * available Features.
170
     *
171
     * @param attributeNames
172
     *            the list of attribute names to load
173
     */
174
    public DefaultFeatureQuery(String[] attributeNames) {
175
        super();
176
        setAttributeNames(attributeNames);
177
    }
178

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

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

    
212
    @Override
213
    public double getScale() {
214
        Double scale = (Double) this.getQueryParameter(SCALE_PARAM_NAME);
215
        if (scale == null) {
216
            return 0;
217
        }
218
        return scale;
219
    }
220

    
221
    @Override
222
    public void setScale(double scale) {
223
        this.setQueryParameter(SCALE_PARAM_NAME, scale);
224
    }
225

    
226
    @Override
227
    public Object getQueryParameter(String name) {
228
        return queryParameters.get(name);
229
    }
230

    
231
    @Override
232
    public void setQueryParameter(String name, Object value) {
233
        queryParameters.put(name, value);
234
    }
235

    
236
    @Override
237
    public void setFeatureType(FeatureType featureType) {
238
        this.featureTypeId = featureType.getId();
239
    }
240

    
241
    @Override
242
    public String[] getAttributeNames() {
243
        if (this.hasExtraColumnDeclaredAsGroupByField()) {
244
            this.retrievesAllAttributes();
245
        }
246
        return (String[])attributeNames.toArray(new String[attributeNames.size()]);
247
    }
248
    
249
    private boolean hasExtraColumnDeclaredAsGroupByField() {
250
        // indica si un campo de agrupaciones es una columna calculada
251
        if (this.hasGroupByColumns()) {
252
            for (String groupByColumn : groupByColumns) {
253
                if (this.extraColumn.get(groupByColumn)!=null) {
254
                    return true;
255
                }
256
            }
257
        }
258
        return false;
259
    }
260

    
261
    @Override
262
    public void setAttributeNames(String[] attributeNames) {
263
        this.attributeNames.clear();
264
        if (attributeNames != null){
265
            for (int i=0 ; i<attributeNames.length ; i++){
266
                this.attributeNames.add(attributeNames[i]);
267
            }
268
        }
269
    }
270

    
271
    @Override
272
    public void retrievesAllAttributes() {
273
        this.attributeNames.clear();
274
    } 
275
    
276
    @Override
277
    public void addAttributeName(String attributeName){
278
        //If the attribute exists finish the method
279
        for (int i=0 ; i<attributeNames.size() ; i++){
280
            if (attributeNames.get(i).equals(attributeName)){
281
                return;
282
            }
283
        }
284
        this.attributeNames.add(attributeName);
285
    }
286

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

    
338
    @Override
339
    public boolean hasAttributeNames() {
340
        if (hasExtraColumnDeclaredAsGroupByField()) {
341
            return true;
342
        }
343
        return !this.attributeNames.isEmpty();
344
    }
345

    
346
    @Override
347
    public void clearAttributeNames() {
348
        this.attributeNames = new ArrayList();
349
    }
350

    
351
    @Override
352
    public Evaluator getFilter() {
353
        return filter;
354
    }
355

    
356
    @Override
357
    public Expression getExpressionFilter() {
358
      if( this.filter instanceof ExpressionEvaluator ) {
359
        return ((ExpressionEvaluator)this.filter).toExpression();
360
      }
361
      return null;
362
    }
363

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

    
374
   @Override
375
    public void setFilter(String filter) {
376
        if( StringUtils.isEmpty(filter) ) {
377
            this.clearFilter();
378
            return;
379
        }
380
        try {
381
            this.setFilter(ExpressionUtils.createExpression(filter));
382
        } catch (Exception ex) {
383
            throw new RuntimeException("Can't create filter from '"+filter+"'",ex);
384
        }
385
    }
386

    
387
    @Override
388
    public void setFilter(Evaluator filter) {
389
        if( filter == null ) {
390
            this.clearFilter();
391
            return;
392
        }        
393
        this.filter = filter;
394
        addFilterAttributes(filter);
395
    }
396

    
397
    @Override
398
    public void addFilter(String filter) {
399
        if( StringUtils.isEmpty(filter) ) {
400
            return;
401
        }
402
        this.addFilter(ExpressionUtils.createExpression(filter));
403
    }
404

    
405
    @Override
406
    public void addFilter(Expression filter) {
407
        Evaluator x = new DefaultFeatureExpressionEvaluator(filter);
408
        this.addFilter(x);
409
    }
410

    
411
    @Override
412
    public void addFilter(Evaluator evaluator) {
413
        if (evaluator == null) {
414
            return;
415
        }
416
        if (this.filter == null) {
417
            this.filter = evaluator;
418
        } else {
419
            if (this.filter instanceof AndEvaluator) {
420
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
421
            } else {
422
                this.filter = new AndEvaluator(this.filter);
423
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
424
            }
425
        }
426
        addFilterAttributes(evaluator);
427
    }
428

    
429
    @Override
430
    public void clearFilter() {
431
      this.filter = null;
432
    }
433

    
434
    private void addFilterAttributes(Evaluator evaluator){
435
        if (evaluator != null){
436
            EvaluatorFieldsInfo fieldsInfo = evaluator.getFieldsInfo();
437
            if (fieldsInfo == null){
438
                // FieldsInfo is not available in this evaluator
439
                return;
440
            }
441
            String[] fieldNames = fieldsInfo.getFieldNames();
442
            if (fieldNames== null){
443
                // fieldNames is not available in this evaluator
444
                return;
445
            }
446

    
447
            for (int i=0 ; i<fieldNames.length ; i++){
448
                addAttributeName(fieldNames[i]);
449
            }
450
        }
451
    }
452

    
453
    @Override
454
    public FeatureQueryOrder getOrder() {
455
        return order;
456
    }
457

    
458
    @Override
459
    public void setOrder(FeatureQueryOrder order) {
460
        if(order == null){
461
            this.order = new DefaultFeatureQueryOrder();
462
        } else {
463
            this.order = order;
464
        }
465
    }
466

    
467
    @Override
468
    public boolean hasFilter() {
469
        return this.filter != null;
470
    }
471

    
472
    @Override
473
    public boolean hasOrder() {
474
        return this.order != null && this.order.size() > 0;
475
    }
476

    
477
    @Override
478
    public Object clone() throws CloneNotSupportedException {
479
        DefaultFeatureQuery clone = (DefaultFeatureQuery) super.clone();
480

    
481
        // Clone attribute names array
482
        if (attributeNames != null) {
483
            clone.attributeNames = new ArrayList();
484
            for (int i=0 ; i<attributeNames.size() ; i++){
485
                clone.attributeNames.add(attributeNames.get(i));
486
            }
487
        }
488

    
489
        // Clone order
490
        if (order != null) {
491
            clone.order = (FeatureQueryOrder) order.clone();
492
        }
493
        
494
        clone.extraColumn = extraColumn.getCopy();
495
        
496
        if( this.filter instanceof ExpressionEvaluator ) {
497
            Expression exp = ((ExpressionEvaluator)this.filter).toExpression();
498
            clone.filter =  new DefaultFeatureExpressionEvaluator(exp);
499
        }
500
        
501
        if (groupByColumns!=null) {
502
            clone.groupByColumns = new ArrayList<String>();
503
            for (String value : groupByColumns) {
504
                clone.groupByColumns.add(value);
505
            }
506
        } else {
507
            clone.groupByColumns = null;
508
        }
509
                
510
                
511
        if (aggregateFunctions!=null) {
512
            clone.aggregateFunctions = new HashMap<String, String>();
513
            for (String key : aggregateFunctions.keySet()) {
514
                clone.aggregateFunctions.put(key, aggregateFunctions.get(key));
515
            }
516
        } else {
517
            clone.aggregateFunctions = null;
518
        }
519
        
520
        
521
        return clone;
522
    }
523

    
524
    @Override
525
    public FeatureQuery getCopy() {
526
        try {
527
            return (FeatureQuery) clone();
528
        } catch (CloneNotSupportedException e) {
529
            // TODO Auto-generated catch block
530
            e.printStackTrace();
531
            return null;
532
        }
533
        // DefaultFeatureQuery aCopy = new DefaultFeatureQuery();
534
        //
535
        // aCopy.featureTypeId = this.featureTypeId;
536
        //
537
        // if (this.attributeNames != null) {
538
        // aCopy.attributeNames = (String[]) Arrays
539
        // .asList(this.attributeNames).toArray(new String[0]);
540
        // }
541
        //
542
        // aCopy.filter = this.filter;
543
        //
544
        // if (this.order != null) {
545
        // aCopy.order = this.order.getCopy();
546
        // }
547
        //
548
        // return aCopy;
549
    }
550

    
551
    @Override
552
    public String getFeatureTypeId() {
553
        return featureTypeId;
554
    }
555

    
556
    @Override
557
    public void setFeatureTypeId(String featureTypeId) {
558
        this.featureTypeId = featureTypeId;
559
    }
560

    
561
    @Override
562
    public void saveToState(PersistentState state) throws PersistenceException {
563
        // FIXME: falta por terminar de implementar
564
        state.set("queryParameters", this.queryParameters);
565
        state.set("featureTypeId", this.featureTypeId);
566
        state.set("attributeNames", this.attributeNames);
567
        
568
        ArrayList<Expression> filterList = new ArrayList<>();
569
        if (this.filter instanceof DefaultFeatureExpressionEvaluator) {
570
            DefaultFeatureExpressionEvaluator filterExpression = (DefaultFeatureExpressionEvaluator) this.filter;
571
           filterList.add(filterExpression.toExpression());
572
        } else if (this.filter instanceof AndEvaluator) {
573
            AndEvaluator filterAnd = (AndEvaluator) this.filter;
574
            List<Evaluator> evaluators = filterAnd.getEvaluators();
575
            for (Evaluator evaluator : evaluators) {
576
                if (evaluator instanceof DefaultFeatureExpressionEvaluator) {
577
                    DefaultFeatureExpressionEvaluator expressionEvaluator = (DefaultFeatureExpressionEvaluator) evaluator;
578
                    filterList.add(expressionEvaluator.toExpression());
579
                } else {
580
                    filterList.clear();
581
                    LOGGER.warn(StringUtils.join("Filters in this FeatureQuery will not persist:", this.toString()));
582
                    break;
583
                }
584
            }
585
        } else {
586
            filterList.clear();
587
            LOGGER.warn(StringUtils.join("Filters in this FeatureQuery will not persist:", this.toString()));
588
        }
589
        
590
        state.set("filter", filterList);
591
        state.set("limit", this.limit);
592
        state.set("pageSize", this.pageSize);
593
        
594
        state.set("order", this.order);
595
        state.set("groupByColumns", this.groupByColumns);
596
        state.set("aggregateFunctions", this.aggregateFunctions);
597
        state.set("extraColumn", this.extraColumn);
598
        
599

    
600
    }
601
    
602

    
603
    @Override
604
    public void loadFromState(PersistentState state) throws PersistenceException {
605
        // FIXME: falta por terminar de implementar
606
        this.queryParameters = (Map) state.get("queryParameters");
607
        this.featureTypeId = state.getString("featureTypeId");
608
        this.attributeNames = state.getList("attributeNames");
609
        List<Expression> filterList = state.getList("filter");
610
        String stateFilter = "";
611
        DataManager dataManager = DALLocator.getDataManager();
612
        if (filterList.size() == 0) {
613
            this.filter = null;
614
        } else if (filterList.size() == 1) {
615
            Expression expression = filterList.get(0);
616
            Evaluator evaluator;
617
            try {
618
                evaluator = dataManager.createFilter(expression);
619
            } catch (InitializeException ex) {
620
                LOGGER.warn("Can't create evaluator", ex);
621
                evaluator = null;
622
            }
623
            this.filter = evaluator;
624
        } else {
625
            AndEvaluator andEvaluator = null;
626
            for (Expression expression : filterList) {
627
                Evaluator evaluator;
628
                try {
629
                    evaluator = dataManager.createFilter(expression);
630

    
631
                    if (andEvaluator == null) {
632
                        andEvaluator = new AndEvaluator(evaluator);
633
                    } else {
634
                        andEvaluator.addEvaluator(evaluator);
635
                    }
636
                } catch (InitializeException ex) {
637
                    LOGGER.warn("Can't create AndEvaluator", ex);//TODO evaluator a null
638
                    break;
639
                }
640
                this.filter = evaluator;
641

    
642
            }
643
        }
644
        this.limit = state.getLong("limit");
645
        this.pageSize = state.getLong("pageSize");
646
        
647
        
648
        this.order = (FeatureQueryOrder) state.get("order");
649
        List asListGroupByColumns = (List) state.getList("groupByColumns");
650
        if (asListGroupByColumns!=null) {
651
            this.groupByColumns = new ArrayList<>(asListGroupByColumns);
652
        } else {
653
            this.groupByColumns = null;
654
        }
655
        Map asMapAggregateFunctions = (Map) state.getMap("aggregateFunctions");
656
        if (asMapAggregateFunctions!=null) {
657
            this.aggregateFunctions = new HashMap<>(asMapAggregateFunctions);
658
        } else {
659
            this.aggregateFunctions = null;
660
        }
661
        this.extraColumn = (FeatureExtraColumns) state.get("extraColumn");
662

    
663
    
664
    }
665

    
666
    /**
667
     * Register the class on PersistenceManager
668
     *
669
     */
670
    public static void registerPersistent() {
671
        DynStruct definition =
672
            ToolsLocator.getPersistenceManager()
673
            .addDefinition(DefaultFeatureQuery.class,
674
                "DefaultFeatureQuery",
675
                "DefaultFeatureQuery Persistent definition",
676
                null,
677
                null);
678

    
679
        definition.addDynFieldMap("queryParameters")
680
                .setClassOfItems(Object.class)
681
                .setMandatory(true);
682

    
683
        definition.addDynFieldString("featureTypeId").setMandatory(false);
684

    
685
        definition.addDynFieldList("attributeNames")
686
                .setClassOfItems(String.class)
687
                .setMandatory(false);
688

    
689
        definition.addDynFieldList("filter")
690
                .setClassOfItems(Expression.class)
691
                .setMandatory(false);
692

    
693
        definition.addDynFieldObject("order")
694
                .setClassOfValue(FeatureQueryOrder.class)
695
                .setMandatory(false);
696

    
697
        definition.addDynFieldLong("limit").setMandatory(false);
698

    
699
        definition.addDynFieldLong("pageSize").setMandatory(false);
700
        
701
       
702
        definition.addDynFieldList("groupByColumns")
703
                .setClassOfItems(String.class);
704

    
705
        definition.addDynFieldMap("aggregateFunctions")
706
                .setClassOfItems(String.class)
707
                .setClassOfValue(String.class);
708
    
709
        definition.addDynFieldObject("extraColumn")
710
                .setClassOfValue(DefaultFeatureExtraColumns.class);
711
                        
712

    
713
    }
714

    
715
    @Override
716
    public long getLimit() {
717
        return limit;
718
    }
719

    
720
    @Override
721
    public long getPageSize() {
722
        return pageSize;
723
    }
724

    
725
    @Override
726
    public void setLimit(long limit) {
727
        this.limit = limit;
728
    }
729

    
730
    @Override
731
    public void setPageSize(long pageSize) {
732
        this.pageSize = pageSize;
733
    }
734

    
735
    @Override
736
    public String[] getConstantsAttributeNames() {
737
        return (String[])constantsAttributeNames.toArray(new String[constantsAttributeNames.size()]);
738
    }
739

    
740
    @Override
741
    public void setConstantsAttributeNames(String[] constantsAttributeNames) {
742
        this.constantsAttributeNames.clear();
743
        if (constantsAttributeNames != null){
744
            for (int i=0 ; i<constantsAttributeNames.length ; i++){
745
                this.constantsAttributeNames.add(constantsAttributeNames[i]);
746
            }
747
        }
748
    }
749

    
750
    @Override
751
    public void addConstantAttributeName(String attributeName) {
752
        //If the attribute exists finish the method
753
        for (int i=0 ; i<constantsAttributeNames.size() ; i++){
754
            if (constantsAttributeNames.get(i).equals(attributeName)){
755
                return;
756
            }
757
        }
758
        this.constantsAttributeNames.add(attributeName);
759
    }
760

    
761
    @Override
762
    public boolean hasConstantsAttributeNames() {
763
        return !this.constantsAttributeNames.isEmpty();
764
    }
765

    
766
    @Override
767
    public void clearConstantsAttributeNames() {
768
        this.constantsAttributeNames = new ArrayList();
769
    }
770

    
771
  @Override
772
  public boolean isAGroupByColumn(String name) {
773
    for (String columnName : groupByColumns) {
774
      if( StringUtils.equalsIgnoreCase(name, columnName) ) {
775
        return true;
776
      }
777
    }
778
    return false;
779
  }
780

    
781
  @Override
782
  public List<String> getGroupByColumns() {
783
    if( this.groupByColumns == null ) {
784
      this.groupByColumns = new ArrayList<>();
785
    }
786
    return this.groupByColumns;
787
  }
788

    
789
  @Override
790
  public Map<String, String> getAggregateFunctions() {
791
    if( this.aggregateFunctions == null ) {
792
      this.aggregateFunctions = new HashMap<>();
793
    }
794
    return this.aggregateFunctions;
795
  }
796

    
797
  @Override
798
  public String getAggregate(String name) {    
799
      String fn = this.getAggregateFunctions().get(name);
800
      if( StringUtils.isAlphanumeric(fn) ) {
801
        return fn + "(\""+ name + "\")";
802
      }
803
      return fn;
804
  }
805
  
806
  @Override
807
  public String getAggregate(String tableName, String name) {    
808
      String fn = this.getAggregateFunctions().get(name);
809
      if (!tableName.startsWith("\"")) {
810
         tableName = "\""+tableName+"\"";
811
      }
812
      if( StringUtils.isAlphanumeric(fn) ) {
813
        return fn + "("+tableName+".\""+ name + "\")";
814
      }
815
      return fn;
816
  }
817
  
818
  @Override
819
  public boolean hasAggregateFunctions() {
820
    return this.aggregateFunctions != null && !this.aggregateFunctions.isEmpty();
821
  }
822

    
823
  @Override
824
  public boolean hasGroupByColumns() {
825
    return this.groupByColumns != null && !this.groupByColumns.isEmpty();
826
  }
827

    
828
  @Override
829
  public void copyFrom(FeatureQuery query) {
830
    DefaultFeatureQuery other = (DefaultFeatureQuery) query;
831
    this.queryParameters = new HashMap();
832
    this.queryParameters.putAll(other.queryParameters);
833
    
834
    this.featureTypeId = other.featureTypeId;
835

    
836
    this.attributeNames.clear();
837
    this.attributeNames.addAll(other.attributeNames);
838

    
839
    this.constantsAttributeNames.clear();
840
    this.constantsAttributeNames.addAll(other.constantsAttributeNames);
841

    
842
    this.filter = other.filter;
843

    
844
    this.order.copyFrom(other.order);
845

    
846
    this.limit = other.limit;
847

    
848
    this.pageSize = other.pageSize;
849

    
850
    if( this.groupByColumns!=null && other.groupByColumns!=null ) {
851
      this.groupByColumns.clear();
852
      this.groupByColumns.addAll(other.groupByColumns);
853
    } else if( other.groupByColumns!=null ) {
854
      this.groupByColumns = new ArrayList<>();
855
      this.groupByColumns.addAll(other.groupByColumns);
856
    } else if( this.groupByColumns!=null ) {
857
      this.groupByColumns = null;
858
    }
859
    
860
    if( this.aggregateFunctions!=null && other.aggregateFunctions!=null ) {
861
      this.aggregateFunctions.clear();
862
      this.aggregateFunctions.putAll(other.aggregateFunctions);
863
    } else if( other.aggregateFunctions!=null ) {
864
      this.aggregateFunctions = new HashMap<>(other.aggregateFunctions);
865
    } else if( this.aggregateFunctions!=null ) {
866
      this.aggregateFunctions=null;
867
    }
868
    this.extraColumn.copyFrom(other.extraColumn);
869
  }
870

    
871
  public FeatureExtraColumns getExtraColumn() {
872
      return this.extraColumn;
873
  }
874
  
875
}