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

History | View | Annotate | Download (36.2 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.set(Config.has_spatial_functions, false);
46
            this.set(Config.support_schemas, true);
47
            this.set(Config.constant_true, "(1=1)");
48
            this.set(Config.constant_false, "(1=2)");
49
            this.set(Config.quote_for_identifiers, "\"");
50
            this.set(Config.quote_for_strings, "'");
51
            this.set(Config.geometry_type_support, GeometrySupportType.WKT);
52
            this.set(Config.group, "( {0} )");
53

    
54
            this.set(Config.Find_SRID, "Find_SRID(({0}), ({1}), ({2}))");
55
            this.set(Config.ST_SRID, "ST_SRID({0})");
56
            this.set(Config.ST_AsText, "ST_AsText({0})");
57
            this.set(Config.ST_AsBinary, "ST_AsBinary({0})");
58
            this.set(Config.ST_AsEWKB, "ST_AsEWKB({0})");
59
            this.set(Config.ST_Contains, "ST_Contains(({0}), ({1}))");
60
            this.set(Config.ST_Crosses, "ST_Crosses(({0}), ({1}))");
61
            this.set(Config.ST_Disjoint, "ST_Disjoint(({0}), ({1}))");
62
            this.set(Config.ST_Equals, "ST_Equals(({0}), ({1}))");
63
            this.set(Config.ST_IsClosed, "ST_IsClosed({0})");
64
            this.set(Config.ST_Overlaps, "ST_Overlaps(({0}), ({1}))");
65
            this.set(Config.ST_Touches, "ST_Touches(({0}), ({1}))");
66
            this.set(Config.ST_Within, "ST_Within(({0}), ({1}))");
67
            this.set(Config.ST_Envelope, "ST_Envelope({0})");
68
            this.set(Config.ST_Intersects, "ST_Intersects(({0}), ({1}))");
69
            this.set(Config.ST_GeomFromText, "ST_GeomFromText({0}, ({1}))");
70
            this.set(Config.ST_GeomFromWKB, "ST_GeomFromWKB(({0}), ({1}))");
71
            this.set(Config.ST_GeomFromEWKB, "ST_GeomFromEWKB(({0}), ({1}))");
72
            
73
            // Por defecto no esta disponible la funcion ST_Simplify
74
            // El proveedor que la soporte que la defina.
75
            // this.set(Config.ST_Simplify, "ST_Simplify(({0}), ({1}))");
76
            this.remove_functionality(Config.ST_Simplify);
77
            
78
            this.set(Config.lcase, "LCASE({0})");
79
            this.set(Config.ucase, "UCASE({0})");
80
            this.set(Config.isNull, "( ({0}) IS NULL )");
81
            this.set(Config.notIsNull, "( ({0}) NOT IS NULL )");
82
            this.set(Config.operator_not, "( NOT ({0}) )");
83

    
84
            this.set(Config.operator_AND, "{0} AND {1}");
85
            this.set(Config.operator_OR, "{0} OR {1}");
86
            this.set(Config.operator_EQ, "( ({0}) = ({1}) )");
87
            this.set(Config.operator_NE, "( ({0}) <> ({1}) )");
88
            this.set(Config.operator_GT, "( ({0}) > ({1}) )");
89
            this.set(Config.operator_GE, "( ({0}) >= ({1}) )");
90
            this.set(Config.operator_LT, "( ({0}) < ({1}) )");
91
            this.set(Config.operator_LE, "( ({0}) <= ({1}) )");
92
            this.set(Config.operator_LIKE, "( ({0}) LIKE ({1}) )");
93
            this.set(Config.operator_ILIKE, "( ({0}) ILIKE ({1}) )");
94

    
95
            this.set(Config.operator_add, "{0} + {1}");
96
            this.set(Config.operator_subst, "{0} - {1}");
97
            this.set(Config.operator_mult, "{0} * {1}");
98
            this.set(Config.operator_div, "{0} / {1}");
99
            this.set(Config.operator_concat, "{0} || {1}");
100

    
101
        }
102

    
103
        @Override
