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

History | View | Annotate | Download (23.3 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.ObjectUtils;
8
import org.apache.commons.lang3.StringUtils;
9
import org.gvsig.expressionevaluator.Code;
10
import static org.gvsig.expressionevaluator.Code.CALLER;
11
import static org.gvsig.expressionevaluator.Code.CONSTANT;
12
import static org.gvsig.expressionevaluator.Code.IDENTIFIER;
13
import static org.gvsig.expressionevaluator.Code.UNDEFINED;
14
import static org.gvsig.expressionevaluator.Code.CODES;
15
import org.gvsig.expressionevaluator.Code.Caller;
16
import org.gvsig.expressionevaluator.Code.Constant;
17
import static org.gvsig.expressionevaluator.Code.EMPTY_FORMATTER;
18
import org.gvsig.expressionevaluator.Code.Identifier;
19
import org.gvsig.expressionevaluator.Code.Method;
20
//import org.gvsig.expressionevaluator.Code.Method;
21
import org.gvsig.expressionevaluator.CodeBuilder;
22
import org.gvsig.expressionevaluator.Codes;
23
import org.gvsig.expressionevaluator.ExpressionBuilder;
24
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ADD;
25
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
26
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_CONCAT;
27
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_DIV;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_EQ;
29
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GE;
30
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GT;
31
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ILIKE;
32
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_IS;
33
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LE;
34
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LIKE;
35
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LT;
36
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MOD;
37
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MULT;
38
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NE;
39
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NEGATE;
40
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NOT;
41
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
42
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_REGEXP;
43
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_SUBST;
44
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
45
import org.gvsig.expressionevaluator.ExpressionUtils;
46
import org.gvsig.expressionevaluator.Formatter;
47
import org.gvsig.expressionevaluator.Function;
48
import org.gvsig.expressionevaluator.Interpreter;
49
import org.gvsig.expressionevaluator.SymbolTable;
50
import org.gvsig.expressionevaluator.impl.function.programming.CallMethodFunction;
51
import org.gvsig.expressionevaluator.impl.function.programming.GetattrFunction;
52
import org.gvsig.expressionevaluator.impl.function.programming.GetitemFunction;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.tools.dynobject.DynObject;
55
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
56
import org.gvsig.tools.exception.BaseException;
57
import org.gvsig.tools.script.Script;
58
import org.gvsig.tools.visitor.Visitor;
59

    
60
@SuppressWarnings("UseSpecificCatch")
61
public class DefaultCodeBuilder implements CodeBuilder {
62

    
63
    public abstract class BaseCode implements Code {
64

    
65
        @Override
66
        public int code() {
67
            return UNDEFINED;
68
        }
69

    
70
        @Override
71
        public void accept(Visitor visitor) throws BaseException {
72
            visitor.visit(this);
73
        }
74

    
75
        @Override
76
        public Value toValue(ExpressionBuilder builder) {
77
            return null;
78
        }
79

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

    
102
    class BaseConstant extends BaseCode implements Constant {
103

    
104
        private Object value;
105

    
106
        public BaseConstant(Object value) {
107
            this.value = value;
108
        }
109

    
110
        @Override
111
        public int code() {
112
            return CONSTANT;
113
        }
114

    
115
        @Override
116
        public Object value() {
117
            return this.value;
118
        }
119

    
120
        public void value(Object v) {
121
            this.value = v;
122
        }
123

    
124
        @Override
125
        public Value toValue(ExpressionBuilder builder) {
126
            return builder.constant(this.value);
127
        }
128

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

    
169
    }
170

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

    
188
        @Override
189
        public boolean enterCode(int max) {
190
            this.counter += 1;
191
            return this.counter < max;
192
        }
193

    
194
        @Override
195
        public void exitCode() {
196
            this.counter -= 1;
197
        }
198

    
199
        @Override
200
        public void resetRecursionState() {
201
            this.counter = 0;
202
        }
203
        
204
    }
205
    
206
    public class BaseIdentifier extends BaseCode implements Identifier, RecursionControlSupport {
207

    
208
        private final String name;
209
        private final RecursionSupport recursionSupport;
210

    
211
        public BaseIdentifier(String name) {
212
            this.name = name;
213
            this.recursionSupport = new RecursionSupport();
214
        }
215

    
216
        @Override
217
        public int code() {
218
            return IDENTIFIER;
219
        }
220

    
221
        @Override
222
        public String name() {
223
            return this.name;
224
        }
225

    
226
        @Override
227
        public Value toValue(ExpressionBuilder builder) {
228
            return builder.variable(this.name);
229
        }
230

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

    
248
        @Override
249
        public boolean enterCode(int max) {
250
            return this.recursionSupport.enterCode(max);
251
        }
252

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

    
258
        @Override
259
        public void resetRecursionState() {
260
            this.recursionSupport.resetRecursionState();
261
        }
262

    
263
    }
264

    
265
    public class BaseCodes implements Codes {
266

    
267
        private final List<Code> codes;
268

    
269
        public BaseCodes() {
270
            this.codes = new ArrayList<>();
271
        }
272

    
273
        @Override
274
        public int code() {
275
            return CODES;
276
        }
277
        
278
        @Override
279
        public int size() {
280
            if( codes == null ) {
281
                return 0;
282
            }
283
            return this.codes.size();
284
        }
285

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

    
290
        public void insert(int pos, Code arg) {
291
            this.codes.add(pos, arg);
292
        }
293

    
294
        @Override
295
        public Iterator<Code> iterator() {
296
            return this.codes.iterator();
297
        }
298

    
299
        @Override
300
        public Code get(int n) {
301
            return this.codes.get(n);
302
        }
303

    
304
        @Override
305
        public boolean isEmpty() {
306
            return this.codes.isEmpty();
307
        }
308

    
309
        @Override
310
        public List<Code> toList() {
311
            return Collections.unmodifiableList(this.codes);
312
        }
313

    
314
        @Override
315
        public void accept(Visitor visitor) throws BaseException {
316
            for( Code arg : this.codes ) {
317
                arg.accept(visitor);
318
            }
319
        }
320

    
321
        @Override
322
        public String toString() {
323
            return this.toString(EMPTY_FORMATTER);
324
        }
325
        
326
        @Override
327
        public Value toValue(ExpressionBuilder builder) {
328
            throw new UnsupportedOperationException();
329
        }
330

    
331
        @Override
332
        public Value toValue() {
333
            throw new UnsupportedOperationException();
334
        }
335

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

    
360
        @Override
361
        public void link(SymbolTable symbolTable) {
362
            for (Code code : this.codes) {
363
                code.link(symbolTable);
364
            }
365
        }
366

    
367
    }
368

    
369
    public class BaseCaller extends BaseCode implements Caller, RecursionControlSupport {
370

    
371
        private final String name;
372
        private final Codes args;
373
        private Function function;
374
        private final int type;
375
        private final RecursionSupport recursionSupport;
376

    
377
        public BaseCaller(String name, int type, Codes args) {
378
            this.name = name;
379
            this.args = args;
380
            this.type = type;
381
            this.function = null;
382
            this.recursionSupport = new RecursionSupport();
383
        }
384

    
385
        @Override
386
        public int code() {
387
            return CALLER;
388
        }
389

    
390
        @Override
391
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
392
            return this.function.call(interpreter, args);
393
        }
394

    
395
        @Override
396
        public String name() {
397
            return this.name;
398
        }
399

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

    
405
        @Override
406
        public Function function(Function function) {
407
            this.function = function;
408
            return this.function;
409
        }
410

    
411
        @Override
412
        public Codes parameters() {
413
            return this.args;
414
        }
415

    
416
        @Override
417
        public int type() {
418
            return this.type;
419
        }
420

    
421
        @Override
422
        public void accept(Visitor visitor) throws BaseException {
423
            visitor.visit(this);
424
            if(this.args!=null) {
425
                this.args.accept(visitor);
426
            }
427
        }
428

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

    
456
            }
457
        }
