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

History | View | Annotate | Download (21.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.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.CodeBuilder;
20
import org.gvsig.expressionevaluator.Codes;
21
import org.gvsig.expressionevaluator.ExpressionBuilder;
22
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
23
import org.gvsig.expressionevaluator.ExpressionUtils;
24
import org.gvsig.expressionevaluator.Formatter;
25
import org.gvsig.expressionevaluator.Function;
26
import org.gvsig.expressionevaluator.Interpreter;
27
import org.gvsig.expressionevaluator.SymbolTable;
28
import org.gvsig.expressionevaluator.impl.function.operator.AddOperator;
29
import org.gvsig.expressionevaluator.impl.function.operator.AndOperator;
30
import org.gvsig.expressionevaluator.impl.function.operator.ConcatOperator;
31
import org.gvsig.expressionevaluator.impl.function.operator.DivOperator;
32
import org.gvsig.expressionevaluator.impl.function.operator.EqOperator;
33
import org.gvsig.expressionevaluator.impl.function.operator.GeOperator;
34
import org.gvsig.expressionevaluator.impl.function.operator.GtOperator;
35
import org.gvsig.expressionevaluator.impl.function.operator.IsOperator;
36
import org.gvsig.expressionevaluator.impl.function.operator.LeOperator;
37
import org.gvsig.expressionevaluator.impl.function.operator.LtOperator;
38
import org.gvsig.expressionevaluator.impl.function.operator.ModOperator;
39
import org.gvsig.expressionevaluator.impl.function.operator.MulOperator;
40
import org.gvsig.expressionevaluator.impl.function.operator.NeOperator;
41
import org.gvsig.expressionevaluator.impl.function.operator.NegOperator;
42
import org.gvsig.expressionevaluator.impl.function.operator.NotOperator;
43
import org.gvsig.expressionevaluator.impl.function.operator.OrOperator;
44
import org.gvsig.expressionevaluator.impl.function.operator.RegExpOperator;
45
import org.gvsig.expressionevaluator.impl.function.operator.SubstOperator;
46
import org.gvsig.expressionevaluator.impl.function.predicate.IlikeOperator;
47
import org.gvsig.expressionevaluator.impl.function.predicate.LikeOperator;
48
import org.gvsig.expressionevaluator.impl.function.programming.GetattrFunction;
49
import org.gvsig.expressionevaluator.impl.function.programming.GetitemFunction;
50
import org.gvsig.fmap.geom.Geometry;
51
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.visitor.Visitor;
53

    
54
@SuppressWarnings("UseSpecificCatch")
55
public class DefaultCodeBuilder implements CodeBuilder {
56

    
57
    public abstract class BaseCode implements Code {
58

    
59
        @Override
60
        public int code() {
61
            return UNDEFINED;
62
        }
63

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

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

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

    
96
    class BaseConstant extends BaseCode implements Constant {
97

    
98
        private final Object value;
99

    
100
        public BaseConstant(Object value) {
101
            this.value = value;
102
        }
103

    
104
        @Override
105
        public int code() {
106
            return CONSTANT;
107
        }
108

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

    
114
        @Override
115
        public Value toValue(ExpressionBuilder builder) {
116
            return builder.constant(this.value);
117
        }
118

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

    
159
    }
160

    
161
    public interface RecursionControlSupport {
162
        
163
        public boolean enterCode(int max);
164
        
165
        public void exitCode();
166
        
167
        public void resetRecursionState();
168
    }
169
    
170
    private class RecursionSupport implements RecursionControlSupport {
171
    
172
        private int counter;
173
        
174
        public RecursionSupport() {
175
            this.counter = 0;
176
        }
177

    
178
        @Override
179
        public boolean enterCode(int max) {
180
            this.counter += 1;
181
            return this.counter < max;
182
        }
183

    
184
        @Override
185
        public void exitCode() {
186
            this.counter -= 1;
187
        }
188

    
189
        @Override
190
        public void resetRecursionState() {
191
            this.counter = 0;
192
        }
193
        
194
    }
195
    
196
    public class BaseIdentifier extends BaseCode implements Identifier, RecursionControlSupport {
197

    
198
        private final String name;
199
        private final RecursionSupport recursionSupport;
200

    
201
        public BaseIdentifier(String name) {
202
            this.name = name;
203
            this.recursionSupport = new RecursionSupport();
204
        }
205

    
206
        @Override
207
        public int code() {
208
            return IDENTIFIER;
209
        }
210

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

    
216
        @Override
217
        public Value toValue(ExpressionBuilder builder) {
218
            return builder.variable(this.name);
219
        }
220

    
221
        @Override
222
        public String toString() {
223
            return this.toString(EMPTY_FORMATTER);
224
        }
225
        
226
        @Override
227
        public String toString(Formatter<Code> formatter) {
228
            if( formatter.canApply(this) ) {
229
                return formatter.format(this);
230
            }
231
            StringBuilder builder = new StringBuilder();
232
            builder.append("\"");
233
            builder.append(this.name());
234
            builder.append("\"");
235
            return builder.toString();
236
        }
237

    
238
        @Override
239
        public boolean enterCode(int max) {
240
            return this.recursionSupport.enterCode(max);
241
        }
242

    
243
        @Override
244
        public void exitCode() {
245
            this.recursionSupport.exitCode();
246
        }
247

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

    
253
    }
254

    
255
    public class BaseCodes implements Codes {
256

    
257
        private final List<Code> codes;
258

    
259
        public BaseCodes() {
260
            this.codes = new ArrayList<>();
261
        }
262

    
263
        @Override
264
        public int code() {
265
            return CODES;
266
        }
267
        
268
        @Override
269
        public int size() {
270
            if( codes == null ) {
271
                return 0;
272
            }
273
            return this.codes.size();
274
        }
275

    
276
        public void add(Code arg) {
277
            this.codes.add(arg);
278
        }
279

    
280
        @Override
281
        public Iterator<Code> iterator() {
282
            return this.codes.iterator();
283
        }
284

    
285
        @Override
286
        public Code get(int n) {
287
            return this.codes.get(n);
288
        }
289

    
290
        @Override
291
        public boolean isEmpty() {
292
            return this.codes.isEmpty();
293
        }
294

    
295
        @Override
296
        public List<Code> toList() {
297
            return Collections.unmodifiableList(this.codes);
298
        }
299

    
300
        @Override
301
        public void accept(Visitor visitor) throws BaseException {
302
            for( Code arg : this.codes ) {
303
                arg.accept(visitor);
304
            }
305
        }
306

    
307
        @Override
308
        public String toString() {
309
            return this.toString(EMPTY_FORMATTER);
310
        }
311
        
312
        @Override
313
        public Value toValue(ExpressionBuilder builder) {
314
            throw new UnsupportedOperationException();
315
        }
316

    
317
        @Override
318
        public Value toValue() {
319
            throw new UnsupportedOperationException();
320
        }
321

    
322
        @Override
323
        public String toString(Formatter<Code> formatter) {
324
            if( formatter.canApply(this) ) {
325
                return formatter.format(this);
326
            }
327
            if( codes != null ) {
328
                StringBuilder builder = new StringBuilder();
329
                boolean skipcoma = true;
330
                for( Code code : codes ) {
331
                    if( code == null ) {
332
                        continue;
333
                    }
334
                    if( skipcoma ) {
335
                        skipcoma = false;
336
                    } else {
337
                        builder.append(", ");
338
                    }
339
                    builder.append(code.toString(formatter));
340
                }
341
                return builder.toString();
342
            }
343
            return "";
344
        }
345

    
346
        @Override
347
        public void link(SymbolTable symbolTable) {
348
            for (Code code : this.codes) {
349
                code.link(symbolTable);
350
            }
351
        }
352

    
353
    }
354

    
355
    public class BaseCaller extends BaseCode implements Caller, RecursionControlSupport {
356

    
357
        private final String name;
358
        private final Codes args;
359
        private Function function;
360
        private final int type;
361
        private final RecursionSupport recursionSupport;
362

    
363
        public BaseCaller(String name, int type, Codes args) {
364
            this.name = name;
365
            this.args = args;
366
            this.type = type;
367
            this.function = null;
368
            this.recursionSupport = new RecursionSupport();
369
        }
370

    
371
        @Override
372
        public int code() {
373
            return CALLER;
374
        }
375

    
376
        @Override
377
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
378
            return this.function.call(interpreter, args);
379
        }
380

    
381
        @Override
382
        public String name() {
383
            return this.name;
384
        }
385

    
386
        @Override
387
        public Function function() {
388
            return this.function;
389
        }
390

    
391
        @Override
392
        public Function function(Function function) {
393
            this.function = function;
394
            return this.function;
395
        }
396

    
397
        @Override
398
        public Codes parameters() {
399
            return this.args;
400
        }
401

    
402
        @Override
403
        public int type() {
404
            return this.type;
405
        }
406

    
407
        @Override
408
        public void accept(Visitor visitor) throws BaseException {
409
            visitor.visit(this);
410
            if(this.args!=null) {
411
                this.args.accept(visitor);
412
            }
413
        }
414

    
415
        @Override
416
        public Value toValue(ExpressionBuilder builder) {
417
            switch(this.type) {
418
                case UNARY_OPERATOR:
419
                    return builder.function(
420
                            NegOperator.NAME.equalsIgnoreCase(this.name())?
421
                                "-" :
422
                                this.name(),
423
                            this.parameters().get(0).toValue(builder)
424
                    );
425
                case BINARY_OPERATOR:
426
                    return builder.binaryOperator(
427
                            this.name(),
428
                            this.parameters().get(0).toValue(builder),
429
                            this.parameters().get(1).toValue(builder)
430
                    );
431
                case FUNCTION:
432
                default:
433
                    ExpressionBuilder.Function f = builder.function(this.name());
434
                    if( this.parameters()!=null ) {
435
                        for (Code parameter : this.parameters()) {
436
                            f.parameter(parameter.toValue(builder));
437
                        }
438
                        
439
                    }
440
                    return f;
441

    
442
            }
443
        }
444

    
445
        @Override
446
        public String toString() {
447
            return this.toString(EMPTY_FORMATTER);
448
        }
449
        
450
        @Override
451
        public String toString(Formatter<Code> formatter) {
452
            if( formatter.canApply(this) ) {
453
                return formatter.format(this);
454
            }
455
            StringBuilder builder = new StringBuilder();
456
            switch(this.type) {
457
                case UNARY_OPERATOR:
458
                    if( NegOperator.NAME.equalsIgnoreCase(this.name()) ) {
459
                        builder.append("-");
460
                    } else {
461
                        builder.append(this.name());
462
                    }
463
                    builder.append("(");
464
                    builder.append(this.parameters().get(0).toString(formatter));
465
                    builder.append(")");
466
                    break;
467
                case BINARY_OPERATOR:
468
                    builder.append("(");
469
                    builder.append(this.parameters().get(0).toString(formatter));
470
                    builder.append(" ");
471
                    builder.append(this.name());
472
                    builder.append(" ");
473
                    builder.append(this.parameters().get(1).toString(formatter));
474
                    builder.append(")");
475
                    break;
476
                case FUNCTION:
477
                default:
478
                    builder.append(this.name());
479
                    builder.append("(");
480
                    if( this.parameters()!=null ) {
481
                        builder.append(this.parameters().toString(formatter));
482
                    }
483
                    builder.append(")");
484
            }
485
            return builder.toString();
486
        }
487

    
488
        @Override
489
        public boolean enterCode(int max) {
490
            return this.recursionSupport.enterCode(max);
491
        }
492

    
493
        @Override
494
        public void exitCode() {
495
            this.recursionSupport.exitCode();
496
        }
497

    
498
        @Override
499
        public void resetRecursionState() {
500
            this.recursionSupport.resetRecursionState();
501
        }
502
    }
503

    
504
    public class BaseMethod extends BaseCaller implements Method {
505

    
506
        private final Code obj;
507
        private final String methodname;
508
        
509
        public BaseMethod(Code obj, String methodname, Codes args) {
510
            super(methodname, FUNCTION, args);
511
            this.obj = obj;
512
            this.methodname = methodname;
513
        }
514

    
515
        @Override
516
        public int code() {
517
            return METHOD;
518
        }
519
        
520
        @Override
521
        public String methodname() {
522
            return this.methodname;
523
        }
524

    
525
        @Override
526
        public Code obj() {
527
            return this.obj;
528
        }
529

    
530
        @Override
531
        public String toString() {
532
            return this.toString(EMPTY_FORMATTER);
533
        }
534

    
535
        @Override
536
        public Value toValue(ExpressionBuilder builder) {
537
            ExpressionBuilder.Method m = builder.method(this.obj.toValue(builder), this.methodname);
538
            if( this.parameters()!=null ) {
539
                for (Code parameter : this.parameters()) {
540
                    m.parameter(parameter.toValue(builder));
541
                }
542
            }
543
            return m;
544
        }
545

    
546
        @Override
547
        public String toString(Formatter<Code> formatter) {
548
            if( formatter.canApply(this) ) {
549
                return formatter.format(this);
550
            }
551
            StringBuilder builder = new StringBuilder();
552
            builder.append(this.obj.toString(formatter));
553
            builder.append("->");
554
            builder.append(this.methodname());
555
            builder.append("(");
556
            if( this.parameters()!=null ) {
557
                builder.append(this.parameters().toString(formatter));
558
            }
559
            builder.append(")");
560
            return builder.toString();
561
        }
562
    }    
563
    
564
    @Override
565
    public CodeBuilder clone() throws CloneNotSupportedException {
566
        // This implementation of CodeBuilder does not maintain state, so 
567
        // we only call the super class.
568
        DefaultCodeBuilder other = (DefaultCodeBuilder) super.clone();
569
        return other;
570
    }
571

    
572
    @Override
573
    public Constant constant(Object value) {
574
        return new BaseConstant(value);
575
    }
576

    
577
    @Override
578
    public Identifier identifier(String name) {
579
        return new BaseIdentifier(name);
580
    }
581

    
582
    @Override
583
    public BaseCodes args() {
584
        return new BaseCodes();
585
    }
586

    
587
    @Override
588
    public Caller function(String name, int type, Codes args) {
589
        return new BaseCaller(name, type, args);
590
    }
591

    
592
    @Override
593
    public Caller function(String name, Codes args) {
594
        return function(name, Caller.FUNCTION, args);
595
    }
596
    
597
    @Override
598
    public Code method(Code obj, String methodname, Codes methodargs) {
599
        Method m = new BaseMethod(obj, methodname, methodargs);
600
        return m;
601
    }
602
    
603
    @Override
604
    public Caller operator(String name, Code arg1) {
605
        BaseCodes args = args();
606
        args.add(arg1);
607
        return function(name, Caller.UNARY_OPERATOR, args);
608
    }
609

    
610
    @Override
611
    public Caller operator(String name, Code arg1, Code arg2) {
612
        BaseCodes args = args();
613
        args.add(arg1);
614
        args.add(arg2);
615
        return function(name, Caller.BINARY_OPERATOR, args);
616
    }
617
    
618
    @Override
619
    public Code not(Code op1) {
620
        return operator(NotOperator.NAME, op1);
621
    }
622

    
623
    @Override
624
    public Code negate(Code op1) {
625
        return operator(NegOperator.NAME, op1);
626
    }
627

    
628
    @Override
629
    public Code concat(Code op1, Code op2) {
630
        return operator(ConcatOperator.NAME, op1, op2);
631
    }
632

    
633
    @Override
634
    public Code add(Code op1, Code op2) {
635
        return operator(AddOperator.NAME, op1, op2);
636
    }
637

    
638
    @Override
639
    public Code subst(Code op1, Code op2) {
640
        return operator(SubstOperator.NAME, op1, op2);
641
    }
642

    
643
    @Override
644
    public Code mult(Code op1, Code op2) {
645
        return operator(MulOperator.NAME, op1, op2);
646
    }
647

    
648
    @Override
649
    public Code div(Code op1, Code op2) {
650
        return operator(DivOperator.NAME, op1, op2);
651
    }
652

    
653
    @Override
654
    public Code mod(Code op1, Code op2) {
655
        return operator(ModOperator.NAME, op1, op2);
656
    }
657

    
658
    @Override
659
    public Code or(Code op1, Code op2) {
660
        return operator(OrOperator.NAME, op1, op2);
661
    }
662

    
663
    @Override
664
    public Code and(Code op1, Code op2) {
665
        return operator(AndOperator.NAME, op1, op2);
666
    }
667

    
668
    @Override
669
    public Code like(Code op1, Code op2) {
670
        return operator(LikeOperator.NAME, op1, op2);
671
    }
672

    
673
    @Override
674
    public Code ilike(Code op1, Code op2) {
675
        return operator(IlikeOperator.NAME, op1, op2);
676
    }
677

    
678
    @Override
679
    public Code regexp(Code op1, Code op2) {
680
        return operator(RegExpOperator.NAME, op1, op2);
681
    }
682

    
683
    @Override
684
    public Code lt(Code op1, Code op2) {
685
        return operator(LtOperator.NAME, op1, op2);
686
    }
687

    
688
    @Override
689
    public Code gt(Code op1, Code op2) {
690
        return operator(GtOperator.NAME, op1, op2);
691
    }
692

    
693
    @Override
694
    public Code le(Code op1, Code op2) {
695
        return operator(LeOperator.NAME, op1, op2);
696
    }
697

    
698
    @Override
699
    public Code ge(Code op1, Code op2) {
700
        return operator(GeOperator.NAME, op1, op2);
701
    }
702

    
703
    @Override
704
    public Code eq(Code op1, Code op2) {
705
        return operator(EqOperator.NAME, op1, op2);
706
    }
707

    
708
    @Override
709
    public Code ne(Code op1, Code op2) {
710
        return operator(NeOperator.NAME, op1, op2);
711
    }
712

    
713
    @Override
714
    public Code is(Code op1, Code op2) {
715
        return operator(IsOperator.NAME, op1, op2);
716
    }
717

    
718
    @Override
719
    public Code getattr(Code obj, String attrname) {
720
        BaseCodes args = args();
721
        args.add(obj);
722
        args.add(constant(attrname));
723
        return function(GetattrFunction.NAME, args);
724
    }    
725

    
726
    @Override
727
    public Code getitem(Code obj, Code index) {
728
        BaseCodes args = args();
729
        args.add(obj);
730
        args.add(index);
731
        return function(GetitemFunction.NAME, args);
732
    }
733

    
734
    
735
    
736
}