104
        public boolean has_functionality(String functionality) {
105
            Object x = this.values.get(functionality);
106
            if (x == null) {
107
                return false;
108
            }
109
            if (x instanceof CharSequence && StringUtils.isEmpty((CharSequence) x)) {
110
                return false;
111
            }
112
            return true;
113
        }
114

    
115
        @Override
116
        public void remove_functionality(String functionality) {
117
            this.values.remove(functionality);
118
        }
119

    
120
        @Override
121
        public boolean has_spatial_functions() {
122
            return this.getBoolean(has_spatial_functions);
123
        }
124

    
125
        @Override
126
        public GeometrySupportType getGeometryTypeSupport() {
127
            return (GeometrySupportType) this.get(geometry_type_support);
128
        }
129

    
130
        @Override
131
        public boolean getBoolean(String name) {
132
            return (boolean) this.values.get(name);
133
        }
134

    
135
        @Override
136
        public String getString(String name) {
137
            return (String) this.values.get(name);
138
        }
139

    
140
        @Override
141
        public Object get(String name) {
142
            return this.values.get(name);
143
        }
144

    
145
        @Override
146
        public void set(String name, Object value) {
147
            this.values.put(name, value);
148
        }
149
    }
150

    
151
    public abstract class AbstractValue implements Value {
152

    
153
        @Override
154
        public void accept(Visitor visitor, VisitorFilter filter) {
155
            if (filter == null || filter.accept(this)) {
156
                visitor.visit(this);
157
            }
158
        }
159

    
160
    }
161

    
162
    public class ClassVisitorFilter implements VisitorFilter {
163

    
164
        private final Class classFilter;
165

    
166
        public ClassVisitorFilter(Class classFilter) {
167
            this.classFilter = classFilter;
168
        }
169

    
170
        @Override
171
        public boolean accept(Visitable visitable) {
172
            return classFilter.isInstance(visitable);
173
        }
174

    
175
    }
176

    
177
    public class GroupBase extends AbstractValue implements Group {
178

    
179
        protected Value value;
180

    
181
        public GroupBase(Value value) {
182
            this.value = value;
183
        }
184

    
185
        @Override
186
        public Value getValue() {
187
            return value;
188
        }
189

    
190
        @Override
191
        public void accept(Visitor visitor, VisitorFilter filter) {
192
            super.accept(visitor, filter);
193
            this.value.accept(visitor, filter);
194
        }
195

    
196
        @Override
197
        public String toString() {
198
            return MessageFormat.format(config.getString(Config.group), this.value.toString());
199
        }
200
    }
201

    
202
    public class VariableBase extends AbstractValue implements Variable {
203

    
204
        protected String name;
205

    
206
        public VariableBase(String name) {
207
            this.name = name;
208
        }
209

    
210
        @Override
211
        public String getName() {
212
            return this.name;
213
        }
214

    
215
        @Override
216
        public String toString() {
217
            return identifier(this.name);
218
        }
219

    
220
        @Override
221
        public int compareTo(Variable o) {
222
            return this.name.compareTo(o.getName());
223
        }
224

    
225
        @Override
226
        public boolean equals(Object obj) {
227
            if (!(obj instanceof Variable)) {
228
                return false;
229
            }
230
            return this.name.equals(((Variable) obj).getName());
231
        }
232

    
233
        @Override
234
        public int hashCode() {
235
            int hash = 7;
236
            hash = 37 * hash + Objects.hashCode(this.name);
237
            return hash;
238
        }
239
    }
