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

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
                Function fn = symbolTable.function(caller.name());
91
                if( fn != null ) {
92
                    caller.function(fn);
93
                }
94
                if( caller.parameters() != null ) {
95
                    for( Code arg : caller.parameters() ) {
96
                        arg.link(symbolTable);
97
                    }
98
                }
99
            }
100
        }
101
    }
102

    
103
    class BaseConstant extends BaseCode implements Constant {
104

    
105
        private Object value;
106

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

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

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

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

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

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

    
170
    }
171

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

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

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

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

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

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

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

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

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

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

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

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

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

    
264
    }
265

    
266
    public class BaseCodes implements Codes {
267

    
268
        private final List<Code> codes;
269

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

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

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

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

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

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

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

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

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

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

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

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

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

    
368
    }
369

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

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

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

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

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

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

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

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

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

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

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

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

    
457
            }
458
        }
459

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

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

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

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

    
530
    public class BaseMethod extends BaseCode implements Method {
531

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
788
    
789
    
790
}