458

    
459
        @Override
460
        public String toString() {
461
            return this.toString(EMPTY_FORMATTER);
462
        }
463
        
464
        @Override
465
        public String toString(Formatter<Code> formatter) {
466
            if( formatter.canApply(this) ) {
467
                return formatter.format(this);
468
            }
469
            Code code;
470
            StringBuilder builder = new StringBuilder();
471
            switch(this.type) {
472
                case UNARY_OPERATOR:
473
                    if( OPERATOR_NEGATE.equalsIgnoreCase(this.name()) ) {
474
                        builder.append("-");
475
                    } else {
476
                        builder.append(this.name());
477
                    }
478
                    builder.append("(");
479
                    builder.append(this.parameters().get(0).toString(formatter));
480
                    builder.append(")");
481
                    break;
482
                case BINARY_OPERATOR:
483
                    builder.append("(");
484
                    code = this.parameters().get(0);
485
                    if( code == null ) {                    
486
                        builder.append("?NULL?");
487
                    } else {
488
                        builder.append(code.toString(formatter));
489
                    }
490
                    builder.append(" ");
491
                    builder.append(this.name());
492
                    builder.append(" ");
493
                    code = this.parameters().get(1);
494
                    if( code == null ) {                    
495
                        builder.append("?NULL?");
496
                    } else {
497
                        builder.append(code.toString(formatter));
498
                    }
499
                    builder.append(")");
500
                    break;
501
                case FUNCTION:
502
                default:
503
                    builder.append(this.name());
504
                    builder.append("(");
505
                    if( this.parameters()!=null ) {
506
                        builder.append(this.parameters().toString(formatter));
507
                    }
508
                    builder.append(")");
509
            }
510
            return builder.toString();
511
        }
