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

History | View | Annotate | Download (29.9 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
    
119
    private String storeName;
120
    
121
    private boolean useSubquery;
122
    
123
    /**
124
     * Creates a FeatureQuery which will load all available Features of a type.
125
     *
126
     */
127
    public DefaultFeatureQuery() {
128
        super();
129
        this.useSubquery = true; // true for backwards compatibility. 
130
    }
131
        
132
    public DefaultFeatureQuery(String storeName) {
133
        this();
134
        this.storeName = storeName;
135
                
136
    }
137

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

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

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

    
183
    /**
184
     * Creates a FeatureQuery which will load a list of attribute names of all
185
     * available Features.
186
     *
187
     * @param attributeNames
188
     *            the list of attribute names to load
189
     */
190
    public DefaultFeatureQuery(String[] attributeNames) {
191
        this();
192
        setAttributeNames(attributeNames);
193
    }
194

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

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

    
229
    @Override
230
    public double getScale() {
231
        Double scale = (Double) this.getQueryParameter(SCALE_PARAM_NAME);
232
        if (scale == null) {
233
            return 0;
234
        }
235
        return scale;
236
    }
237

    
238
    @Override
239
    public void setScale(double scale) {
240
        this.setQueryParameter(SCALE_PARAM_NAME, scale);
241
    }
242

    
243
    @Override
244
    public Object getQueryParameter(String name) {
245
        return queryParameters.get(name);
246
    }
247

    
248
    @Override
249
    public void setQueryParameter(String name, Object value) {
250
        queryParameters.put(name, value);
251
    }
252

    
253
    @Override
254
    public void setFeatureType(FeatureType featureType) {
255
        this.featureTypeId = featureType.getId();
256
    }
257

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

    
278
    @Override
279
    public void setAttributeNames(String[] attributeNames) {
280
        this.attributeNames.clear();
281
        if (attributeNames != null){
282
            for (int i=0 ; i<attributeNames.length ; i++){
283
                this.attributeNames.add(attributeNames[i]);
284
            }
285
        }
286
    }
287

    
288
    @Override
289
    public void retrievesAllAttributes() {
290
        this.attributeNames.clear();
291
    } 
292
    
293
    @Override
294
    public void addAttributeName(String attributeName){
295
        //If the attribute exists finish the method
296
        for (int i=0 ; i<attributeNames.size() ; i++){
297
            if (attributeNames.get(i).equals(attributeName)){
298
                return;
299
            }
300
        }
301
        this.attributeNames.add(attributeName);
302
    }
303

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

    
355
    @Override
356
    public boolean hasAttributeNames() {
357
        if (hasExtraColumnDeclaredAsGroupByField()) {
358
            return true;
359
        }
360
        return !this.attributeNames.isEmpty();
361
    }
362

    
363
    @Override
364
    public void clearAttributeNames() {
365
        this.attributeNames = new ArrayList();
366
    }
367

    
368
    @Override
369
    public Evaluator getFilter() {
370
      if( this.filter instanceof ExpressionEvaluator ) {
371
        ExpressionEvaluator ee = (ExpressionEvaluator) this.filter;
372
        ee.addSymbolTable(symbolTable);
373
      }
374
      return filter;
375
    }
376

    
377
    @Override
378
    public Expression getExpressionFilter() {
379
      if( this.filter instanceof ExpressionEvaluator ) {
380
        ExpressionEvaluator ee = (ExpressionEvaluator) this.filter;
381
        ee.addSymbolTable(symbolTable);
382
        return ee.toExpression();
383
      }
384
      return null;
385
    }
386

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

    
397
   @Override
398
    public void setFilter(String filter) {
399
        if( StringUtils.isEmpty(filter) ) {
400
            this.clearFilter();
401
            return;
402
        }
403
        try {
404
            this.setFilter(ExpressionUtils.createExpression(filter));
405
        } catch (Exception ex) {
406
            throw new RuntimeException("Can't create filter from '"+filter+"'",ex);
407
        }
408
    }
409

    
410
    @Override
411
    public void setFilter(Evaluator filter) {
412
        if( filter == null ) {
413
            this.clearFilter();
414
            return;
415
        }        
416
        this.filter = filter;
417
        addFilterAttributes(filter);
418
    }
419

    
420
    @Override
421
    public void addFilter(String filter) {
422
        if( StringUtils.isEmpty(filter) ) {
423
            return;
424
        }
425
        this.addFilter(ExpressionUtils.createExpression(filter));
426
    }
427

    
428
    @Override
429
    public void addFilter(Expression filter) {
430
        Evaluator x = new DefaultFeatureExpressionEvaluator(filter);
431
        this.addFilter(x);
432
    }
433

    
434
    @Override
435
    public void addFilter(Evaluator evaluator) {
436
        if (evaluator == null) {
437
            return;
438
        }
439
        if (this.filter == null) {
440
            this.filter = evaluator;
441
        } else {
442
            if (this.filter instanceof AndEvaluator) {
443
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
444
            } else {
445
                this.filter = new AndEvaluator(this.filter);
446
                ((AndEvaluator) this.filter).addEvaluator(evaluator);
447
            }
448
        }
449
        addFilterAttributes(evaluator);
450
    }
451

    
452
    @Override
453
    public void clearFilter() {
454
      this.filter = null;
455
    }
456

    
457
    private void addFilterAttributes(Evaluator evaluator){
458
        if (evaluator != null){
459
            EvaluatorFieldsInfo fieldsInfo = evaluator.getFieldsInfo();
460
            if (fieldsInfo == null){
461
                // FieldsInfo is not available in this evaluator
462
                return;
463
            }
464
            String[] fieldNames = fieldsInfo.getFieldNames();
465
            if (fieldNames== null){
466
                // fieldNames is not available in this evaluator
467
                return;
468
            }
469

    
470
            for (int i=0 ; i<fieldNames.length ; i++){
471
                addAttributeName(fieldNames[i]);
472
            }
473
        }
474
    }
475

    
476
    @Override
477
    public FeatureQueryOrder getOrder() {
478
        return order;
479
    }
480

    
481
    @Override
482
    public void setOrder(FeatureQueryOrder order) {
483
        if(order == null){
484
            this.order = new DefaultFeatureQueryOrder();
485
        } else {
486
            this.order = order;
487
        }
488
    }
489

    
490
    @Override
491
    public boolean hasFilter() {
492
        return this.filter != null;
493
    }
494

    
495
    @Override
496
    public boolean hasOrder() {
497
        return this.order != null && this.order.size() > 0;
498
    }
499

    
500
    @Override
501
    public Object clone() throws CloneNotSupportedException {
502
        DefaultFeatureQuery clone = (DefaultFeatureQuery) super.clone();
503

    
504
        // Clone attribute names array
505
        if (attributeNames != null) {
506
            clone.attributeNames = new ArrayList();
507
            for (int i=0 ; i<attributeNames.size() ; i++){
508
                clone.attributeNames.add(attributeNames.get(i));
509
            }
510
        }
511

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

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

    
575
    @Override
576
    public String getFeatureTypeId() {
577
        return featureTypeId;
578
    }
579

    
580
    @Override
581
    public void setFeatureTypeId(String featureTypeId) {
582
        this.featureTypeId = featureTypeId;
583
    }
584

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

    
626
    }
627
    
628

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

    
657
                    if (andEvaluator == null) {
658
                        andEvaluator = new AndEvaluator(evaluator);
659
                    } else {
660
                        andEvaluator.addEvaluator(evaluator);
661
                    }
662
                } catch (InitializeException ex) {
663
                    LOGGER.warn("Can't create AndEvaluator", ex);//TODO evaluator a null
664
                    break;
665
                }
