Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / DefaultCodeBuilder.java @ 44296

History | View | Annotate | Download (22 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.Iterator;
6
import java.util.List;
7
import org.apache.commons.lang3.StringUtils;
8
import org.gvsig.expressionevaluator.Code;
9
import static org.gvsig.expressionevaluator.Code.CALLER;
10
import static org.gvsig.expressionevaluator.Code.CONSTANT;
11
import static org.gvsig.expressionevaluator.Code.IDENTIFIER;
12
import static org.gvsig.expressionevaluator.Code.UNDEFINED;
13
import static org.gvsig.expressionevaluator.Code.CODES;
14
import org.gvsig.expressionevaluator.Code.Caller;
15
import org.gvsig.expressionevaluator.Code.Constant;
16
import static org.gvsig.expressionevaluator.Code.EMPTY_FORMATTER;
17
import org.gvsig.expressionevaluator.Code.Identifier;
18
import org.gvsig.expressionevaluator.Code.Method;
19
//import org.gvsig.expressionevaluator.Code.Method;
20
import org.gvsig.expressionevaluator.CodeBuilder;
21
import org.gvsig.expressionevaluator.Codes;
22
import org.gvsig.expressionevaluator.ExpressionBuilder;
23
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ADD;
24
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
25
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_CONCAT;
26
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_DIV;
27
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_EQ;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GE;
29
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GT;
30
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ILIKE;
31
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_IS;
32
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LE;
33
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LIKE;
34
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LT;
35
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MOD;
36
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MULT;
37
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NE;
38
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NEGATE;
39
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NOT;
40
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
41
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_REGEXP;
42
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_SUBST;
43
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
44
import org.gvsig.expressionevaluator.ExpressionUtils;
45
import org.gvsig.expressionevaluator.Formatter;
46
import org.gvsig.expressionevaluator.Function;
47
import org.gvsig.expressionevaluator.Interpreter;
48
import org.gvsig.expressionevaluator.SymbolTable;
49
import org.gvsig.expressionevaluator.impl.function.programming.CallMethodFunction;
50
import org.gvsig.expressionevaluator.impl.function.programming.GetattrFunction;
51
import org.gvsig.expressionevaluator.impl.function.programming.GetitemFunction;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.tools.exception.BaseException;
54
import org.gvsig.tools.visitor.Visitor;
55

    
56
@SuppressWarnings("UseSpecificCatch")
57
public class DefaultCodeBuilder implements CodeBuilder {
58

    
59
    public abstract class BaseCode implements Code {
60

    
61
        @Override
62
        public int code() {
63
            return UNDEFINED;
64
        }
65

    
66
        @Override
67
        public void accept(Visitor visitor) throws BaseException {
68
            visitor.visit(this);
69
        }
70

    
71
        @Override
72
        public Value toValue(ExpressionBuilder builder) {
73
            return null;
74
        }
75

    
76
        @Override
77
        public Value toValue() {
78
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
79
            return this.toValue(builder);
80
        }
81
        
82
        @Override
83
        public void link(SymbolTable symbolTable) {
84
            if( this.code() == Code.CALLER ) {
85
                Caller caller = (Caller) this;
86
                if( caller.function() == null ) {
87
                    caller.function(symbolTable.function(caller.name()));
88
                }
89
                if( caller.parameters() != null ) {
90
                    for( Code arg : caller.parameters() ) {
91
                        arg.link(symbolTable);
92
                    }
93
                }
94
            }
95
        }
96
    }
97

    
98
    class BaseConstant extends BaseCode implements Constant {
99

    
100
        private Object value;
101

    
102
        public BaseConstant(Object value) {
103
            this.value = value;
104
        }
105

    
106
        @Override
107
        public int code() {
108
            return CONSTANT;
109
        }
110

    
111
        @Override
112
        public Object value() {
113
            return this.value;
114
        }
115

    
116
        public void value(Object v) {
117
            this.value = v;
118
        }
119

    
120
        @Override
121
        public Value toValue(ExpressionBuilder builder) {
122
            return builder.constant(this.value);
123
        }
124

    
125
        @Override
126
        public String toString() {
127
            return this.toString(EMPTY_FORMATTER);
128
        }
129
        
130
        @Override
131
        public String toString(Formatter<Code> formatter) {
132
            if( formatter.canApply(this) ) {
133
                return formatter.format(this);
134
            }
135
            StringBuilder builder = new StringBuilder();
136
            Object v = this.value();
137
            if( v == null ) {
138
                builder.append("NULL");
139
            } else if( v instanceof CharSequence ) {
140
                if( StringUtils.isEmpty((CharSequence)v) ) {
141
                    builder.append("''");
142
                } else {
143
                    v = "'" + StringUtils.replace(v.toString(), "'", "''") + "'";
144
                    builder.append(v);
145
                }
146
                
147
            } else if( v instanceof Boolean ) {
148
                builder.append(((Boolean)v).toString().toUpperCase());
149
                
150
            } else if( v instanceof Geometry ) {
151
                try {
152
                    builder.append("'");
153
                    builder.append(((Geometry) v).convertToWKT());
154
                    builder.append("'::geometry");
155
                } catch (Exception ex) {
156
                    builder.append("'UNKNOW'::geometry");
157
                }
158
                
159
            } else {
160
                builder.append(v);
161
            }
162
            return builder.toString();
163
        }
164

    
165
    }
166

    
167
    public interface RecursionControlSupport {
168
        
169
        public boolean enterCode(int max);
170
        
171
        public void exitCode();
172
        
173
        public void resetRecursionState();
174
    }
175
    
176
    private class RecursionSupport implements RecursionControlSupport {
177
    
178
        private int counter;
179
        
180
        public RecursionSupport() {
181
            this.counter = 0;
182
        }
183

    
184
        @Override
185
        public boolean enterCode(int max) {
186
            this.counter += 1;
187
            return this.counter < max;
188
        }
189

    
190
        @Override
191
        public void exitCode() {
192
            this.counter -= 1;
193
        }
194

    
195
        @Override
196
        public void resetRecursionState() {
197
            this.counter = 0;
198
        }
199
        
200
    }
201
    
202
    public class BaseIdentifier extends BaseCode implements Identifier, RecursionControlSupport {
203

    
204
        private final String name;
205
        private final RecursionSupport recursionSupport;
206

    
207
        public BaseIdentifier(String name) {
208
            this.name = name;
209
            this.recursionSupport = new RecursionSupport();
210
        }
211

    
212
        @Override
213
        public int code() {
214
            return IDENTIFIER;
215
        }
216

    
217
        @Override
218
        public String name() {
219
            return this.name;
220
        }
221

    
222
        @Override
223
        public Value toValue(ExpressionBuilder builder) {
224
            return builder.variable(this.name);
225
        }
226

    
227
        @Override
228
        public String toString() {
229
            return this.toString(EMPTY_FORMATTER);
230
        }
231
        
232
        @Override
233
        public String toString(Formatter<Code> formatter) {
234
            if( formatter.canApply(this) ) {
235
                return formatter.format(this);
236
            }
237
            StringBuilder builder = new StringBuilder();
238
            builder.append("\"");
239
            builder.append(this.name());
240
            builder.append("\"");
241
            return builder.toString();
242
        }
243

    
244
        @Override
245
        public boolean enterCode(int max) {
246
            return this.recursionSupport.enterCode(max);
247
        }
248

    
249
        @Override
250
        public void exitCode() {
251
            this.recursionSupport.exitCode();
252
        }
253

    
254
        @Override
255
        public void resetRecursionState() {
256
            this.recursionSupport.resetRecursionState();
257
        }
258

    
259
    }
260

    
261
    public class BaseCodes implements Codes {
262

    
263
        private final List<Code> codes;
264

    
265
        public BaseCodes() {
266
            this.codes = new ArrayList<>();
267
        }
268

    
269
        @Override
270
        public int code() {
271
            return CODES;
272
        }
273
        
274
        @Override
275
        public int size() {
276
            if( codes == null ) {
277
                return 0;
278
            }
279
            return this.codes.size();
280
        }
281

    
282
        public void add(Code arg) {
283
            this.codes.add(arg);
284
        }
285

    
286
        public void insert(int pos, Code arg) {
287
            this.codes.add(pos, arg);
288
        }
289

    
290
        @Override
291
        public Iterator<Code> iterator() {
292
            return this.codes.iterator();
293
        }
294

    
295
        @Override
296
        public Code get(int n) {
297
            return this.codes.get(n);
298
        }
299

    
300
        @Override
301
        public boolean isEmpty() {
302
            return this.codes.isEmpty();
303
        }
304

    
305
        @Override
306
        public List<Code> toList() {
307
            return Collections.unmodifiableList(this.codes);
308
        }
309

    
310
        @Override
311
        public void accept(Visitor visitor) throws BaseException {
312
            for( Code arg : this.codes ) {
313
                arg.accept(visitor);
314
            }
315
        }
316

    
317
        @Override
318
        public String toString() {
319
            return this.toString(EMPTY_FORMATTER);
320
        }
321
        
322
        @Override
323
        public Value toValue(ExpressionBuilder builder) {
324
            throw new UnsupportedOperationException();
325
        }
326

    
327
        @Override
328
        public Value toValue() {
329
            throw new UnsupportedOperationException();
330
        }
331

    
332
        @Override
333
        public String toString(Formatter<Code> formatter) {
334
            if( formatter.canApply(this) ) {
335
                return formatter.format(this);
336
            }
337
            if( codes != null ) {
338
                StringBuilder builder = new StringBuilder();
339
                boolean skipcoma = true;
340
                for( Code code : codes ) {
341
                    if( code == null ) {
342
                        continue;
343
                    }
344
                    if( skipcoma ) {
345
                        skipcoma = false;
346
                    } else {
347
                        builder.append(", ");
348
                    }
349
                    builder.append(code.toString(formatter));
350
                }
351
                return builder.toString();
352
            }
353
            return "";
354
        }
355

    
356
        @Override
357
        public void link(SymbolTable symbolTable) {
358
            for (Code code : this.codes) {
359
                code.link(symbolTable);
360
            }
361
        }
362

    
363
    }
364

    
365
    public class BaseCaller extends BaseCode implements Caller, RecursionControlSupport {
366

    
367
        private final String name;
368
        private final Codes args;
369
        private Function function;
370
        private final int type;
371
        private final RecursionSupport recursionSupport;
372

    
373
        public BaseCaller(String name, int type, Codes args) {
374
            this.name = name;
375
            this.args = args;
376
            this.type = type;
377
            this.function = null;
378
            this.recursionSupport = new RecursionSupport();
379
        }
380

    
381
        @Override
382
        public int code() {
383
            return CALLER;
384
        }
385

    
386
        @Override
387
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
388
            return this.function.call(interpreter, args);
389
        }
390

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

    
396
        @Override
397
        public Function function() {
398
            return this.function;
399
        }
400

    
401
        @Override
402
        public Function function(Function function) {
403
            this.function = function;
404
            return this.function;
405
        }
406

    
407
        @Override
408
        public Codes parameters() {
409
            return this.args;
410
        }
411

    
412
        @Override
413
        public int type() {
414
            return this.type;
415
        }
416

    
417
        @Override
418
        public void accept(Visitor visitor) throws BaseException {
419
            visitor.visit(this);
420
            if(this.args!=null) {
421
                this.args.accept(visitor);
422
            }
423
        }
424

    
425
        @Override
426
        public Value toValue(ExpressionBuilder builder) {
427
            switch(this.type) {
428
                case UNARY_OPERATOR:
429
                    return builder.function(
430
                            OPERATOR_NEGATE.equalsIgnoreCase(this.name())?
431
                                "-" :
432
                                this.name(),
433
                            this.parameters().get(0).toValue(builder)
434
                    );
435
                case BINARY_OPERATOR:
436
                    return builder.binaryOperator(
437
                            this.name(),
438
                            this.parameters().get(0).toValue(builder),
439
                            this.parameters().get(1).toValue(builder)
440
                    );
441
                case FUNCTION:
442
                default:
443
                    ExpressionBuilder.Function f = builder.function(this.name());
444
                    if( this.parameters()!=null ) {
445
                        for (Code parameter : this.parameters()) {
446
                            f.parameter(parameter.toValue(builder));
447
                        }
448
                        
449
                    }
450
                    return f;
451

    
452
            }
453
        }
454

    
455
        @Override
456
        public String toString() {
457
            return this.toString(EMPTY_FORMATTER);
458
        }
459
        
460
        @Override
461
        public String toString(Formatter<Code> formatter) {
462
            if( formatter.canApply(this) ) {
463
                return formatter.format(this);
464
            }
465
            StringBuilder builder = new StringBuilder();
466
            switch(this.type) {
467
                case UNARY_OPERATOR:
468
                    if( OPERATOR_NEGATE.equalsIgnoreCase(this.name()) ) {
469
                        builder.append("-");
470
                    } else {
471
                        builder.append(this.name());
472
                    }
473
                    builder.append("(");
474
                    builder.append(this.parameters().get(0).toString(formatter));
475
                    builder.append(")");
476
                    break;
477
                case BINARY_OPERATOR:
478
                    builder.append("(");
479
                    builder.append(this.parameters().get(0).toString(formatter));
480
                    builder.append(" ");
481
                    builder.append(this.name());
482
                    builder.append(" ");
483
                    builder.append(this.parameters().get(1).toString(formatter));
484
                    builder.append(")");
485
                    break;
486
                case FUNCTION:
487
                default:
488
                    builder.append(this.name());
489
                    builder.append("(");
490
                    if( this.parameters()!=null ) {
491
                        builder.append(this.parameters().toString(formatter));
492
                    }
493
                    builder.append(")");
494
            }
495
            return builder.toString();
496
        }
497

    
498
        @Override
499
        public boolean enterCode(int max) {
500
            return this.recursionSupport.enterCode(max);
501
        }
502

    
503
        @Override
504
        public void exitCode() {
505
            this.recursionSupport.exitCode();
506
        }
507

    
508
        @Override
509
        public void resetRecursionState() {
510
            this.recursionSupport.resetRecursionState();
511
        }
512
    }
513

    
514
    public class BaseMethod extends BaseCode implements Method {
515

    
516
        private final Code instance;
517
        private final String methodname;
518
        private final Codes args;
519
        
520
        public BaseMethod(Code instance, String methodname, Codes args) {
521
            this.instance = instance;
522
            this.methodname = methodname;
523
            this.args = args;
524
        }
525

    
526
        @Override
527
        public int code() {
528
            return METHOD;
529
        }
530
        
531
        @Override
532
        public String methodname() {
533
            return this.methodname;
534
        }
535

    
536
        @Override
537
        public Code instance() {
538
            return this.instance;
539
        }
540

    
541
        @Override
542
        public Codes parameters() {
543
            return this.args;
544
        }
545

    
546
        @Override
547
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
548
            Object theInstance = interpreter.run(instance);
549
            return InstanceUtils.callmethod(theInstance, methodname, args);
550
        }
551

    
552
        @Override
553
        public String toString() {
554
            return this.toString(EMPTY_FORMATTER);
555
        }
556

    
557
        @Override
558
        public Value toValue(ExpressionBuilder builder) {
559
            ExpressionBuilder.Method m = builder.method(this.instance.toValue(builder), this.methodname);
560
            if( this.parameters()!=null ) {
561
                for (Code parameter : this.parameters()) {
562
                    m.parameter(parameter.toValue(builder));
563
                }
564
            }
565
            return m;
566
        }
567

    
568
        @Override
569
        public String toString(Formatter<Code> formatter) {
570
            if( formatter.canApply(this) ) {
571
                return formatter.format(this);
572
            }
573
            StringBuilder builder = new StringBuilder();
574
            builder.append(this.instance.toString(formatter));
575
            builder.append("->");
576
            builder.append(this.methodname());
577
            builder.append("(");
578
            if( this.parameters()!=null ) {
579
                builder.append(this.parameters().toString(formatter));
580
            }
581
            builder.append(")");
582
            return builder.toString();
583
        }
584
        
585
        
586
    }    