512

    
513
        @Override
514
        public boolean enterCode(int max) {
515
            return this.recursionSupport.enterCode(max);
516
        }
517

    
518
        @Override
519
        public void exitCode() {
520
            this.recursionSupport.exitCode();
521
        }
522

    
523
        @Override
524
        public void resetRecursionState() {
525
            this.recursionSupport.resetRecursionState();
526
        }
527
    }
528

    
529
    public class BaseMethod extends BaseCode implements Method {
530

    
531
        private final Code instance;
532
        private final String methodname;
533
        private final Codes args;
534
        
535
        public BaseMethod(Code instance, String methodname, Codes args) {
536
            this.instance = instance;
537
            this.methodname = methodname;
538
            this.args = args;
539
        }
540

    
541
        @Override
542
        public int code() {
543
            return METHOD;
544
        }
545
        
546
        @Override
547
        public String methodname() {
548
            return this.methodname;
549
        }
550

    
551
        @Override
552
        public Code instance() {
553
            return this.instance;
554
        }
555

    
556
        @Override
557
        public Codes parameters() {
558
            return this.args;
559
        }
560

    
561
        @Override
562
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
563
            Object theInstance = interpreter.run(instance);
564
            if( theInstance instanceof SimpleScript ) {
565
                try {
566
                    return ((SimpleScript)theInstance).invokeFunction(methodname, args);
567
                } catch(NoSuchMethodException ex) {
568
                    // Ignore... continue calling instance method
569
                }                
570
            } else if( theInstance instanceof DynObject ) {
571
                DynObject dynobj = (DynObject) theInstance;
572
                try {
573
                    return dynobj.invokeDynMethod(methodname, args);
574
                } catch(DynMethodNotSupportedException ex) {
575
                    // Ignore... continue calling instance method
576
                }
577
            }
578
            return InstanceUtils.callmethod(theInstance, methodname, args);
579
        }
580

    
581
        @Override
582
        public String toString() {
583
            return this.toString(EMPTY_FORMATTER);
584
        }
585

    
586
        @Override
587
        public Value toValue(ExpressionBuilder builder) {
588
            ExpressionBuilder.Method m = builder.method(this.instance.toValue(builder), this.methodname);
589
            if( this.parameters()!=null ) {
590
                for (Code parameter : this.parameters()) {
591
                    m.parameter(parameter.toValue(builder));
592
                }
593
            }
594
            return m;
595
        }
596

    
597
        @Override
598
        public String toString(Formatter<Code> formatter) {
599
            if( formatter.canApply(this) ) {
600
                return formatter.format(this);
601
            }
602
            StringBuilder builder = new StringBuilder();
603
            builder.append(this.instance.toString(formatter));
604
            builder.append("->");
605
            builder.append(this.methodname());
606
            builder.append("(");
607
            if( this.parameters()!=null ) {
608
                builder.append(this.parameters().toString(formatter));
609
            }
610
            builder.append(")");
611
            return builder.toString();
612
        }
613
        
614
        
615
    }    
616
    
617
    @Override
618
    public CodeBuilder clone() throws CloneNotSupportedException {
619
        // This implementation of CodeBuilder does not maintain state, so 
620
        // we only call the super class.
621
        DefaultCodeBuilder other = (DefaultCodeBuilder) super.clone();
622
        return other;
623
    }
624

    
625
    @Override
626
    public Constant constant(Object value) {
627
        return new BaseConstant(value);
628
    }
629

    
630
    @Override
631
    public Identifier identifier(String name) {
632
        return new BaseIdentifier(name);
633
    }
634

    
635
    @Override
636
    public BaseCodes args() {
637
        return new BaseCodes();
638
    }
639

    
640
    @Override
