Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / fmap / dal / swing / impl / searchpanel / DefaultSearchParameters.java @ 46723

History | View | Annotate | Download (24.2 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.fmap.dal.swing.impl.searchpanel;
7

    
8
import java.io.ByteArrayInputStream;
9
import java.io.InputStream;
10
import java.util.ArrayList;
11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Map;
14
import javax.json.Json;
15
import javax.json.JsonObject;
16
import javax.json.JsonReader;
17
import org.apache.commons.lang3.StringUtils;
18
import org.gvsig.expressionevaluator.Code;
19
import org.gvsig.expressionevaluator.Expression;
20
import org.gvsig.expressionevaluator.ExpressionUtils;
21
import org.gvsig.fmap.dal.exception.DataException;
22
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
23
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
24
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
25
import org.gvsig.fmap.dal.feature.FeatureQuery;
26
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
27
import org.gvsig.fmap.dal.feature.FeatureSet;
28
import org.gvsig.fmap.dal.feature.FeatureStore;
29
import org.gvsig.fmap.dal.feature.FeatureType;
30
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
31
import org.gvsig.tools.ToolsLocator;
32
import org.gvsig.tools.dispose.DisposeUtils;
33
import org.gvsig.tools.dynobject.DynStruct;
34
import org.gvsig.tools.persistence.PersistenceManager;
35
import org.gvsig.tools.persistence.PersistentState;
36
import org.gvsig.tools.persistence.exception.PersistenceException;
37
import org.gvsig.tools.visitor.FilteredVisitable;
38

    
39
/**
40
 *
41
 * @author jjdelcerro
42
 */
43
public class DefaultSearchParameters implements SearchParameters, Cloneable {
44

    
45
    private List<String> resultColumnNames;
46
    private FeatureQuery query;
47
    private String name;
48
    private Map<String, JsonObject> values;
49
    private int searchMode;
50
    private boolean ignoreAggregateFunctions;
51

    
52
    public DefaultSearchParameters() {
53
        this.resultColumnNames = new ArrayList<>();
54
        this.query = null;
55
        this.values = new HashMap<>();
56
        this.searchMode = DefaultSearchPanel.PANEL_SIMPLIFIED;
57
    }
58

    
59
    @Override
60
    public List<String> getResultColumnNames() {
61
        return this.resultColumnNames;
62
    }
63

    
64
    public List<String> getGroupByColumns() {
65
        return this.query.getGroupByColumns();
66
    }
67

    
68
    public Map<String, String> getAggregateFunctions() {
69
        return this.query.getAggregateFunctions();
70
    }
71

    
72
    @Override
73
    public void setQuery(FeatureQuery query) {
74
        this.query = query;
75
    }
76

    
77
    public void setFilter(Expression exp) {
78
        this.query.setFilter(exp);
79
    }
80

    
81
    @Override
82
    public FeatureQuery getQuery() {
83
        return this.query;
84
    }
85

    
86
    @Override
87
    public FeatureQuery getQueryToApply() {
88
        if( this.query == null ) {
89
            return null;
90
        }
91
        FeatureQuery theQuery = this.query.getCopy();
92
        if( this.ignoreAggregateFunctions ) {
93
            theQuery.getAggregateFunctions().clear();
94
        }
95
        return theQuery;
96
    }
97
    
98
    void setResultColumnNames(List<String> selectedNames) {
99
        throw new UnsupportedOperationException("Not supported yet.");
100
    }
101

    
102
    @Override
103
    public Map<String, JsonObject> getValues() {
104
        return this.values;
105
    }
106

    
107
    public static void registerPersistence() {
108
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
109
        if (manager.getDefinition("SearchParameters") == null) {
110
            DynStruct definition = manager.addDefinition(DefaultSearchParameters.class,
111
                    "DefaultSearchParameters", "DefaultSearchParameters persistence definition", null, null);
112
            definition.addDynFieldList("resultColumnNames").setClassOfItems(String.class);
113
            definition.addDynFieldMap("values").setClassOfItems(String.class);
114
            definition.addDynFieldObject("query").setClassOfValue(FeatureQuery.class).setMandatory(false);
115
            definition.addDynFieldString("name");
116
            definition.addDynFieldInt("searchMode").setDefaultFieldValue(DefaultSearchPanel.PANEL_SIMPLIFIED).setMandatory(false);
117
            definition.addDynFieldBoolean("ignoreAggregateFunctions").setDefaultFieldValue(false).setMandatory(false);
118
        }
119
    }
120

    
121
    @Override
122
    public void saveToState(PersistentState state) throws PersistenceException {
123
        state.set("resultColumnNames", this.resultColumnNames);
124
        HashMap<String, String> valuesMap = new HashMap<>();
125
        for (String key : this.values.keySet()) {
126
            JsonObject value = this.values.get(key);
127
            valuesMap.put(key, value.toString());
128
        }
129
        state.set("values", valuesMap);
130
        state.set("query", this.query);
131
        state.set("name", this.name);
132
        state.set("searchMode", this.searchMode);
133
        state.set("ignoreAggregateFunctions", this.ignoreAggregateFunctions);
134
    }
135

    
136
    @Override
137
    public void loadFromState(PersistentState state) throws PersistenceException {
138
        this.resultColumnNames = new ArrayList<>(state.getList("resultColumnNames"));
139
        Map<String, String> valuesState = state.getMap("values");
140
        HashMap<String, JsonObject> valuesMap = new HashMap<>();
141

    
142
        for (String key : valuesState.keySet()) {
143
            String value = valuesState.get(key);
144
            InputStream targetStream = new ByteArrayInputStream(value.getBytes());
145
            JsonReader reader = Json.createReader(targetStream);
146
            JsonObject jsonObject = reader.readObject();
147
            valuesMap.put(key, jsonObject);
148
        }
149

    
150
        this.values = valuesMap;
151
        this.query = (FeatureQuery) state.get("query");
152
        this.name = state.getString("name");
153
        this.searchMode = state.getInt("searchMode", DefaultSearchPanel.PANEL_SIMPLIFIED);
154
        this.ignoreAggregateFunctions = state.getBoolean("ignoreAggregateFunctions", false);
155
    }
156
    
157
    private boolean isColumn(String name, FeatureType type) {
158
        if(type != null) {
159
            FeatureAttributeDescriptor attr = type.getAttributeDescriptorFromAll(name);
160
            if(attr != null){
161
                return true;
162
            }
163
        }
164
        if( this.query!=null ) {
165
            EditableFeatureAttributeDescriptor x = this.query.getExtraColumn().get(name);
166
            return x!=null;
167
        }
168
        return false;
169
    }
170

    
171
    private FeatureAttributeDescriptor getColumn(String name, FeatureType type) {
172
        if(type != null) {
173
            FeatureAttributeDescriptor attr = type.getAttributeDescriptorFromAll(name);
174
            if(attr != null){
175
                return attr;
176
            }
177
        }
178
        if( this.query!=null ) {
179
            EditableFeatureAttributeDescriptor x = this.query.getExtraColumn().get(name);
180
            return x;
181
        }
182
        return null;
183
    }
184

    
185
    @Override
186
    public String toString() {
187
        StringBuilder builder = new StringBuilder();
188
        builder.append("NAME: ");
189
        builder.append(this.getName());
190
        builder.append("\n");
191
        builder.append("SEARCH MODE: ");
192
        builder.append(this.getSearchMode());
193
        builder.append("\n");
194
        builder.append("IGNORE AGGREGATE FUNCTIONS: ");
195
        builder.append(this.getIgnoreAggregateFunctions());
196
        builder.append("\n");
197
        
198
        boolean first = true;
199
        for (String attributeName : this.getResultColumnNames()) {
200
            if (first) {
201
                builder.append("COLUMNS:\n  ");
202
                first=false;
203
            } else {
204
                builder.append(", ");
205
            }
206
            builder.append("\"");
207
            builder.append(attributeName);
208
            builder.append("\"");
209
        }                
210
        if( !first ) {
211
            builder.append("\n");
212
        }
213
        
214
        if (this.query != null) { 
215
            try {
216
                first = true;
217
                for (Map.Entry<String, String> aggregate : this.getAggregateFunctions().entrySet()) {
218
                    String exp = aggregate.getKey();
219
                    String function = aggregate.getValue();
220
                    if (first) {
221
                        builder.append("AGGREGATES:\n");
222
                        first=false;
223
                    }
224
                    builder.append("- ");
225
                    builder.append(function);
226
                    builder.append("(");
227
                    if( this.isColumn(exp, null) ) {
228
                        builder.append("\"");
229
                        builder.append(exp);
230
                        builder.append("\"");
231
                    } else {
232
                        builder.append(exp);
233
                    }
234
                    builder.append(")\n");
235
                }
236
            } catch(Exception ex) {
237
                builder.append("ERROR: ");
238
                builder.append(ex.getMessage());
239
                builder.append("\n");
240
            }
241

    
242
            try {
243
                if (this.query.getExpressionFilter() != null) {
244
                    builder.append("WHERE:\n  ");
245
                    builder.append(this.query.getExpressionFilter().getPhrase().replace("\n", " "));
246
                    builder.append("\n");
247
                }
248
            } catch(Exception ex) {
249
                builder.append("ERROR: ");
250
                builder.append(ex.getMessage());
251
                builder.append("\n");
252
            }
253

    
254
            try {
255
                first = true;
256
                for (String groupByColumn : this.query.getGroupByColumns()) {
257
                    if (first) {
258
                        builder.append("GROUP BY:\n");
259
                        first=false;
260
                    } else {
261
                        builder.append(", ");
262
                    }
263
                    if( isColumn(groupByColumn, null) ) {
264
                        builder.append("\"");
265
                        builder.append(groupByColumn);
266
                        builder.append("\"");
267
                    } else {
268
                        builder.append(groupByColumn);
269
                    }
270
                }
271
                if( !first ) {
272
                    builder.append("\n");
273
                }
274
            } catch(Exception ex) {
275
                builder.append("ERROR: ");
276
                builder.append(ex.getMessage());
277
                builder.append("\n");
278
            }
279

    
280
            try {
281
                first = true;
282
                for (FeatureQueryOrder.FeatureQueryOrderMember member : this.query.getOrder().members()) {
283
                    if (first) {
284
                        builder.append("ORDER BY: ");
285
                        first=false;
286
                    } else {
287
                        builder.append(", ");
288
                    }
289
                    builder.append("\"");
290
                    builder.append(member.getAttributeName());
291
                    builder.append("\"");
292
                    if(member.getAscending()) {
293
                        builder.append(" ASC");
294
                    } else {
295
                        builder.append(" DESC");
296
                    }
297
                }
298
                if( !first ) {
299
                    builder.append("\n");
300
                }
301
            } catch(Exception ex) {
302
                builder.append("ERROR: ");
303
                builder.append(ex.getMessage());
304
                builder.append("\n");
305
            }
306

    
307
            try {
308
                first = true;
309
                for (EditableFeatureAttributeDescriptor col : this.query.getExtraColumn().getColumns()) {
310
                    if (first) {
311
                        builder.append("USER COLUMNS:\n");
312
                        first=false;
313
                    }
314
                    builder.append("- \"");
315
                    builder.append(col.getName());
316
                    builder.append("\" ");
317
                    builder.append(col.getDataTypeName());
318
                    if( col.getFeatureAttributeEmulator() instanceof FeatureAttributeEmulatorExpression ) {
319
                        Expression exp = ((FeatureAttributeEmulatorExpression)col.getFeatureAttributeEmulator()).getExpression();
320
                        if( exp != null ) {
321
                            builder.append(" AS ");
322
                            builder.append(exp.getPhrase().replace("\n", " "));
323
                        }
324
                    }
325
                    builder.append("\n");
326
                }
327
            } catch(Exception ex) {
328
                builder.append("ERROR: ");
329
                builder.append(ex.getMessage());
330
                builder.append("\n");
331
            }
332
        }
333
        try {
334
            first = true;
335
            for (Map.Entry<String, JsonObject> value : this.getValues().entrySet()) {
336
                String key = value.getKey();
337
                JsonObject data = value.getValue();
338
                if (first) {
339
                    builder.append("VALUES:\n");
340
                    first=false;
341
                }
342
                builder.append("- ");
343
                builder.append(key);
344
                if( data != null ) {
345
                    builder.append(", ");
346
                    builder.append(data.toString().replace("\n"," "));
347
                }
348
                builder.append("\n");
349
            }
350
        } catch(Exception ex) {
351
            builder.append("ERROR: ");
352
            builder.append(ex.getMessage());
353
            builder.append("\n");
354
        }
355
        return builder.toString();
356
    }
357

    
358
    @Override
359
    public Object clone() throws CloneNotSupportedException {
360
        DefaultSearchParameters clone = (DefaultSearchParameters) super.clone();
361
        clone.query = this.query.getCopy();
362
        clone.resultColumnNames = new ArrayList(this.resultColumnNames);
363
        HashMap<String, JsonObject> cloneValues = new HashMap<>(this.values);
364
        clone.values = cloneValues;
365
        return clone;
366
    }
367

    
368
    public DefaultSearchParameters getCopy() {
369
        try {
370
            return (DefaultSearchParameters) this.clone();
371
        } catch (CloneNotSupportedException ex) {
372
            return null;
373
        }
374
    }
375

    
376
    @Override
377
    public void copyFrom(SearchParameters params) {
378
        this.resultColumnNames = params.getResultColumnNames();
379
        this.query = params.getQuery().getCopy();
380
        this.name = params.getName();
381
        this.values = params.getValues();
382
        this.searchMode = params.getSearchMode();
383
        this.ignoreAggregateFunctions = params.getIgnoreAggregateFunctions();
384
    }
385

    
386
    @Override
387
    public String getName() {
388
        return this.name;
389
    }
390

    
391
    @Override
392
    public void setName(String name) {
393
        this.name = name;
394
    }
395

    
396
    @Override
397
    public FeatureType getFeatureType(FeatureStore store) {
398
        FeatureSet fset = null;
399
        try {
400
            fset = store.getFeatureSet(this.query);
401
            FeatureType ft = fset.getDefaultFeatureType();
402
            return ft;
403
        } catch (DataException ex) {
404
            return store.getDefaultFeatureTypeQuietly();
405
        } finally {
406
            DisposeUtils.disposeQuietly(fset);
407
        }
408
    }
409
    
410
    public int getSearchMode()  {
411
        return this.searchMode;
412
    }
413
    
414
    public void setSearchMode(int searchMode) {
415
        this.searchMode = searchMode;
416
    }
417

    
418
    void fix(FeatureType featureType) {
419
        fix(featureType, false);
420
    }
421
    
422
    void fix(FeatureType featureType, boolean onlyEssentials) {
423
        if(!onlyEssentials){
424
            List<String> toRemoveAggregateColumns = new ArrayList<>();
425
            Map<String, String> aggregateFunctions = this.query.getAggregateFunctions();
426
            for (Map.Entry<String, String> aggregate : aggregateFunctions.entrySet()) {
427
                String colname = aggregate.getKey();
428
                String funcname = aggregate.getValue();
429
                if( this.query.getExtraColumn().get(colname)==null && featureType.get(colname)==null ) {
430
                    toRemoveAggregateColumns.add(colname);
431
                }
432
            }
433
            for (String toRemoveAggregateColumn : toRemoveAggregateColumns) {
434
                this.query.removeAggregateFunction(toRemoveAggregateColumn);
435
            }
436
        }
437
        if( this.query.getLimit()==0 ) {
438
            // Esto es por compatibilidad con querys guardados con antelacion
439
            // al cambio para hacer valido el limit 0.
440
            this.query.clearLimit();
441
        }
442
    }
443
    
444
    public boolean isValid(FeatureType type, StringBuilder errMessage){
445
        StringBuilder message;
446
        if(errMessage == null){
447
            message = new StringBuilder();
448
        } else {
449
            message = errMessage;
450
        }
451
        for (String attributeName : this.getResultColumnNames()) {
452
            if(!isColumn(attributeName, type)){
453
                message.append("Column \"");
454
                message.append(attributeName);
455
                message.append("\" not defined.\n");
456
            }
457
        }                
458
        
459
        if (this.query != null) { 
460
            try {
461
                for (Map.Entry<String, String> aggregate : this.getAggregateFunctions().entrySet()) {
462
                    String exp = aggregate.getKey();
463
                    String function = aggregate.getValue();
464
                    FeatureAttributeDescriptor attr = getColumn(exp, type);
465
                    if(attr != null){
466
                        if(StringUtils.equalsIgnoreCase(function, "SUM") && !attr.getDataType().isNumeric()){
467
                            message.append("Can't SUM not numeric column ");
468
                            message.append(function);
469
                            message.append("(");
470
                            message.append(exp);
471
                            message.append(")\n");
472
                            
473
                        }
474
                    } else {
475
                        Code code = null;
476
                        try {
477
                            code = ExpressionUtils.compile(exp);
478
                        } catch(Throwable t){
479
                            //TODO
480
                        }
481
                        if(code == null) {
482
                            message.append("Invalid expression in aggregate function ");
483
                            message.append(function);
484
                            message.append("(");
485
                            message.append(exp);
486
                            message.append(")\n");
487
                        }
488
                    }
489
                }
490
            } catch(Exception ex) {
491
                message.append("ERROR: ");
492
                message.append(ex.getMessage());
493
                message.append("\n");
494
            }
495

    
496
            try {
497
                Expression exp = this.query.getExpressionFilter();
498
                if (exp != null) {
499
                    Code code = null;
500
                    try {
501
                        code = exp.getCode();
502
                        code.accept((Object obj) -> {
503
                            String name1 = ((Code.Identifier)obj).name();
504
                            if (!isColumn(name1, type)) {
505
                                    message.append("Column \"");
506
                                    message.append(name1);
507
                                    message.append("\" not defined in filter.\n");
508
                            }
509
                        }, (FilteredVisitable t) -> (t instanceof Code.Identifier));
510
                    } catch (Throwable t) {
511
                        //TODO
512
                    }
513
                    if (code == null) {
514
                        message.append("Incorrect filter ");
515
                        message.append(exp.getPhrase());
516
                        message.append("\n");
517
                    }
518
                }
519
            } catch(Exception ex) {
520
                message.append("ERROR: ");
521
                message.append(ex.getMessage());
522
                message.append("\n");
523
            }
524

    
525
            try {
526
                for (String groupByColumn : this.query.getGroupByColumns()) {
527
                    if(!isColumn(groupByColumn, type)){
528
                        Code code = null;
529
                        try {
530
                            code = ExpressionUtils.compile(groupByColumn);
531
                        } catch(Throwable t){
532
                            //TODO
533
                        }
534
                        if(code == null) {
535
                            message.append("Group expression ");
536
                            message.append(groupByColumn);
537
                            message.append(" not valid \n");
538
                        }
539
                    }
540
                    
541
                }
542
            } catch(Exception ex) {
543
                message.append("ERROR: ");
544
                message.append(ex.getMessage());
545
                message.append("\n");
546
            }
547

    
548
            try {
549
                for (FeatureQueryOrder.FeatureQueryOrderMember member : this.query.getOrder().members()) {
550
                    if(!isColumn(member.getAttributeName(), type)){
551
                        Code code = null;
552
                        try {
553
                            code = ExpressionUtils.compile(member.getAttributeName());
554
                        } catch(Throwable t){
555
                            //Do nothing
556
                        }
557
                        if(code == null) {
558
                            message.append("Order expression ");
559
                            message.append(member.getAttributeName());
560
                            message.append(" not valid \n");
561
                        }
562
                    }
563

    
564
                }
565
            } catch(Exception ex) {
566
                message.append("ERROR: ");
567
                message.append(ex.getMessage());
568
                message.append("\n");
569
            }
570

    
571
            try {
572
                for (EditableFeatureAttributeDescriptor col : this.query.getExtraColumn().getColumns()) {
573
                    if( col.getFeatureAttributeEmulator() instanceof FeatureAttributeEmulatorExpression ) {
574
                        Expression exp = ((FeatureAttributeEmulatorExpression)col.getFeatureAttributeEmulator()).getExpression();
575
                        if( exp == null) {
576
                        } else {
577
                            Code code = null;
578
                            try {
579
                                code = exp.getCode();
580
                                code.accept((Object obj) -> {
581
                                    String name1 = ((Code.Identifier) obj).name();
582
                                    if (!isColumn(name1, type)) {
583
                                        message.append("\"");
584
                                        message.append(col.getName());
585
                                        message.append("\" refers to the nonexistent column \"");
586
                                        message.append(name1);
587
                                        message.append("\"");
588
                                    }
589
                                }, (FilteredVisitable t) -> (t instanceof Code.Identifier));
590
                            } catch (Throwable t) {
591
                                //Do nothing
592
                            }
593
                            if (code == null) {
594
                                message.append("Incorrect calculate column \"");
595
                                message.append(col.getName());
596
                                message.append("\"\n");
597
                            }
598
                        }
599
                    }
600
                }
601
            } catch(Exception ex) {
602
                message.append("ERROR: ");
603
                message.append(ex.getMessage());
604
                message.append("\n");
605
            }
606
        }
607
        if(StringUtils.isNotBlank(message)){
608
            return false;
609
        }
610
        
611
//        try {
612
//            for (Map.Entry<String, JsonObject> value : this.getValues().entrySet()) {
613
//                String key = value.getKey();
614
//                JsonObject data = value.getValue();
615
//            }
616
//        } catch(Exception ex) {
617
//                errMessage.append("ERROR: ");
618
//                errMessage.append(ex.getMessage());
619
//                errMessage.append("\n");
620
//        }
621
        return true;
622

    
623
    }
624

    
625
    @Override
626
    public void setIgnoreAggregateFunctions(boolean ignore) {
627
        this.ignoreAggregateFunctions = ignore;
628
    }
629

    
630
    @Override
631
    public boolean getIgnoreAggregateFunctions() {
632
        return this.ignoreAggregateFunctions;
633
    }
634

    
635
    @Override
636
    public void clear() {
637
        this.resultColumnNames = new ArrayList<>();
638
        if( query!=null ) {
639
            this.query.clearAttributeNames();
640
            this.query.clearConstantsAttributeNames();
641
            this.query.clearFilter();
642
            this.query.clearLimit();
643
        }
644
        this.values = new HashMap<>();
645
        this.searchMode = DefaultSearchPanel.PANEL_SIMPLIFIED;
646
    }
647
    
648
}
649