587
    
588
    @Override
589
    public CodeBuilder clone() throws CloneNotSupportedException {
590
        // This implementation of CodeBuilder does not maintain state, so 
591
        // we only call the super class.
592
        DefaultCodeBuilder other = (DefaultCodeBuilder) super.clone();
593
        return other;
594
    }
595

    
596
    @Override
597
    public Constant constant(Object value) {
598
        return new BaseConstant(value);
599
    }
600

    
601
    @Override
602
    public Identifier identifier(String name) {
603
        return new BaseIdentifier(name);
604
    }
605

    
606
    @Override
607
    public BaseCodes args() {
608
        return new BaseCodes();
609
    }
610

    
611
    @Override
612
    public Caller function(String name, int type, Codes args) {
613
        return new BaseCaller(name, type, args);
614
    }
615

    
616
    @Override
617
    public Caller function(String name, Codes args) {
618
        return function(name, Caller.FUNCTION, args);
619
    }
620
    
621
    @Override
622
    public Code method(Code instance, String methodname, Codes methodargs) {
623
        Method m = new BaseMethod(instance, methodname, methodargs);
624
        return m;
625
    }
626
    
627
    @Override
628
    public Caller operator(String name, Code arg1) {
629
        BaseCodes args = args();
630
        args.add(arg1);
631
        return function(name, Caller.UNARY_OPERATOR, args);
632
    }