641
    public Caller function(String name, int type, Codes args) {
642
        return new BaseCaller(name, type, args);
643
    }
644

    
645
    @Override
646
    public Caller function(String name, Codes args) {
647
        return function(name, Caller.FUNCTION, args);
648
    }
649
    
650
    @Override
651
    public Code method(Code instance, String methodname, Codes methodargs) {
652
        Method m = new BaseMethod(instance, methodname, methodargs);
653
        return m;
654
    }
655
    
656
    @Override
657
    public Caller operator(String name, Code arg1) {
658
        BaseCodes args = args();
659
        args.add(arg1);
660
        return function(name, Caller.UNARY_OPERATOR, args);
661
    }
662

    
663
    @Override
664
    public Caller operator(String name, Code arg1, Code arg2) {
665
        BaseCodes args = args();
666
        args.add(arg1);
667
        args.add(arg2);
668
        return function(name, Caller.BINARY_OPERATOR, args);
669
    }
670
    
671
    @Override
672
    public Code not(Code op1) {
673
        return operator(OPERATOR_NOT, op1);
674
    }
675

    
676
    @Override
677
    public Code negate(Code op1) {
678
        return operator(OPERATOR_NEGATE, op1);
679
    }
680

    
681
    @Override
682
    public Code concat(Code op1, Code op2) {
683
        return operator(OPERATOR_CONCAT, op1, op2);
684
    }
685

    
686
    @Override
687
    public Code add(Code op1, Code op2) {
688
        return operator(OPERATOR_ADD, op1, op2);
689
    }
690

    
691
    @Override
692
    public Code subst(Code op1, Code op2) {
693
        return operator(OPERATOR_SUBST, op1, op2);
694
    }
695

    
696
    @Override
697
    public Code mult(Code op1, Code op2) {
698
        return operator(OPERATOR_MULT, op1, op2);
699
    }
700

    
701
    @Override
702
    public Code div(Code op1, Code op2) {
703
        return operator(OPERATOR_DIV, op1, op2);
704
    }
705

    
706
    @Override
707
    public Code mod(Code op1, Code op2) {
708
        return operator(OPERATOR_MOD, op1, op2);
709
    }
710

    
711
    @Override
712
    public Code or(Code op1, Code op2) {
713
        return operator(OPERATOR_OR, op1, op2);
714
    }
715

    
716
    @Override
717
    public Code and(Code op1, Code op2) {
718
        return operator(OPERATOR_AND, op1, op2);
719
    }
720

    
721
    @Override
722
    public Code like(Code op1, Code op2) {
723
        return operator(OPERATOR_LIKE, op1, op2);
724
    }
725

    
726
    @Override
727
    public Code ilike(Code op1, Code op2) {
728
        return operator(OPERATOR_ILIKE, op1, op2);
729
    }
730

    
731
    @Override
732
    public Code regexp(Code op1, Code op2) {
733
        return operator(OPERATOR_REGEXP, op1, op2);
734
    }
735

    
736
    @Override
737
    public Code lt(Code op1, Code op2) {
738
        return operator(OPERATOR_LT, op1, op2);
739
    }
740

    
741
    @Override
742
    public Code gt(Code op1, Code op2) {
743
        return operator(OPERATOR_GT, op1, op2);
744
    }
745

    
746
    @Override
747
    public Code le(Code op1, Code op2) {
748
        return operator(OPERATOR_LE, op1, op2);
749
    }
750

    
751
    @Override
752
    public Code ge(Code op1, Code op2) {
753
        return operator(OPERATOR_GE, op1, op2);
754
    }
755

    
756
    @Override
757
    public Code eq(Code op1, Code op2) {
758
        return operator(OPERATOR_EQ, op1, op2);
759
    }
760

    
761
    @Override
762
    public Code ne(Code op1, Code op2) {
763
        return operator(OPERATOR_NE, op1, op2);
764
    }
765

    
766
    @Override
767
    public Code is(Code op1, Code op2) {
768
        return operator(OPERATOR_IS, op1, op2);
769
    }
770

    
771
    @Override
772
    public Code getattr(Code obj, String attrname) {
773
        BaseCodes args = args();
774
        args.add(obj);
775
        args.add(constant(attrname));
776
        return function(GetattrFunction.NAME, args);
777
    }    
778

    
779
    @Override
780
    public Code getitem(Code obj, Code index) {
781
        BaseCodes args = args();
782
        args.add(obj);
783
        args.add(index);
784
        return function(GetitemFunction.NAME, args);
785
    }
786

    
787
    
788
    
789
}