666
                this.filter = evaluator;
667

    
668
            }
669
        }
670
        this.limit = state.getLong("limit");
671
        this.pageSize = state.getLong("pageSize");
672
        this.useSubquery = state.getBoolean("useSubquery",true);
673
        this.storeName = state.getString("storeName");
674
        
675
        
676
        this.order = (FeatureQueryOrder) state.get("order");
677
        List asListGroupByColumns = (List) state.getList("groupByColumns");
678
        if (asListGroupByColumns!=null) {
679
            this.groupByColumns = new ArrayList<>(asListGroupByColumns);
680
        } else {
681
            this.groupByColumns = null;
682
        }
683
        Map asMapAggregateFunctions = (Map) state.getMap("aggregateFunctions");
684
        if (asMapAggregateFunctions!=null) {
685
            this.aggregateFunctions = new HashMap<>(asMapAggregateFunctions);
686
        } else {
687
            this.aggregateFunctions = null;
688
        }
689
        this.extraColumn = (FeatureExtraColumns) state.get("extraColumn");
690

    
691
    
692
    }
693

    
694
    /**
695
     * Register the class on PersistenceManager
696
     *
697
     */
698
    public static void registerPersistent() {
699
        DynStruct definition =
700
            ToolsLocator.getPersistenceManager()
701
            .addDefinition(DefaultFeatureQuery.class,
702
                "DefaultFeatureQuery",
703
                "DefaultFeatureQuery Persistent definition",
704
                null,
705
                null);
706

    
707
        definition.addDynFieldMap("queryParameters")
708
                .setClassOfItems(Object.class)
709
                .setMandatory(true);
710

    
711
        definition.addDynFieldString("featureTypeId").setMandatory(false);
712

    
713
        definition.addDynFieldList("attributeNames")
714
                .setClassOfItems(String.class)
715
                .setMandatory(false);
716

    
717
        definition.addDynFieldList("filter")
718
                .setClassOfItems(Expression.class)
719
                .setMandatory(false);
720

    
721
        definition.addDynFieldObject("order")
722
                .setClassOfValue(FeatureQueryOrder.class)
723
                .setMandatory(false);
724

    
725
        definition.addDynFieldLong("limit").setMandatory(false);
726

    
727
        definition.addDynFieldLong("pageSize").setMandatory(false);
728
        
729
        definition.addDynFieldBoolean("useSubquery").setMandatory(false);
730
       
731
        definition.addDynFieldList("groupByColumns")
732
                .setClassOfItems(String.class);
733

    
734
        definition.addDynFieldMap("aggregateFunctions")
735
                .setClassOfItems(String.class)
736
                .setClassOfValue(String.class);
737
    
738
        definition.addDynFieldObject("extraColumn")
739
                .setClassOfValue(DefaultFeatureExtraColumns.class);
740
                        
741
                definition.addDynFieldString("storeName").setMandatory(false);
742

    
743
    }