633

    
634
    @Override
635
    public Caller operator(String name, Code arg1, Code arg2) {
636
        BaseCodes args = args();
637
        args.add(arg1);
638
        args.add(arg2);
639
        return function(name, Caller.BINARY_OPERATOR, args);
640
    }
641
    
642
    @Override
643
    public Code not(Code op1) {
644
        return operator(OPERATOR_NOT, op1);
645
    }
646

    
647
    @Override
648
    public Code negate(Code op1) {
649
        return operator(OPERATOR_NEGATE, op1);
650
    }
651

    
652
    @Override
653
    public Code concat(Code op1, Code op2) {
654
        return operator(OPERATOR_CONCAT, op1, op2);
655
    }
656

    
657
    @Override
658
    public Code add(Code op1, Code op2) {
659
        return operator(OPERATOR_ADD, op1, op2);
660
    }
661

    
662
    @Override
663
    public Code subst(Code op1, Code op2) {
664
        return operator(OPERATOR_SUBST, op1, op2);
665
    }
666

    
667
    @Override
668
    public Code mult(Code op1, Code op2) {
669
        return operator(OPERATOR_MULT, op1, op2);
670
    }
671

    
672
    @Override
673
    public Code div(Code op1, Code op2) {
674
        return operator(OPERATOR_DIV, op1, op2);
675
    }
