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

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 static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ADD;
23
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
24
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_CONCAT;
25
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_DIV;
26
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_EQ;
27
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GE;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GT;
29
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ILIKE;
30
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_IS;
31
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LE;
32
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LIKE;
33
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LT;
34
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MOD;
35
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MULT;
36
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NE;
37
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NEGATE;
38
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NOT;
39
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
40
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_REGEXP;
41
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_SUBST;
42
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
43
import org.gvsig.expressionevaluator.ExpressionUtils;
44
import org.gvsig.expressionevaluator.Formatter;
45
import org.gvsig.expressionevaluator.Function;
46
import org.gvsig.expressionevaluator.Interpreter;
47
import org.gvsig.expressionevaluator.SymbolTable;
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 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
        public void value(Object v) {
115
            this.value = v;
116
        }
117

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

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

    
163
    }
164

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

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

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

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

    
202
        private final String name;
203
        private final RecursionSupport recursionSupport;
204

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

    
210
        @Override
211
        public int code() {
212
            return IDENTIFIER;
213
        }
214

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

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

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

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

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

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

    
257
    }
258

    
259
    public class BaseCodes implements Codes {
260

    
261
        private final List<Code> codes;
262

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

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

    
280
        public void add(Code arg) {
281
            this.codes.add(arg);
282
        }
283

    
284
        @Override
285
        public Iterator<Code> iterator() {
286
            return this.codes.iterator();
287
        }
288

    
289
        @Override
290
        public Code get(int n) {
291
            return this.codes.get(n);
292
        }
293

    
294
        @Override
295
        public boolean isEmpty() {
296
            return this.codes.isEmpty();
297
        }
298

    
299
        @Override
300
        public List<Code> toList() {
301
            return Collections.unmodifiableList(this.codes);
302
        }
303

    
304
        @Override
305
        public void accept(Visitor visitor) throws BaseException {
306
            for( Code arg : this.codes ) {
307
                arg.accept(visitor);
308
            }
309
        }
310

    
311
        @Override
312
        public String toString() {
313
            return this.toString(EMPTY_FORMATTER);
314
        }
315
        
316
        @Override
317
        public Value toValue(ExpressionBuilder builder) {
318
            throw new UnsupportedOperationException();
319
        }
320

    
321
        @Override
322
        public Value toValue() {
323
            throw new UnsupportedOperationException();
324
        }
325

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

    
350
        @Override
351
        public void link(SymbolTable symbolTable) {
352
            for (Code code : this.codes) {
353
                code.link(symbolTable);
354
            }
355
        }
356

    
357
    }
358

    
359
    public class BaseCaller extends BaseCode implements Caller, RecursionControlSupport {
360

    
361
        private final String name;
362
        private final Codes args;
363
        private Function function;
364
        private final int type;
365
        private final RecursionSupport recursionSupport;
366

    
367
        public BaseCaller(String name, int type, Codes args) {
368
            this.name = name;
369
            this.args = args;
370
            this.type = type;
371
            this.function = null;
372
            this.recursionSupport = new RecursionSupport();
373
        }
374

    
375
        @Override
376
        public int code() {
377
            return CALLER;
378
        }
379

    
380
        @Override
381
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
382
            return this.function.call(interpreter, args);
383
        }
384

    
385
        @Override
386
        public String name() {
387
            return this.name;
388
        }
389

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

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

    
401
        @Override
402
        public Codes parameters() {
403
            return this.args;
404
        }
405

    
406
        @Override
407
        public int type() {
408
            return this.type;
409
        }
410

    
411
        @Override
412
        public void accept(Visitor visitor) throws BaseException {
413
            visitor.visit(this);
414
            if(this.args!=null) {
415
                this.args.accept(visitor);
416
            }
417
        }
418

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

    
446
            }
447
        }
448

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

    
492
        @Override
493
        public boolean enterCode(int max) {
494
            return this.recursionSupport.enterCode(max);
495
        }
496

    
497
        @Override
498
        public void exitCode() {
499
            this.recursionSupport.exitCode();
500
        }
501

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

    
508
    public class BaseMethod extends BaseCaller implements Method {
509

    
510
        private final Code obj;
511
        private final String methodname;
512
        
513
        public BaseMethod(Code obj, String methodname, Codes args) {
514
            super(methodname, FUNCTION, args);
515
            this.obj = obj;
516
            this.methodname = methodname;
517
        }
518

    
519
        @Override
520
        public int code() {
521
            return METHOD;
522
        }
523
        
524
        @Override
525
        public String methodname() {
526
            return this.methodname;
527
        }
528

    
529
        @Override
530
        public Code obj() {
531
            return this.obj;
532
        }
533

    
534
        @Override
535
        public String toString() {
536
            return this.toString(EMPTY_FORMATTER);
537
        }
538

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

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

    
576
    @Override
577
    public Constant constant(Object value) {
578
        return new BaseConstant(value);
579
    }
580

    
581
    @Override
582
    public Identifier identifier(String name) {
583
        return new BaseIdentifier(name);
584
    }
585

    
586
    @Override
587
    public BaseCodes args() {
588
        return new BaseCodes();
589
    }
590

    
591
    @Override
592
    public Caller function(String name, int type, Codes args) {
593
        return new BaseCaller(name, type, args);
594
    }
595

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

    
614
    @Override
615
    public Caller operator(String name, Code arg1, Code arg2) {
616
        BaseCodes args = args();
617
        args.add(arg1);
618
        args.add(arg2);
619
        return function(name, Caller.BINARY_OPERATOR, args);
620
    }
621
    
622
    @Override
623
    public Code not(Code op1) {
624
        return operator(OPERATOR_NOT, op1);
625
    }
626

    
627
    @Override
628
    public Code negate(Code op1) {
629
        return operator(OPERATOR_NEGATE, op1);
630
    }
631

    
632
    @Override
633
    public Code concat(Code op1, Code op2) {
634
        return operator(OPERATOR_CONCAT, op1, op2);
635
    }
636

    
637
    @Override
638
    public Code add(Code op1, Code op2) {
639
        return operator(OPERATOR_ADD, op1, op2);
640
    }
641

    
642
    @Override
643
    public Code subst(Code op1, Code op2) {
644
        return operator(OPERATOR_SUBST, op1, op2);
645
    }
646

    
647
    @Override
648
    public Code mult(Code op1, Code op2) {
649
        return operator(OPERATOR_MULT, op1, op2);
650
    }
651

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
722
    @Override
723
    public Code getattr(Code obj, String attrname) {
724
        BaseCodes args = args();
725
        args.add(obj);
726
        args.add(constant(attrname));
727
        return function(GetattrFunction.NAME, args);
728
    }    
729

    
730
    @Override
731
    public Code getitem(Code obj, Code index) {
732
        BaseCodes args = args();
733
        args.add(obj);
734
        args.add(index);
735
        return function(GetitemFunction.NAME, args);
736
    }
737

    
738
    
739
    
740
}