240

    
241
    public class ParameterBase extends AbstractValue implements Parameter {
242

    
243
        protected String name;
244
        protected Object value;
245
        protected ParameterType type;
246
        protected Value srs;
247

    
248
        public ParameterBase() {
249
            this.type = ParameterType.Constant;
250
            this.name = null;
251
            this.value = null;
252
        }
253

    
254
        @Override
255
        public void accept(Visitor visitor, VisitorFilter filter) {
256
            super.accept(visitor, filter);
257
            if (this.srs != null) {
258
                this.srs.accept(visitor, filter);
259
            }
260
        }
261

    
262
        @Override
263
        public Parameter as_geometry_variable() {
264
            this.type = ParameterType.Geometry;
265
            if (this.value == null && this.name != null) {
266
                this.value = this.name;
267
            }
268
            return this;
269
        }
270

    
271
        @Override
272
        public Parameter as_constant() {
273
            this.type = ParameterType.Constant;
274
            if (this.value == null && this.name != null) {
275
                this.value = this.name;
276
            }
277
            return this;
278
        }
279

    
280
        @Override
281
        public Parameter as_variable() {
282
            this.type = ParameterType.Variable;
283
            if (this.value != null && this.name == null) {
284
                this.name = (String) this.value;
285
            }
286
            return this;
287
        }
288

    
289
        @Override
290
        public Parameter srs(Value srs) {
291
            this.srs = srs;
292
            if( this.type == ParameterType.Variable ) {
293
                this.type = ParameterType.Geometry;
294
            }
295
            return this;
296
        }
297

    
298
        @Override
299
        public Parameter srs(IProjection srs) {
300
            this.srs = constant(getSRSId(srs));
301
            if( this.type == ParameterType.Variable ) {
302
                this.type = ParameterType.Geometry;
303
            }
304
            return this;
305
        }
306

    
307
        @Override
308
        public String getName() {
309
            switch (this.type) {
310
                case Variable:
311
                case Geometry:
312
                    return this.name;
313
                case Constant:
314
                    if (this.value == null) {
315
                        return null;
316
                    }
317
                    return this.value.toString();
318
                default:
319
                    if (this.name != null) {
320
                        return this.name;
321
                    }
322
                    if (this.value != null) {
323
                        return this.value.toString();
324
                    }
325
                    return null;
326
            }
327
        }
328

    
329
        @Override
330
        public boolean is_constant() {
331
            return this.type == ParameterType.Constant;
332
        }
333

    
334
        @Override
335
        public boolean is_geometry_variable() {
336
            return this.type == ParameterType.Geometry;
337
        }
338

    
339
        @Override
340
        public boolean is_variable() {
341
            return this.type == ParameterType.Variable;
342
        }
343

    
344
        @Override
345
        public Parameter value(Object value) {
346
            this.value = value;
347
            return this;
348
        }
349

    
350
        @Override
351
        public Parameter name(String name) {
352
            this.type = ParameterType.Variable;
353
            this.name = name;
354
            return this;
355
        }
356

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

    
386
        @Override
387
        public ParameterType getType() {
388
            return this.type;
389
        }
390

    
391
        @Override
392
        public Value getSRS() {
393
            return this.srs;
394
        }
395

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

    
429
    public class ConstantBase extends AbstractValue implements Constant {
430

    
431
        protected Object value;
432

    
433
        public ConstantBase(Object value) {
434
            this.value = value;
435
        }
436

    
437
        @Override
438
        public Object getValue() {
439
            return this.value;
440
        }
441

    
442
        @Override
443
        public String toString() {
444
            if (this.value instanceof String) {
445
                return string((String) this.value);
446
            }
447
            if (this.value instanceof Boolean) {
448
                if (((Boolean) this.value)) {
449
                    return config.getString(Config.constant_true);
450
                } else {
451
                    return config.getString(Config.constant_false);
452
                }
453
            }
454
            return ObjectUtils.toString(this.value, "");
455
        }
456
    }
457

    
458
    public class CustomBase extends AbstractValue implements Custom {
459

    
460
        protected Object value;
461

    
462
        // Esto es para permitir declarar parametros y columnas en una seccion
463
        // custom.
464
        protected List<Value> values;
465

    
466
        public CustomBase(Object value) {
467
            this.value = value;
468
        }
469

    
470
        @Override
471
        public void accept(Visitor visitor, VisitorFilter filter) {
472
            super.accept(visitor, filter);
473
            if (this.values != null) {
474
                for (Value value : values) {
475
                    value.accept(visitor, filter);
476
                }
477
            }
478
        }
479

    
480
        @Override
481
        public Object getValue() {
482
            return this.value;
483
        }
484

    
485
        @Override
486
        public Custom add(Variable variable) {
487
            if (this.values == null) {
488
                this.values = new ArrayList<>();
489
            }
490
            this.values.add(variable);
491
            return this;
492
        }
493

    
494
        @Override
495
        public Custom add(Parameter parameter) {
496
            if (this.values == null) {
497
                this.values = new ArrayList<>();
498
            }
499
            this.values.add(parameter);
500
            return this;
501
        }
502

    
503
        @Override
504
        public String toString() {
505
            return ObjectUtils.toString(this.value, "");
506
        }
507
    }
508

    
509
    public class GeometryValueBase extends AbstractValue implements GeometryValue {
510

    
511
        protected Geometry geometry;
512
        protected IProjection projection;
513

    
514
        public GeometryValueBase(Geometry geometry, IProjection projection) {
515
            this.geometry = geometry;
516
            this.projection = projection;
517
        }
518

    
519
        @Override
520
        public Geometry getGeometry() {
521
            return this.geometry;
522
        }
523

    
524
        @Override
525
        public IProjection getSRS() {
526
            return this.projection;
527
        }
528

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

    
559
    public class FunctionBase extends AbstractValue implements Function {
560

    
561
        protected String name;
562
        protected String format;
563
        protected List<Value> parameters;
564

    
565
        public FunctionBase(String name, String format) {
566
            this.name = name;
567
            this.format = format;
568
        }
569

    
570
        @Override
571
        public List<Value> parameters() {
572
            if (this.parameters == null) {
573
                this.parameters = new ArrayList<>();
574
            }
575
            return this.parameters;
576
        }
577

    
578
        @Override
579
        public Function parameter(Value parameter) {
580
            this.parameters().add(parameter);
581
            return this;
582
        }
583

    
584
        @Override
585
        public String getName() {
586
            return this.name;
587
        }
588

    
589
        @Override
590
        public void accept(Visitor visitor, VisitorFilter filter) {
591
            super.accept(visitor, filter);
592
            for (Value value : this.parameters) {
593
                value.accept(visitor, filter);
594
            }
595
        }
596

    
597
        @Override
598
        public String toString() {
599
            if (this.parameters != null && !this.parameters.isEmpty()) {
600
                List<String> values = new ArrayList<>();
601
                for (Value value : this.parameters) {
602
                    values.add(value.toString());
603
                }
604
                return MessageFormat.format(format, values.toArray());
605
            } else {
606
                return this.format;
607
            }
608
        }
609
    }
610

    
611
    public class BinaryOperatorBase extends AbstractValue implements BinaryOperator {
612

    
613
        protected String name;
614
        protected String format;
615
        protected Value left;
616
        protected Value right;
617

    
618
        public BinaryOperatorBase(String name, String format) {
619
            this.name = name;
620
            this.format = format;
621
        }
622

    
623
        @Override
624
        public String getName() {
625
            return this.name;
626
        }
627

    
628
        @Override
629
        public void accept(Visitor visitor, VisitorFilter filter) {
630
            super.accept(visitor, filter);
631
            this.left.accept(visitor, filter);
632
            this.right.accept(visitor, filter);
633
        }
634

    
635
        @Override
636
        public BinaryOperator setLeft(Value operand) {
637
            this.left = operand;
638
            return this;
639
        }
640

    
641
        @Override
642
        public BinaryOperator setRight(Value operand) {
643
            this.right = operand;
644
            return this;
645
        }
646

    
647
        @Override
648
        public Value getLeft() {
649
            return this.left;
650
        }
651

    
652
        @Override
653
        public Value getRight() {
654
            return this.right;
655
        }
656

    
657
        @Override
658
        public String toString() {
659
            return MessageFormat.format(
660
                    format,
661
                    this.left.toString(),
662
                    this.right.toString()
663
            );
664
        }
665
    }
666

    
667
    protected Value value;
668
    protected Config config;
669

    
670
    public ExpressionBuilderBase() {
671
        this.config = new ConfigBase();
672
    }
673

    
674
    @Override
675
    public ExpressionBuilder createExpressionBuilder() {
676
        return new ExpressionBuilderBase();
677
    }
678

    
679
    @Override
680
    public Config getConfig() {
681
        return this.config;
682
    }
683

    
684
    @Override
685
    public Value getValue() {
686
        return this.value;
687
    }
688

    
689
    @Override
690
    public ExpressionBuilder setValue(Value value) {
691
        this.value = value;
692
        return this;
693
    }
694

    
695
    @Override
696
    public String toString() {
697
        return this.value.toString();
698
    }
699

    
700
    @Override
701
    public void accept(Visitor visitor, VisitorFilter filter) {
702
        if( this.value == null) {
703
            return;
704
        }
705
        this.value.accept(visitor, filter);
706
    }
707

    
708
    @Override
709
    public boolean has_spatial_functions() {
710
        return this.config.getBoolean(Config.has_spatial_functions);
711
    }
712

    
713
    @Override
714
    public GeometrySupportType geometry_support_type() {
715
        return (GeometrySupportType) this.config.get(Config.geometry_type_support);
716
    }
717

    
718
    @Override
719
    public String string(String s) {
720
        String quote = this.config.getString(Config.quote_for_strings);
721
//        No se porque no esta disponible wrapIfMissing
722
//        return StringUtils.wrapIfMissing(s,quote);
723
        if (s.startsWith(quote)) {
724
            return s;
725
        }
726
        return quote + s + quote;
727
    }
728

    
729
    @Override
730
    public String identifier(String id) {
731
        String quote = this.config.getString(Config.quote_for_identifiers);
732
//        No se porque no esta disponible wrapIfMissing
733
//        return StringUtils.wrapIfMissing(id,quote);
734
        if (id.startsWith(quote)) {
735
            return id;
736
        }
737
        return quote + id + quote;
738
    }
739

    
740
    @Override
741
    public String bytearray(byte[] data) {
742
        return bytearray_0x(data);
743
    }
744
    
745
    protected String bytearray_hex(byte[] data) {
746
        StringBuilder builder = new StringBuilder();
747
        for (byte abyte : data) {
748
            int v = abyte & 0xff;
749
            builder.append(String.format("%02x", v));
750
        }
751
        return builder.toString();
752
    }
753

    
754
    protected String bytearray_0x(byte[] data) {
755
        return "0x" + bytearray_hex(data);
756
    }
757

    
758
    protected String bytearray_x(byte[] data) {
759
        return "x'" + bytearray_hex(data) + "'";
760
    }
761
    
762
    @Override
763
    public int getSRSId(IProjection projection) {
764
        String abrev = projection.getAbrev();
765
        return Integer.valueOf(abrev.split(":")[1]);
766
    }
767

    
768
    @Override
769
    public Constant srs(IProjection projection) {
770
        return constant(getSRSId(projection));
771
    }
772

    
773
    @Override
774
    public Variable variable(String name) {
775
        return new VariableBase(name);
776
    }
777

    
778
    @Override
779
    public Variable column(String name) {
780
        return new VariableBase(name);
781
    }
782

    
783
    @Override
784
    public Parameter parameter(String name) {
785
        Parameters parameters = this.getParameters();
786
        Parameter parameter = parameters.get(name);
787
        if( parameter != null ) {
788
            return parameter;
789
        }
790
        parameter = this.parameter();
791
        parameter.name(name);
792
        return parameter;
793
    }
794
    
795
    public Parameter parameter() {
796
        return new ParameterBase();
797
    }
798
    
799
    @Override
800
    public Constant constant(Object value) {
801
        return new ConstantBase(value);
802
    }
803

    
804
    @Override
805
    public Group group(Value value) {
806
        return new GroupBase(value);
807
    }
808

    
809
    @Override
810
    public GeometryValue geometry(Geometry geom, IProjection projection) {
811
        return new GeometryValueBase(geom, projection);
812
    }
813

    
814
    @Override
815
    public GeometryValue envelope(Envelope envelope, IProjection projection) {
816
        return new GeometryValueBase(envelope.getGeometry(), projection);
817
    }
818

    
819
    @Override
820
    public Custom custom(Object value) {
821
        return new CustomBase(value);
822
    }
823

    
824
    public Function function(String name, String format, Value... values) {
825
        FunctionBase func = new FunctionBase(name, format);
826
        for (Value value : values) {
827
            func.parameter(value);
828
        }
829
        return func;
830
    }
831

    
832
    public BinaryOperator binaryOperator(String name, String format, Value leftOperand, Value rightOperand) {
833
        BinaryOperator operator = new BinaryOperatorBase(name, format);
834
        operator.setLeft(leftOperand);
835
        operator.setRight(rightOperand);
836
        return operator;
837
    }
838

    
839
    @Override
840
    public List<Variable> getVariables() {
841
        final Set<Variable> vars = new HashSet<>();
842
        this.accept(new Visitor() {
843
            @Override
844
            public void visit(Visitable value) {
845
                vars.add((Variable) value);
846
            }
847
        }, new ClassVisitorFilter(Variable.class));
848
        List<Variable> lvars = new ArrayList<>(vars);
849
        Collections.sort(lvars);
850
        return lvars;
851
    }
852

    
853
    private static class ParametersBase extends ArrayList<Parameter> implements Parameters {
854

    
855
        public ParametersBase() {
856
            super();
857
        }
858

    
859
        public ParametersBase(Collection parameters) {
860
            super(parameters);
861
        }
862

    
863
        @Override
864
        public Parameter get(String name) {
865
            if( name == null ) {
866
                return null;
867
            }
868
            for (Parameter param : this) {
869
                if( param.is_variable() || param.is_geometry_variable() ) {
870
                    if( name.equalsIgnoreCase(param.getName()) ) {
871
                        return param;
872
                    }
873
                }
874
            }
875
            return null;
876
        }
877

    
878
        
879
        @Override
880
        public String toString() {
881
            boolean first = true;
882
            StringBuilder builder = new StringBuilder();
883
            builder.append("{ ");
884
            for (Parameter param : this) {
885
                if (!first) {
886
                    builder.append(", ");
887
                } else {
888
                    first = false;
889
                }
890
                String s;
891
                Object value = param.getValue();
892
                if (value == null) {
893
                    s = "null";
894
                } else if (value instanceof String) {
895
                    s = "'" + (String) value + "'";
896
                } else {
897
                    s = value.toString();
898
                }
899
                switch (param.getType()) {
900
                    case Constant:
901
                        builder.append(s);
902
                        break;
903
                    case Geometry:
904
                        builder.append("(Geometry)");
905
                    case Variable:
906
                    default:
907
                        builder.append(param.getName());
908
                        builder.append(": ");
909
                        builder.append(s);
910
                }
911
            }
912
            builder.append(" }");
913
            return builder.toString();
914
        }
915
    }
916

    
917
    @Override
918
    public Parameters getParameters() {
919
        final Parameters params = new ParametersBase();
920
        this.accept(new Visitor() {
921
            @Override
922
            public void visit(Visitable value) {
923
                params.add((Parameter) value);
924
            }
925
        }, new ClassVisitorFilter(Parameter.class));
926
        return params;
927
    }
928

    
929
    @Override
930
    public Function getAsGeometry(Value value) {
931
        return function("ST_AsBinary", config.getString(Config.ST_AsBinary), value);
932
    }
933

    
934
    @Override
935
    public ExpressionBuilder set(Value value) {
936
        this.value = value;
937
        return this;
938
    }
939

    
940
    @Override
941
    public ExpressionBuilder and(Value value) {
942
        if (this.value == null) {
943
            return this.set(value);
944
        }
945
        BinaryOperator operator = binaryOperator("AND", config.getString(Config.operator_AND), this.value, value);
946
        this.value = operator;
947
        return this;
948
    }
949

    
950
    @Override
951
    public ExpressionBuilder or(Value value) {
952
        if (this.value == null) {
953
            return this.set(value);
954
        }
955
        BinaryOperator operator = binaryOperator("OR", config.getString(Config.operator_OR), this.value, value);
956
        this.value = operator;
957
        return this;
958
    }
959

    
960
    @Override
961
    public Function Find_SRID(Value schema, Value table, Value column) {
962
        return function("Find_SRID", config.getString(Config.Find_SRID), schema, table, column);
963
    }
964

    
965
    @Override
966
    public Function ST_Intersects(Value geom1, Value geom2) {
967
        return function("ST_Intersects", config.getString(Config.ST_Intersects), geom1, geom2);
968
    }
969

    
970
    @Override
971
    public Function ST_SRID(Value geom) {
972
        return function("ST_SRID", config.getString(Config.ST_SRID), geom);
973
    }
974

    
975
    @Override
976
    public Function ST_Envelope(Value geom) {
977
        return function("ST_Envelope", config.getString(Config.ST_Envelope), geom);
978
    }
979

    
980
    @Override
981
    public Function ST_AsText(Value geom) {
982
        return function("ST_AsText", config.getString(Config.ST_AsText), geom);
983
    }
984

    
985
    @Override
986
    public Function ST_AsBinary(Value geom) {
987
        return function("ST_AsBinary", config.getString(Config.ST_AsBinary), geom);
988
    }
989

    
990
    @Override
991
    public Function ST_AsEWKB(Value geom) {
992
        return function("ST_AsEWKB", config.getString(Config.ST_AsEWKB), geom);
993
    }
994

    
995
    @Override
996
    public Function ST_GeomFromText(Value geom, Value crs) {
997
        return function("ST_GeomFromText", config.getString(Config.ST_GeomFromText), geom, crs);
998
    }
999

    
1000
    @Override
1001
    public Function ST_GeomFromWKB(Value geom, Value crs) {
1002
        return function("ST_GeomFromWKB", config.getString(Config.ST_GeomFromWKB), geom, crs);
1003
    }
1004

    
1005
    @Override
1006
    public Function ST_GeomFromEWKB(Value geom, Value crs) {
1007
        return function("ST_GeomFromEWKB", config.getString(Config.ST_GeomFromEWKB), geom, crs);
1008
    }
1009

    
1010
    @Override
1011
    public Function ST_Simplify(Value geom, Value tolerance) {
1012
        return function("ST_Simplify", config.getString(Config.ST_Simplify), tolerance);
1013
    }
1014

    
1015
    @Override
1016
    public Function ST_Disjoint(Value geom1, Value geom2) {
1017
        return function("ST_Disjoint", config.getString(Config.ST_Disjoint), geom1, geom2);
1018
    }
1019

    
1020
    @Override
1021
    public Function ST_Contains(Value geom1, Value geom2) {
1022
        return function("ST_Contains", config.getString(Config.ST_Contains), geom1, geom2);
1023
    }
1024

    
1025
    @Override
1026
    public Function ST_Equals(Value geom1, Value geom2) {
1027
        return function("ST_Equals", config.getString(Config.ST_Equals), geom1, geom2);
1028
    }
1029

    
1030
    @Override
1031
    public Function ST_Crosses(Value geom1, Value geom2) {
1032
        return function("ST_Crosses", config.getString(Config.ST_Crosses), geom1, geom2);
1033
    }
1034

    
1035
    @Override
1036
    public Function ST_IsClosed(Value geom) {
1037
        return function("ST_IsClosed", config.getString(Config.ST_IsClosed), geom);
1038
    }
1039

    
1040
    @Override
1041
    public Function ST_Overlaps(Value geom1, Value geom2) {
1042
        return function("ST_Overlaps", config.getString(Config.ST_Overlaps), geom1, geom2);
1043
    }
1044

    
1045
    @Override
1046
    public Function ST_Touches(Value geom1, Value geom2) {
1047
        return function("ST_Touches", config.getString(Config.ST_Touches), geom1, geom2);
1048
    }
1049

    
1050
    @Override
1051
    public Function ST_Within(Value geom1, Value geom2) {
1052
        return function("ST_Within", config.getString(Config.ST_Within), geom1, geom2);
1053
    }
1054

    
1055
    @Override
1056
    public Function isNull(Value value) {
1057
        return function("IS NULL", config.getString(Config.isNull), value);
1058
    }
1059

    
1060
    @Override
1061
    public Function notIsNull(Value value) {
1062
        return function("NOT IS NULL", config.getString(Config.notIsNull), value);
1063
    }
1064

    
1065
    @Override
1066
    public Function not(Value value) {
1067
        return function("NOT", config.getString(Config.operator_not), value);
1068
    }
1069

    
1070
    @Override
1071
    public Function lcase(Value s) {
1072
        return function("LCASE", config.getString(Config.lcase), s);
1073
    }
1074

    
1075
    @Override
1076
    public Function ucase(Value s) {
1077
        return function("UCASE", config.getString(Config.ucase), s);
1078
    }
1079

    
1080
    @Override
1081
    public BinaryOperator and(Value leftOperand, Value rightOperand) {
1082
        return binaryOperator("AND", config.getString(Config.operator_AND), leftOperand, rightOperand);
1083
    }
1084

    
1085
    @Override
1086
    public BinaryOperator or(Value leftOperand, Value rightOperand) {
1087
        return binaryOperator("OR", config.getString(Config.operator_OR), leftOperand, rightOperand);
1088
    }
1089

    
1090
    @Override
1091
    public BinaryOperator eq(Value leftOperand, Value rightOperand) {
1092
        return binaryOperator("=", config.getString(Config.operator_EQ), leftOperand, rightOperand);
1093
    }
1094

    
1095
    @Override
1096
    public BinaryOperator ne(Value leftOperand, Value rightOperand) {
1097
        return binaryOperator("<>", config.getString(Config.operator_NE), leftOperand, rightOperand);
1098
    }
1099

    
1100
    @Override
1101
    public BinaryOperator gt(Value op1, Value op2) {
1102
        return binaryOperator(">", config.getString(Config.operator_GT), op1, op2);
1103
    }
1104

    
1105
    @Override
1106
    public BinaryOperator ge(Value op1, Value op2) {
1107
        return binaryOperator(">=", config.getString(Config.operator_GE), op1, op2);
1108
    }
1109

    
1110
    @Override
1111
    public BinaryOperator lt(Value op1, Value op2) {
1112
        return binaryOperator("<", config.getString(Config.operator_LT), op1, op2);
1113
    }
1114

    
1115
    @Override
1116
    public BinaryOperator le(Value op1, Value op2) {
1117
        return binaryOperator("<=", config.getString(Config.operator_LE), op1, op2);
1118
    }
1119

    
1120
    @Override
1121
    public BinaryOperator like(Value op1, Value op2) {
1122
        return binaryOperator("LIKE", config.getString(Config.operator_LIKE), op1, op2);
1123
    }
1124

    
1125
    @Override
1126
    public BinaryOperator ilike(Value op1, Value op2) {
1127
        return binaryOperator("ILIKE", config.getString(Config.operator_ILIKE), op1, op2);
1128
    }
1129

    
1130
    @Override
1131
    public BinaryOperator add(Value op1, Value op2) {
1132
        return binaryOperator("ADD", config.getString(Config.operator_add), op1, op2);
1133
    }
1134

    
1135
    @Override
1136
    public BinaryOperator subst(Value op1, Value op2) {
1137
        return binaryOperator("SUBST", config.getString(Config.operator_subst), op1, op2);
1138
    }
1139

    
1140
    @Override
1141
    public BinaryOperator mult(Value op1, Value op2) {
1142
        return binaryOperator("MULT", config.getString(Config.operator_mult), op1, op2);
1143
    }
1144

    
1145
    @Override
1146
    public BinaryOperator div(Value op1, Value op2) {
1147
        return binaryOperator("DIV", config.getString(Config.operator_div), op1, op2);
1148
    }
1149

    
1150
    @Override
1151
    public BinaryOperator concat(Value op1, Value op2) {
1152
        return binaryOperator("CONCAT", config.getString(Config.operator_concat), op1, op2);
1153
    }
1154

    
1155
}