676

    
677
    @Override
678
    public Code mod(Code op1, Code op2) {
679
        return operator(OPERATOR_MOD, op1, op2);
680
    }
681

    
682
    @Override
683
    public Code or(Code op1, Code op2) {
684
        return operator(OPERATOR_OR, op1, op2);
685
    }
686

    
687
    @Override
688
    public Code and(Code op1, Code op2) {
689
        return operator(OPERATOR_AND, op1, op2);
690
    }
691

    
692
    @Override
693
    public Code like(Code op1, Code op2) {
694
        return operator(OPERATOR_LIKE, op1, op2);
695
    }
696

    
697
    @Override
698
    public Code ilike(Code op1, Code op2) {
699
        return operator(OPERATOR_ILIKE, op1, op2);
700
    }
701

    
702
    @Override
703
    public Code regexp(Code op1, Code op2) {
704
        return operator(OPERATOR_REGEXP, op1, op2);
705
    }
706

    
707
    @Override
708
    public Code lt(Code op1, Code op2) {
709
        return operator(OPERATOR_LT, op1, op2);
710
    }
711

    
712
    @Override
713
    public Code gt(Code op1, Code op2) {
714
        return operator(OPERATOR_GT, op1, op2);
715
    }
716

    
717
    @Override
718
    public Code le(Code op1, Code op2) {
719
        return operator(OPERATOR_LE, op1, op2);
720
    }
721

    
722
    @Override
723
    public Code ge(Code op1, Code op2) {
724
        return operator(OPERATOR_GE, op1, op2);
725
    }
726

    
727
    @Override
728
    public Code eq(Code op1, Code op2) {
729
        return operator(OPERATOR_EQ, op1, op2);
730
    }
731

    
732
    @Override
733
    public Code ne(Code op1, Code op2) {
734
        return operator(OPERATOR_NE, op1, op2);
735
    }
736

    
737
    @Override
738
    public Code is(Code op1, Code op2) {
739
        return operator(OPERATOR_IS, op1, op2);
740
    }
741

    
742
    @Override
743
    public Code getattr(Code obj, String attrname) {
744
        BaseCodes args = args();
745
        args.add(obj);
746
        args.add(constant(attrname));
747
        return function(GetattrFunction.NAME, args);
748
    }    
749

    
750
    @Override
751
    public Code getitem(Code obj, Code index) {
752
        BaseCodes args = args();
753
        args.add(obj);
754
        args.add(index);
755
        return function(GetitemFunction.NAME, args);
756
    }
757

    
758
    
759
    
760
}