Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / feature / spi / ExpressionBuilderBase.java @ 43093

History | View | Annotate | Download (35.4 KB)

1
package org.gvsig.fmap.dal.feature.spi;
2

    
3
import java.text.MessageFormat;
4
import java.util.ArrayList;
5
import java.util.Collection;
6
import java.util.Collections;
7
import java.util.HashMap;
8
import java.util.HashSet;
9
import java.util.List;
10
import java.util.Map;
11
import java.util.Objects;
12
import java.util.Set;
13
import org.apache.commons.lang3.ObjectUtils;
14
import org.apache.commons.lang3.StringUtils;
15
import org.cresques.cts.IProjection;
16
import org.gvsig.fmap.dal.ExpressionBuilder;
17
import org.gvsig.fmap.dal.ExpressionBuilder.BinaryOperator;
18
import org.gvsig.fmap.dal.ExpressionBuilder.Config;
19
import org.gvsig.fmap.dal.ExpressionBuilder.Constant;
20
import org.gvsig.fmap.dal.ExpressionBuilder.Custom;
21
import org.gvsig.fmap.dal.ExpressionBuilder.Function;
22
import org.gvsig.fmap.dal.ExpressionBuilder.GeometrySupportType;
23
import org.gvsig.fmap.dal.ExpressionBuilder.GeometryValue;
24
import org.gvsig.fmap.dal.ExpressionBuilder.Group;
25
import org.gvsig.fmap.dal.ExpressionBuilder.Parameter;
26
import org.gvsig.fmap.dal.ExpressionBuilder.ParameterType;
27
import org.gvsig.fmap.dal.ExpressionBuilder.Value;
28
import org.gvsig.fmap.dal.ExpressionBuilder.Variable;
29
import org.gvsig.fmap.dal.ExpressionBuilder.Visitable;
30
import org.gvsig.fmap.dal.ExpressionBuilder.Visitor;
31
import org.gvsig.fmap.dal.ExpressionBuilder.VisitorFilter;
32
import org.gvsig.fmap.geom.Geometry;
33
import org.gvsig.fmap.geom.primitive.Envelope;
34

    
35
@SuppressWarnings("UseSpecificCatch")
36
public class ExpressionBuilderBase implements ExpressionBuilder {
37

    
38
    public class ConfigBase implements Config {
39

    
40
        protected Map<String, Object> values;
41

    
42
        public ConfigBase() {
43
            this.values = new HashMap<>();
44

    
45
            this.values.put(has_spatial_functions, false);
46
            this.values.put(constant_true, "(1=1)");
47
            this.values.put(constant_false, "(1=2)");
48
            this.values.put(quote_for_identifiers, "\"");
49
            this.values.put(quote_for_strings, "'");
50
            this.values.put(geometry_type_support, GeometrySupportType.WKT);
51
            this.values.put(group, "( {0} )");
52

    
53
            this.values.put(Find_SRID, "Find_SRID(({0}), ({1}), ({2}))");
54
            this.values.put(ST_SRID, "ST_SRID({0})");
55
            this.values.put(ST_AsText, "ST_AsText({0})");
56
            this.values.put(ST_AsBinary, "ST_AsBinary({0})");
57
            this.values.put(ST_AsEWKB, "ST_AsWKB({0})");
58
            this.values.put(ST_Contains, "ST_Contains(({0}), ({1}))");
59
            this.values.put(ST_Crosses, "ST_Crosses(({0}), ({1}))");
60
            this.values.put(ST_Disjoint, "ST_Disjoint(({0}), ({1}))");
61
            this.values.put(ST_Equals, "ST_Equals(({0}), ({1}))");
62
            this.values.put(ST_IsClosed, "ST_IsClosed({0})");
63
            this.values.put(ST_Overlaps, "ST_Overlaps(({0}), ({1}))");
64
            this.values.put(ST_Touches, "ST_Touches(({0}), ({1}))");
65
            this.values.put(ST_Within, "ST_Within(({0}), ({1}))");
66
            this.values.put(ST_Envelope, "ST_Envelope({0})");
67
            this.values.put(ST_Intersects, "ST_Intersects(({0}), ({1}))");
68
            this.values.put(ST_GeomFromText, "ST_GeomFromText({0}, ({1}))");
69
            this.values.put(ST_GeomFromWKB, "ST_GeomFromWKB(({0}), ({1}))");
70
            this.values.put(ST_GeomFromEWKB, "ST_GeomFromEWKB(({0}), ({1}))");
71
            this.values.put(lcase, "LCASE({0})");
72
            this.values.put(ucase, "UCASE({0})");
73
            this.values.put(isNull, "( ({0}) IS NULL )");
74
            this.values.put(notIsNull, "( ({0}) NOT IS NULL )");
75
            this.values.put(operator_not, "( NOT ({0}) )");
76

    
77
            this.values.put(operator_AND, "{0} AND {1}");
78
            this.values.put(operator_OR, "{0} OR {1}");
79
            this.values.put(operator_EQ, "( ({0}) = ({1}) )");
80
            this.values.put(operator_NE, "( ({0}) <> ({1}) )");
81
            this.values.put(operator_GT, "( ({0}) > ({1}) )");
82
            this.values.put(operator_GE, "( ({0}) >= ({1}) )");
83
            this.values.put(operator_LT, "( ({0}) < ({1}) )");
84
            this.values.put(operator_LE, "( ({0}) <= ({1}) )");
85
            this.values.put(operator_LIKE, "( ({0}) LIKE ({1}) )");
86
            this.values.put(operator_ILIKE, "( ({0}) ILIKE ({1}) )");
87

    
88
            this.values.put(operator_add, "{0} + {1}");
89
            this.values.put(operator_subst, "{0} - {1}");
90
            this.values.put(operator_mult, "{0} * {1}");
91
            this.values.put(operator_div, "{0} / {1}");
92
            this.values.put(operator_concat, "{0} || {1}");
93

    
94
        }
95

    
96
        @Override
97
        public boolean has_functionality(String functionality) {
98
            Object x = this.values.get(functionality);
99
            if (x == null) {
100
                return false;
101
            }
102
            if (x instanceof CharSequence && StringUtils.isEmpty((CharSequence) x)) {
103
                return false;
104
            }
105
            return true;
106
        }
107

    
108
        @Override
109
        public void remove_functionality(String functionality) {
110
            this.values.remove(functionality);
111
        }
112

    
113
        @Override
114
        public boolean has_spatial_functions() {
115
            return this.getBoolean(has_spatial_functions);
116
        }
117

    
118
        @Override
119
        public GeometrySupportType getGeometryTypeSupport() {
120
            return (GeometrySupportType) this.get(geometry_type_support);
121
        }
122

    
123
        @Override
124
        public boolean getBoolean(String name) {
125
            return (boolean) this.values.get(name);
126
        }
127

    
128
        @Override
129
        public String getString(String name) {
130
            return (String) this.values.get(name);
131
        }
132

    
133
        @Override
134
        public Object get(String name) {
135
            return this.values.get(name);
136
        }
137

    
138
        @Override
139
        public void set(String name, Object value) {
140
            this.values.put(name, value);
141
        }
142
    }
143

    
144
    public abstract class AbstractValue implements Value {
145

    
146
        @Override
147
        public void accept(Visitor visitor, VisitorFilter filter) {
148
            if (filter == null || filter.accept(this)) {
149
                visitor.visit(this);
150
            }
151
        }
152

    
153
    }
154

    
155
    public class ClassVisitorFilter implements VisitorFilter {
156

    
157
        private final Class classFilter;
158

    
159
        public ClassVisitorFilter(Class classFilter) {
160
            this.classFilter = classFilter;
161
        }
162

    
163
        @Override
164
        public boolean accept(Visitable visitable) {
165
            return classFilter.isInstance(visitable);
166
        }
167

    
168
    }
169

    
170
    public class GroupBase extends AbstractValue implements Group {
171

    
172
        protected Value value;
173

    
174
        public GroupBase(Value value) {
175
            this.value = value;
176
        }
177

    
178
        @Override
179
        public Value getValue() {
180
            return value;
181
        }
182

    
183
        @Override
184
        public void accept(Visitor visitor, VisitorFilter filter) {
185
            super.accept(visitor, filter);
186
            this.value.accept(visitor, filter);
187
        }
188

    
189
        @Override
190
        public String toString() {
191
            return MessageFormat.format(config.getString(Config.group), this.value.toString());
192
        }
193
    }
194

    
195
    public class VariableBase extends AbstractValue implements Variable {
196

    
197
        protected String name;
198

    
199
        public VariableBase(String name) {
200
            this.name = name;
201
        }
202

    
203
        @Override
204
        public String getName() {
205
            return this.name;
206
        }
207

    
208
        @Override
209
        public String toString() {
210
            return identifier(this.name);
211
        }
212

    
213
        @Override
214
        public int compareTo(Variable o) {
215
            return this.name.compareTo(o.getName());
216
        }
217

    
218
        @Override
219
        public boolean equals(Object obj) {
220
            if (!(obj instanceof Variable)) {
221
                return false;
222
            }
223
            return this.name.equals(((Variable) obj).getName());
224
        }
225

    
226
        @Override
227
        public int hashCode() {
228
            int hash = 7;
229
            hash = 37 * hash + Objects.hashCode(this.name);
230
            return hash;
231
        }
232
    }
233

    
234
    public class ParameterBase extends AbstractValue implements Parameter {
235

    
236
        protected String name;
237
        protected Object value;
238
        protected ParameterType type;
239
        protected Value srs;
240

    
241
        public ParameterBase() {
242
            this.type = ParameterType.Constant;
243
            this.name = null;
244
            this.value = null;
245
        }
246

    
247
        @Override
248
        public void accept(Visitor visitor, VisitorFilter filter) {
249
            super.accept(visitor, filter);
250
            if (this.srs != null) {
251
                this.srs.accept(visitor, filter);
252
            }
253
        }
254

    
255
        @Override
256
        public Parameter as_geometry_variable() {
257
            this.type = ParameterType.Geometry;
258
            if (this.value == null && this.name != null) {
259
                this.value = this.name;
260
            }
261
            return this;
262
        }
263

    
264
        @Override
265
        public Parameter as_constant() {
266
            this.type = ParameterType.Constant;
267
            if (this.value == null && this.name != null) {
268
                this.value = this.name;
269
            }
270
            return this;
271
        }
272

    
273
        @Override
274
        public Parameter as_variable() {
275
            this.type = ParameterType.Variable;
276
            if (this.value != null && this.name == null) {
277
                this.name = (String) this.value;
278
            }
279
            return this;
280
        }
281

    
282
        @Override
283
        public Parameter srs(Value srs) {
284
            this.srs = srs;
285
            if( this.type == ParameterType.Variable ) {
286
                this.type = ParameterType.Geometry;
287
            }
288
            return this;
289
        }
290

    
291
        @Override
292
        public Parameter srs(IProjection srs) {
293
            this.srs = constant(getSRSId(srs));
294
            if( this.type == ParameterType.Variable ) {
295
                this.type = ParameterType.Geometry;
296
            }
297
            return this;
298
        }
299

    
300
        @Override
301
        public String getName() {
302
            switch (this.type) {
303
                case Variable:
304
                case Geometry:
305
                    return this.name;
306
                case Constant:
307
                    if (this.value == null) {
308
                        return null;
309
                    }
310
                    return this.value.toString();
311
                default:
312
                    if (this.name != null) {
313
                        return this.name;
314
                    }
315
                    if (this.value != null) {
316
                        return this.value.toString();
317
                    }
318
                    return null;
319
            }
320
        }
321

    
322
        @Override
323
        public boolean is_constant() {
324
            return this.type == ParameterType.Constant;
325
        }
326

    
327
        @Override
328
        public boolean is_geometry_variable() {
329
            return this.type == ParameterType.Geometry;
330
        }
331

    
332
        @Override
333
        public boolean is_variable() {
334
            return this.type == ParameterType.Variable;
335
        }
336

    
337
        @Override
338
        public Parameter value(Object value) {
339
            this.value = value;
340
            return this;
341
        }
342

    
343
        @Override
344
        public Parameter name(String name) {
345
            this.type = ParameterType.Variable;
346
            this.name = name;
347
            return this;
348
        }
349

    
350
        @Override
351
        public Object getValue() {
352
            try {
353
                switch (this.type) {
354
                    case Constant:
355
                        if (this.value instanceof Geometry) {
356
                            switch (config.getGeometryTypeSupport()) {
357
                                case EWKB:
358
                                    return bytearray(((Geometry) this.value).convertToEWKB());
359
                                case WKB:
360
                                    return bytearray(((Geometry) this.value).convertToWKB());
361
                                case WKT:
362
                                default:
363
                                    return ((Geometry) this.value).convertToWKT();
364
                            }
365
                        } else if (this.value instanceof IProjection) {
366
                            return getSRSId((IProjection) this.value);
367
                        }
368
                        return this.value;
369
                    case Variable:
370
                    case Geometry:
371
                    default:
372
                        return this.value;
373
                }
374
            } catch (Exception ex) {
375
                throw new RuntimeException("Can't get value from parameter.", ex);
376
            }
377
        }
378

    
379
        @Override
380
        public ParameterType getType() {
381
            return this.type;
382
        }
383

    
384
        @Override
385
        public Value getSRS() {
386
            return this.srs;
387
        }
388

    
389
        @Override
390
        public String toString() {
391
            switch (this.type) {
392
                case Constant:
393
                case Variable:
394
                default:
395
                    return "?";
396
                case Geometry:
397
                    switch (config.getGeometryTypeSupport()) {
398
                        case EWKB:
399
                            return MessageFormat.format(
400
                                    config.getString(Config.ST_GeomFromEWKB),
401
                                    "?",
402
                                    String.valueOf(this.srs.toString())
403
                            );
404
                        case WKB:
405
                            return MessageFormat.format(
406
                                    config.getString(Config.ST_GeomFromWKB),
407
                                    "?",
408
                                    String.valueOf(this.srs.toString())
409
                            );
410
                        case WKT:
411
                        default:
412
                            return MessageFormat.format(
413
                                    config.getString(Config.ST_GeomFromText),
414
                                    "?",
415
                                    String.valueOf(this.srs.toString())
416
                            );
417
                    }
418
            }
419
        }
420
    }
421

    
422
    public class ConstantBase extends AbstractValue implements Constant {
423

    
424
        protected Object value;
425

    
426
        public ConstantBase(Object value) {
427
            this.value = value;
428
        }
429

    
430
        @Override
431
        public Object getValue() {
432
            return this.value;
433
        }
434

    
435
        @Override
436
        public String toString() {
437
            if (this.value instanceof String) {
438
                return string((String) this.value);
439
            }
440
            if (this.value instanceof Boolean) {
441
                if (((Boolean) this.value)) {
442
                    return config.getString(Config.constant_true);
443
                } else {
444
                    return config.getString(Config.constant_false);
445
                }
446
            }
447
            return ObjectUtils.toString(this.value, "");
448
        }
449
    }
450

    
451
    public class CustomBase extends AbstractValue implements Custom {
452

    
453
        protected Object value;
454

    
455
        // Esto es para permitir declarar parametros y columnas en una seccion
456
        // custom.
457
        protected List<Value> values;
458

    
459
        public CustomBase(Object value) {
460
            this.value = value;
461
        }
462

    
463
        @Override
464
        public void accept(Visitor visitor, VisitorFilter filter) {
465
            super.accept(visitor, filter);
466
            if (this.values != null) {
467
                for (Value value : values) {
468
                    value.accept(visitor, filter);
469
                }
470
            }
471
        }
472

    
473
        @Override
474
        public Object getValue() {
475
            return this.value;
476
        }
477

    
478
        @Override
479
        public Custom add(Variable variable) {
480
            if (this.values == null) {
481
                this.values = new ArrayList<>();
482
            }
483
            this.values.add(variable);
484
            return this;
485
        }
486

    
487
        @Override
488
        public Custom add(Parameter parameter) {
489
            if (this.values == null) {
490
                this.values = new ArrayList<>();
491
            }
492
            this.values.add(parameter);
493
            return this;
494
        }
495

    
496
        @Override
497
        public String toString() {
498
            return ObjectUtils.toString(this.value, "");
499
        }
500
    }
501

    
502
    public class GeometryValueBase extends AbstractValue implements GeometryValue {
503

    
504
        protected Geometry geometry;
505
        protected IProjection projection;
506

    
507
        public GeometryValueBase(Geometry geometry, IProjection projection) {
508
            this.geometry = geometry;
509
            this.projection = projection;
510
        }
511

    
512
        @Override
513
        public Geometry getGeometry() {
514
            return this.geometry;
515
        }
516

    
517
        @Override
518
        public IProjection getSRS() {
519
            return this.projection;
520
        }
521

    
522
        @Override
523
        public String toString() {
524
            try {
525
                switch (config.getGeometryTypeSupport()) {
526
                    case EWKB:
527
                        return MessageFormat.format(
528
                                config.getString(Config.ST_GeomFromEWKB),
529
                                bytearray(this.geometry.convertToEWKB()),
530
                                String.valueOf(getSRSId(this.projection))
531
                        );
532
                    case WKB:
533
                        return MessageFormat.format(
534
                                config.getString(Config.ST_GeomFromWKB),
535
                                bytearray(this.geometry.convertToWKB()),
536
                                String.valueOf(getSRSId(this.projection))
537
                        );
538
                    case WKT:
539
                    default:
540
                        return MessageFormat.format(
541
                                config.getString(Config.ST_GeomFromText),
542
                                string(this.geometry.convertToWKT()),
543
                                String.valueOf(getSRSId(this.projection))
544
                        );
545
                }
546
            } catch (Exception ex) {
547
                throw new RuntimeException("Can't convert geometry to string.", ex);
548
            }
549
        }
550
    }
551

    
552
    public class FunctionBase extends AbstractValue implements Function {
553

    
554
        protected String name;
555
        protected String format;
556
        protected List<Value> parameters;
557

    
558
        public FunctionBase(String name, String format) {
559
            this.name = name;
560
            this.format = format;
561
        }
562

    
563
        @Override
564
        public List<Value> parameters() {
565
            if (this.parameters == null) {
566
                this.parameters = new ArrayList<>();
567
            }
568
            return this.parameters;
569
        }
570

    
571
        @Override
572
        public Function parameter(Value parameter) {
573
            this.parameters().add(parameter);
574
            return this;
575
        }
576

    
577
        @Override
578
        public String getName() {
579
            return this.name;
580
        }
581

    
582
        @Override
583
        public void accept(Visitor visitor, VisitorFilter filter) {
584
            super.accept(visitor, filter);
585
            for (Value value : this.parameters) {
586
                value.accept(visitor, filter);
587
            }
588
        }
589

    
590
        @Override
591
        public String toString() {
592
            if (this.parameters != null && !this.parameters.isEmpty()) {
593
                List<String> values = new ArrayList<>();
594
                for (Value value : this.parameters) {
595
                    values.add(value.toString());
596
                }
597
                return MessageFormat.format(format, values.toArray());
598
            } else {
599
                return this.format;
600
            }
601
        }
602
    }
603

    
604
    public class BinaryOperatorBase extends AbstractValue implements BinaryOperator {
605

    
606
        protected String name;
607
        protected String format;
608
        protected Value left;
609
        protected Value right;
610

    
611
        public BinaryOperatorBase(String name, String format) {
612
            this.name = name;
613
            this.format = format;
614
        }
615

    
616
        @Override
617
        public String getName() {
618
            return this.name;
619
        }
620

    
621
        @Override
622
        public void accept(Visitor visitor, VisitorFilter filter) {
623
            super.accept(visitor, filter);
624
            this.left.accept(visitor, filter);
625
            this.right.accept(visitor, filter);
626
        }
627

    
628
        @Override
629
        public BinaryOperator setLeft(Value operand) {
630
            this.left = operand;
631
            return this;
632
        }
633

    
634
        @Override
635
        public BinaryOperator setRight(Value operand) {
636
            this.right = operand;
637
            return this;
638
        }
639

    
640
        @Override
641
        public Value getLeft() {
642
            return this.left;
643
        }
644

    
645
        @Override
646
        public Value getRight() {
647
            return this.right;
648
        }
649

    
650
        @Override
651
        public String toString() {
652
            return MessageFormat.format(
653
                    format,
654
                    this.left.toString(),
655
                    this.right.toString()
656
            );
657
        }
658
    }
659

    
660
    protected Value value;
661
    protected Config config;
662

    
663
    public ExpressionBuilderBase() {
664
        this.config = new ConfigBase();
665
    }
666

    
667
    @Override
668
    public ExpressionBuilder createExpressionBuilder() {
669
        return new ExpressionBuilderBase();
670
    }
671

    
672
    @Override
673
    public Config getConfig() {
674
        return this.config;
675
    }
676

    
677
    @Override
678
    public Value getValue() {
679
        return this.value;
680
    }
681

    
682
    @Override
683
    public ExpressionBuilder setValue(Value value) {
684
        this.value = value;
685
        return this;
686
    }
687

    
688
    @Override
689
    public String toString() {
690
        return this.value.toString();
691
    }
692

    
693
    @Override
694
    public void accept(Visitor visitor, VisitorFilter filter) {
695
        if( this.value == null) {
696
            return;
697
        }
698
        this.value.accept(visitor, filter);
699
    }
700

    
701
    @Override
702
    public boolean has_spatial_functions() {
703
        return this.config.getBoolean(Config.has_spatial_functions);
704
    }
705

    
706
    @Override
707
    public GeometrySupportType geometry_support_type() {
708
        return (GeometrySupportType) this.config.get(Config.geometry_type_support);
709
    }
710

    
711
    @Override
712
    public String string(String s) {
713
        String quote = this.config.getString(Config.quote_for_strings);
714
//        No se porque no esta disponible wrapIfMissing
715
//        return StringUtils.wrapIfMissing(s,quote);
716
        if (s.startsWith(quote)) {
717
            return s;
718
        }
719
        return quote + s + quote;
720
    }
721

    
722
    @Override
723
    public String identifier(String id) {
724
        String quote = this.config.getString(Config.quote_for_identifiers);
725
//        No se porque no esta disponible wrapIfMissing
726
//        return StringUtils.wrapIfMissing(id,quote);
727
        if (id.startsWith(quote)) {
728
            return id;
729
        }
730
        return quote + id + quote;
731
    }
732

    
733
    @Override
734
    public String bytearray(byte[] data) {
735
        StringBuilder builder = new StringBuilder();
736
        builder.append("0x");
737
        for (byte abyte : data) {
738
            int v = abyte & 0xff;
739
            builder.append(String.format("%02x", v));
740
        }
741
        return builder.toString();
742
    }
743

    
744
    @Override
745
    public int getSRSId(IProjection projection) {
746
        String abrev = projection.getAbrev();
747
        return Integer.valueOf(abrev.split(":")[1]);
748
    }
749

    
750
    @Override
751
    public Constant srs(IProjection projection) {
752
        return constant(getSRSId(projection));
753
    }
754

    
755
    @Override
756
    public Variable variable(String name) {
757
        return new VariableBase(name);
758
    }
759

    
760
    @Override
761
    public Variable column(String name) {
762
        return new VariableBase(name);
763
    }
764

    
765
    @Override
766
    public Parameter parameter(String name) {
767
        Parameters parameters = this.getParameters();
768
        Parameter parameter = parameters.get(name);
769
        if( parameter != null ) {
770
            return parameter;
771
        }
772
        parameter = this.parameter();
773
        parameter.name(name);
774
        return parameter;
775
    }
776
    
777
    public Parameter parameter() {
778
        return new ParameterBase();
779
    }
780
    
781
    @Override
782
    public Constant constant(Object value) {
783
        return new ConstantBase(value);
784
    }
785

    
786
    @Override
787
    public Group group(Value value) {
788
        return new GroupBase(value);
789
    }
790

    
791
    @Override
792
    public GeometryValue geometry(Geometry geom, IProjection projection) {
793
        return new GeometryValueBase(geom, projection);
794
    }
795

    
796
    @Override
797
    public GeometryValue envelope(Envelope envelope, IProjection projection) {
798
        return new GeometryValueBase(envelope.getGeometry(), projection);
799
    }
800

    
801
    @Override
802
    public Custom custom(Object value) {
803
        return new CustomBase(value);
804
    }
805

    
806
    public Function function(String name, String format, Value... values) {
807
        FunctionBase func = new FunctionBase(name, format);
808
        for (Value value : values) {
809
            func.parameter(value);
810
        }
811
        return func;
812
    }
813

    
814
    public BinaryOperator binaryOperator(String name, String format, Value leftOperand, Value rightOperand) {
815
        BinaryOperator operator = new BinaryOperatorBase(name, format);
816
        operator.setLeft(leftOperand);
817
        operator.setRight(rightOperand);
818
        return operator;
819
    }
820

    
821
    @Override
822
    public List<Variable> getVariables() {
823
        final Set<Variable> vars = new HashSet<>();
824
        this.accept(new Visitor() {
825
            @Override
826
            public void visit(Visitable value) {
827
                vars.add((Variable) value);
828
            }
829
        }, new ClassVisitorFilter(Variable.class));
830
        List<Variable> lvars = new ArrayList<>(vars);
831
        Collections.sort(lvars);
832
        return lvars;
833
    }
834

    
835
    private static class ParametersBase extends ArrayList<Parameter> implements Parameters {
836

    
837
        public ParametersBase() {
838
            super();
839
        }
840

    
841
        public ParametersBase(Collection parameters) {
842
            super(parameters);
843
        }
844

    
845
        @Override
846
        public Parameter get(String name) {
847
            if( name == null ) {
848
                return null;
849
            }
850
            for (Parameter param : this) {
851
                if( param.is_variable() || param.is_geometry_variable() ) {
852
                    if( name.equalsIgnoreCase(param.getName()) ) {
853
                        return param;
854
                    }
855
                }
856
            }
857
            return null;
858
        }
859

    
860
        
861
        @Override
862
        public String toString() {
863
            boolean first = true;
864
            StringBuilder builder = new StringBuilder();
865
            builder.append("{ ");
866
            for (Parameter param : this) {
867
                if (!first) {
868
                    builder.append(", ");
869
                } else {
870
                    first = false;
871
                }
872
                String s;
873
                Object value = param.getValue();
874
                if (value == null) {
875
                    s = "null";
876
                } else if (value instanceof String) {
877
                    s = "'" + (String) value + "'";
878
                } else {
879
                    s = value.toString();
880
                }
881
                switch (param.getType()) {
882
                    case Constant:
883
                        builder.append(s);
884
                        break;
885
                    case Geometry:
886
                        builder.append("(Geometry)");
887
                    case Variable:
888
                    default:
889
                        builder.append(param.getName());
890
                        builder.append(": ");
891
                        builder.append(s);
892
                }
893
            }
894
            builder.append(" }");
895
            return builder.toString();
896
        }
897
    }
898

    
899
    @Override
900
    public Parameters getParameters() {
901
        final Parameters params = new ParametersBase();
902
        this.accept(new Visitor() {
903
            @Override
904
            public void visit(Visitable value) {
905
                params.add((Parameter) value);
906
            }
907
        }, new ClassVisitorFilter(Parameter.class));
908
        return params;
909
    }
910

    
911
    @Override
912
    public Function getAsGeometry(Value value) {
913
        return function("ST_AsBinary", config.getString(Config.ST_AsBinary), value);
914
    }
915

    
916
    @Override
917
    public ExpressionBuilder set(Value value) {
918
        this.value = value;
919
        return this;
920
    }
921

    
922
    @Override
923
    public ExpressionBuilder and(Value value) {
924
        if (this.value == null) {
925
            return this.set(value);
926
        }
927
        BinaryOperator operator = binaryOperator("AND", config.getString(Config.operator_AND), this.value, value);
928
        this.value = operator;
929
        return this;
930
    }
931

    
932
    @Override
933
    public ExpressionBuilder or(Value value) {
934
        if (this.value == null) {
935
            return this.set(value);
936
        }
937
        BinaryOperator operator = binaryOperator("OR", config.getString(Config.operator_OR), this.value, value);
938
        this.value = operator;
939
        return this;
940
    }
941

    
942
    @Override
943
    public Function Find_SRID(Value schema, Value table, Value column) {
944
        return function("Find_SRID", config.getString(Config.Find_SRID), schema, table, column);
945
    }
946

    
947
    @Override
948
    public Function ST_Intersects(Value geom1, Value geom2) {
949
        return function("ST_Intersects", config.getString(Config.ST_Intersects), geom1, geom2);
950
    }
951

    
952
    @Override
953
    public Function ST_SRID(Value geom) {
954
        return function("ST_SRID", config.getString(Config.ST_SRID), geom);
955
    }
956

    
957
    @Override
958
    public Function ST_Envelope(Value geom) {
959
        return function("ST_Envelope", config.getString(Config.ST_Envelope), geom);
960
    }
961

    
962
    @Override
963
    public Function ST_AsText(Value geom) {
964
        return function("ST_AsText", config.getString(Config.ST_AsText), geom);
965
    }
966

    
967
    @Override
968
    public Function ST_AsBinary(Value geom) {
969
        return function("ST_AsBinary", config.getString(Config.ST_AsBinary), geom);
970
    }
971

    
972
    @Override
973
    public Function ST_AsEWKB(Value geom) {
974
        return function("ST_AsEWKB", config.getString(Config.ST_AsEWKB), geom);
975
    }
976

    
977
    @Override
978
    public Function ST_GeomFromText(Value geom, Value crs) {
979
        return function("ST_GeomFromText", config.getString(Config.ST_GeomFromText), geom, crs);
980
    }
981

    
982
    @Override
983
    public Function ST_GeomFromWKB(Value geom, Value crs) {
984
        return function("ST_GeomFromWKB", config.getString(Config.ST_GeomFromWKB), geom, crs);
985
    }
986

    
987
    @Override
988
    public Function ST_GeomFromEWKB(Value geom, Value crs) {
989
        return function("ST_GeomFromEWKB", config.getString(Config.ST_GeomFromEWKB), geom, crs);
990
    }
991

    
992
    @Override
993
    public Function ST_Disjoint(Value geom1, Value geom2) {
994
        return function("ST_Disjoint", config.getString(Config.ST_Disjoint), geom1, geom2);
995
    }
996

    
997
    @Override
998
    public Function ST_Contains(Value geom1, Value geom2) {
999
        return function("ST_Contains", config.getString(Config.ST_Contains), geom1, geom2);
1000
    }
1001

    
1002
    @Override
1003
    public Function ST_Equals(Value geom1, Value geom2) {
1004
        return function("ST_Equals", config.getString(Config.ST_Equals), geom1, geom2);
1005
    }
1006

    
1007
    @Override
1008
    public Function ST_Crosses(Value geom1, Value geom2) {
1009
        return function("ST_Crosses", config.getString(Config.ST_Crosses), geom1, geom2);
1010
    }
1011

    
1012
    @Override
1013
    public Function ST_IsClosed(Value geom) {
1014
        return function("ST_IsClosed", config.getString(Config.ST_IsClosed), geom);
1015
    }
1016

    
1017
    @Override
1018
    public Function ST_Overlaps(Value geom1, Value geom2) {
1019
        return function("ST_Overlaps", config.getString(Config.ST_Overlaps), geom1, geom2);
1020
    }
1021

    
1022
    @Override
1023
    public Function ST_Touches(Value geom1, Value geom2) {
1024
        return function("ST_Touches", config.getString(Config.ST_Touches), geom1, geom2);
1025
    }
1026

    
1027
    @Override
1028
    public Function ST_Within(Value geom1, Value geom2) {
1029
        return function("ST_Within", config.getString(Config.ST_Within), geom1, geom2);
1030
    }
1031

    
1032
    @Override
1033
    public Function isNull(Value value) {
1034
        return function("IS NULL", config.getString(Config.isNull), value);
1035
    }
1036

    
1037
    @Override
1038
    public Function notIsNull(Value value) {
1039
        return function("NOT IS NULL", config.getString(Config.notIsNull), value);
1040
    }
1041

    
1042
    @Override
1043
    public Function not(Value value) {
1044
        return function("NOT", config.getString(Config.operator_not), value);
1045
    }
1046

    
1047
    @Override
1048
    public Function lcase(Value s) {
1049
        return function("LCASE", config.getString(Config.lcase), s);
1050
    }
1051

    
1052
    @Override
1053
    public Function ucase(Value s) {
1054
        return function("UCASE", config.getString(Config.ucase), s);
1055
    }
1056

    
1057
    @Override
1058
    public BinaryOperator and(Value leftOperand, Value rightOperand) {
1059
        return binaryOperator("AND", config.getString(Config.operator_AND), leftOperand, rightOperand);
1060
    }
1061

    
1062
    @Override
1063
    public BinaryOperator or(Value leftOperand, Value rightOperand) {
1064
        return binaryOperator("OR", config.getString(Config.operator_OR), leftOperand, rightOperand);
1065
    }
1066

    
1067
    @Override
1068
    public BinaryOperator eq(Value leftOperand, Value rightOperand) {
1069
        return binaryOperator("=", config.getString(Config.operator_EQ), leftOperand, rightOperand);
1070
    }
1071

    
1072
    @Override
1073
    public BinaryOperator ne(Value leftOperand, Value rightOperand) {
1074
        return binaryOperator("<>", config.getString(Config.operator_NE), leftOperand, rightOperand);
1075
    }
1076

    
1077
    @Override
1078
    public BinaryOperator gt(Value op1, Value op2) {
1079
        return binaryOperator(">", config.getString(Config.operator_GT), op1, op2);
1080
    }
1081

    
1082
    @Override
1083
    public BinaryOperator ge(Value op1, Value op2) {
1084
        return binaryOperator(">=", config.getString(Config.operator_GE), op1, op2);
1085
    }
1086

    
1087
    @Override
1088
    public BinaryOperator lt(Value op1, Value op2) {
1089
        return binaryOperator("<", config.getString(Config.operator_LT), op1, op2);
1090
    }
1091

    
1092
    @Override
1093
    public BinaryOperator le(Value op1, Value op2) {
1094
        return binaryOperator("<=", config.getString(Config.operator_LE), op1, op2);
1095
    }
1096

    
1097
    @Override
1098
    public BinaryOperator like(Value op1, Value op2) {
1099
        return binaryOperator("LIKE", config.getString(Config.operator_LIKE), op1, op2);
1100
    }
1101

    
1102
    @Override
1103
    public BinaryOperator ilike(Value op1, Value op2) {
1104
        return binaryOperator("ILIKE", config.getString(Config.operator_ILIKE), op1, op2);
1105
    }
1106

    
1107
    @Override
1108
    public BinaryOperator add(Value op1, Value op2) {
1109
        return binaryOperator("ADD", config.getString(Config.operator_add), op1, op2);
1110
    }
1111

    
1112
    @Override
1113
    public BinaryOperator subst(Value op1, Value op2) {
1114
        return binaryOperator("SUBST", config.getString(Config.operator_subst), op1, op2);
1115
    }
1116

    
1117
    @Override
1118
    public BinaryOperator mult(Value op1, Value op2) {
1119
        return binaryOperator("MULT", config.getString(Config.operator_mult), op1, op2);
1120
    }
1121

    
1122
    @Override
1123
    public BinaryOperator div(Value op1, Value op2) {
1124
        return binaryOperator("DIV", config.getString(Config.operator_div), op1, op2);
1125
    }
1126

    
1127
    @Override
1128
    public BinaryOperator concat(Value op1, Value op2) {
1129
        return binaryOperator("CONCAT", config.getString(Config.operator_concat), op1, op2);
1130
    }
1131

    
1132
}