744

    
745
    @Override
746
    public long getLimit() {
747
        return limit;
748
    }
749

    
750
    @Override
751
    public long getPageSize() {
752
        return pageSize;
753
    }
754

    
755
    @Override
756
    public void setLimit(long limit) {
757
        this.limit = limit;
758
    }
759

    
760
    @Override
761
    public void setPageSize(long pageSize) {
762
        this.pageSize = pageSize;
763
    }
764

    
765
    @Override
766
    public String[] getConstantsAttributeNames() {
767
        return (String[])constantsAttributeNames.toArray(new String[constantsAttributeNames.size()]);
768
    }
769

    
770
    @Override
771
    public void setConstantsAttributeNames(String[] constantsAttributeNames) {
772
        this.constantsAttributeNames.clear();
773
        if (constantsAttributeNames != null){
774
            for (int i=0 ; i<constantsAttributeNames.length ; i++){
775
                this.constantsAttributeNames.add(constantsAttributeNames[i]);
776
            }
777
        }
778
    }
779

    
780
    @Override
781
    public void addConstantAttributeName(String attributeName) {
782
        //If the attribute exists finish the method
783
        for (int i=0 ; i<constantsAttributeNames.size() ; i++){
784
            if (constantsAttributeNames.get(i).equals(attributeName)){
785
                return;
786
            }
787
        }
788
        this.constantsAttributeNames.add(attributeName);
789
    }
790

    
791
    @Override
792
    public boolean hasConstantsAttributeNames() {
793
        return !this.constantsAttributeNames.isEmpty();
794
    }
795

    
796
    @Override
797
    public void clearConstantsAttributeNames() {
798
        this.constantsAttributeNames = new ArrayList();
799
    }
800

    
801
  @Override
802
  public boolean isAGroupByColumn(String name) {
803
    for (String columnName : groupByColumns) {
804
      if( StringUtils.equalsIgnoreCase(name, columnName) ) {
805
        return true;
806
      }
807
    }
808
    return false;
809
  }
810

    
811
  @Override
812
  public List<String> getGroupByColumns() {
813
    if( this.groupByColumns == null ) {
814
      this.groupByColumns = new ArrayList<>();
815
    }
816
    return this.groupByColumns;
817
  }
818

    
819
  @Override
820
  public void addAggregate(String funcName, String columnName) {
821
        Map<String, String> aggregateds = this.getAggregateFunctions();
822
        aggregateds.put(columnName, funcName);
823
  }
824

    
825
  @Override
826
  public Map<String, String> getAggregateFunctions() {
827
    if( this.aggregateFunctions == null ) {
828
      this.aggregateFunctions = new HashMap<>();
829
    }
830
    return this.aggregateFunctions;
831
  }
832

    
833
  @Override
834
  public String getAggregate(String name) {    
835
      String fn = this.getAggregateFunctions().get(name);
836
      if( StringUtils.isAlphanumeric(fn) ) {
837
        return fn + "(\""+ name + "\")";
838
      }
839
      return fn;
840
  }
841
  
842
  @Override
843
  public String getAggregate(String tableName, String name) {    
844
      String fn = this.getAggregateFunctions().get(name);
845
      if (!tableName.startsWith("\"")) {
846
         tableName = "\""+tableName+"\"";
847
      }
848
      if( StringUtils.isAlphanumeric(fn) ) {
849
        return fn + "("+tableName+".\""+ name + "\")";
850
      }
851
      return fn;
852
  }
853
  
854
  @Override
855
  public boolean hasAggregateFunctions() {
856
    return this.aggregateFunctions != null && !this.aggregateFunctions.isEmpty();
857
  }
858

    
859
  @Override
860
  public boolean hasGroupByColumns() {
861
    return this.groupByColumns != null && !this.groupByColumns.isEmpty();
862
  }
863

    
864
  @Override
865
  public void copyFrom(FeatureQuery query) {
866
    DefaultFeatureQuery other = (DefaultFeatureQuery) query;
867
    this.queryParameters = new HashMap();
868
    this.queryParameters.putAll(other.queryParameters);
869
    
870
    this.featureTypeId = other.featureTypeId;
871

    
872
    this.attributeNames.clear();
873
    this.attributeNames.addAll(other.attributeNames);
874

    
875
    this.constantsAttributeNames.clear();
876
    this.constantsAttributeNames.addAll(other.constantsAttributeNames);
877

    
878
    this.filter = other.filter;
879

    
880
    this.order.copyFrom(other.order);
881

    
882
    this.limit = other.limit;
883

    
884
    this.pageSize = other.pageSize;
885
    this.useSubquery = other.useSubquery;
886

    
887
    if( this.groupByColumns!=null && other.groupByColumns!=null ) {
888
      this.groupByColumns.clear();
889
      this.groupByColumns.addAll(other.groupByColumns);
890
    } else if( other.groupByColumns!=null ) {
891
      this.groupByColumns = new ArrayList<>();
892
      this.groupByColumns.addAll(other.groupByColumns);
893
    } else if( this.groupByColumns!=null ) {
894
      this.groupByColumns = null;
895
    }
896
    
897
    if( this.aggregateFunctions!=null && other.aggregateFunctions!=null ) {
898
      this.aggregateFunctions.clear();
899
      this.aggregateFunctions.putAll(other.aggregateFunctions);
900
    } else if( other.aggregateFunctions!=null ) {
901
      this.aggregateFunctions = new HashMap<>(other.aggregateFunctions);
902
    } else if( this.aggregateFunctions!=null ) {
903
      this.aggregateFunctions=null;
904
    }
905
    this.extraColumn.copyFrom(other.extraColumn);
906
    if( other.symbolTable!=null ) {
907
        try {
908
            this.symbolTable = other.symbolTable.clone();
909
        } catch (CloneNotSupportedException ex) {
910
            LOGGER.debug("Can't clone symbol table",ex);
911
        }
912
    }
913
        this.storeName = other.storeName;
914
  }
915

    
916
    @Override
917
    public FeatureExtraColumns getExtraColumn() {
918
        return this.extraColumn;
919
    }
920

    
921
    @Override
922
    public MutableSymbolTable getSymbolTable() {
923
        return symbolTable;
924
    }
925

    
926
    @Override
927
    public void setSymbolTable(MutableSymbolTable symbolTable) {
928
        this.symbolTable = symbolTable;
929
    }
930

    
931
    @Override
932
    public void setVar(String name, Object value) {
933
        if( this.symbolTable==null ) {
934
            this.symbolTable = ExpressionUtils.createSymbolTable();
935
        }
936
        this.symbolTable.setVar(name, value);
937
    }
938

    
939
    @Override
940
    public boolean isUseSubquery() {
941
        return useSubquery;
942
    }
943

    
944
    @Override
945
    public void setUseSubquery(boolean useSubquery) {
946
        this.useSubquery = useSubquery;
947
    }
948
    
949
}