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 / test / java / org / gvsig / expresionevaluator / impl / TestCodeFormatter.java @ 44198

History | View | Annotate | Download (19.1 KB)

1
package org.gvsig.expresionevaluator.impl;
2

    
3
import java.text.MessageFormat;
4
import static junit.framework.Assert.assertEquals;
5
import junit.framework.TestCase;
6
import org.apache.commons.lang3.StringUtils;
7
import org.cresques.cts.IProjection;
8
import org.gvsig.expressionevaluator.Code;
9
import org.gvsig.expressionevaluator.Code.Caller;
10
import org.gvsig.expressionevaluator.Code.Constant;
11
import org.gvsig.expressionevaluator.Codes;
12
import org.gvsig.expressionevaluator.ExpressionBuilder;
13
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
14
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
15
import org.gvsig.expressionevaluator.ExpressionUtils;
16
import org.gvsig.expressionevaluator.Formatter;
17
import org.gvsig.expressionevaluator.LexicalAnalyzer;
18
import org.gvsig.fmap.crs.CRSFactory;
19
import org.gvsig.fmap.geom.Geometry;
20
import org.gvsig.fmap.geom.GeometryUtils;
21
import org.gvsig.fmap.geom.exception.CreateGeometryException;
22
import org.gvsig.fmap.geom.primitive.Point;
23
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
24

    
25
public class TestCodeFormatter extends TestCase {
26

    
27
    private static class MyFormatter implements Formatter<Code> {
28
    
29
        private class Formatter_constant_bytearray implements Formatter<Code> {
30

    
31
            @Override
32
            public boolean canApply(Code code) {
33
                if( code instanceof Constant ) {
34
                    return ((Constant)code).value() instanceof byte[];
35
                }
36
                return false;
37
            }
38

    
39
            @Override
40
            public String format(Code code) {
41
                return builder.bytearray_x((byte[]) ((Constant)code).value());
42
            }
43
        }
44

    
45
        private class Formatter_constant_geometry implements Formatter<Code> {
46

    
47
            @Override
48
            public boolean canApply(Code code) {
49
                if( code instanceof Constant ) {
50
                    return ((Constant)code).value() instanceof Geometry;
51
                }
52
                return false;
53
            }
54

    
55
            @Override
56
            public String format(Code code) {
57
                Geometry geometry = (Geometry) ((Constant)code).value();
58
                return MessageFormat.format(
59
                        "ST_GeomFromWKB(({0}), ({1}))",
60
                        builder.bytearray_x(GeometryUtils.toWKB(geometry)),
61
                        String.valueOf(builder.srs_id(geometry.getProjection()))
62
                );
63
                
64
            }
65
        }
66

    
67
        
68
        private class Formatter_ST_intersects_H2Spatial implements Formatter<Code> {
69
            // Need for H2Spatial
70
            @Override
71
            public boolean canApply(Code code) {
72
                if( code instanceof Caller ) {
73
                    return StringUtils.equalsIgnoreCase("ST_intersects",((Caller)code).name());
74
                }
75
                return false;
76
            }
77

    
78
            @Override
79
            public String format(Code code) {
80
                Codes parameters = ((Caller)code).parameters();
81
                String p1 = parameters.get(0).toString(MyFormatter.this);
82
                String p2 = parameters.get(1).toString(MyFormatter.this);
83
                String r = MessageFormat.format(
84
                        "( (({0}) && ({1})) AND ST_Intersects(({0}),({1}) ))", 
85
                        p1,
86
                        p2
87
                );
88
                return r;
89
            }
90
        }
91
  
92
        private class Formatter_ST_intersects_SpatiaLite implements Formatter<Code> {
93
            // Need for SpatiaLite
94

    
95
            private final String table;
96
            private final String geomcolumn;
97

    
98
            public Formatter_ST_intersects_SpatiaLite(String table, String geomcolumn) {
99
                this.table = table;
100
                this.geomcolumn = geomcolumn;
101
            }
102

    
103
            @Override
104
            public boolean canApply(Code code) {
105
                if( code instanceof Caller ) {
106
                    return StringUtils.equalsIgnoreCase("ST_intersects2",((Caller)code).name());
107
                }
108
                return false;
109
            }
110

    
111
            @Override
112
            public String format(Code code) {
113
                Codes parameters = ((Caller)code).parameters();
114
                String p1 = parameters.get(0).toString(MyFormatter.this);
115
                String p2 = parameters.get(1).toString(MyFormatter.this);
116
                String r = MessageFormat.format(
117
                    "(ST_Intersects({0},{1}) AND ROWID IN ( SELECT ROWID FROM SpatialIndex WHERE f_table_name = ''{2}'' AND f_geometry_column = ''{3}'' AND search_frame = \"{2}\".\"{3}\"))",
118
                    p1,
119
                    p2,
120
                    table,
121
                    geomcolumn
122
                );
123
                return r;
124
            }
125
        }
126
  
127
        private class Formatter_DECODE implements Formatter<Code> {
128
            // Need for SpatiaLite 
129
            @Override
130
            public boolean canApply(Code code) {
131
                if( code instanceof Caller ) {
132
                    if( StringUtils.equalsIgnoreCase("DECODE",((Caller)code).name()) ) {
133
                        Codes parameters = ((Caller)code).parameters();
134
                        Code code_p1 = parameters.get(0);
135
                        Code code_p2 = parameters.get(1);
136
                        if( code_p1 instanceof Constant && code_p2 instanceof Constant ) {
137
                            Object p1 = ((Constant)code_p1).value();
138
                            Object p2 = ((Constant)code_p2).value();
139
                            if( p1 instanceof String && p1 instanceof String && 
140
                                StringUtils.equalsIgnoreCase((CharSequence) p2,"hex") ) {
141
                                return true;
142
                            }
143
                        }
144
                    }
145
                }
146
                return false;
147
            }
148

    
149
            @Override
150
            public String format(Code code) {
151
                Codes parameters = ((Caller)code).parameters();
152
                Object p1 = ((Constant)parameters.get(0)).value();
153
                return "x'"+ (String)p1 + "'";
154
            }
155
        }
156
  
157
        private class Formatter_IFNULL implements Formatter<Code> {
158
            // Need for H2Spatial
159
            @Override
160
            public boolean canApply(Code code) {
161
                if( code instanceof Caller ) {
162
                    return StringUtils.equalsIgnoreCase("IFNULL",((Caller)code).name());
163
                }
164
                return false;
165
            }
166

    
167
            @Override
168
            public String format(Code code) {
169
                Codes parameters = ((Caller)code).parameters();
170
                String p1 = parameters.get(0).toString(MyFormatter.this);
171
                String p2 = parameters.get(1).toString(MyFormatter.this);
172
                String p3 = parameters.get(2).toString(MyFormatter.this);
173
                String r = MessageFormat.format(
174
                        "NVL2({0}, {1}, {2})", 
175
                        p1,
176
                        p3,
177
                        p2
178
                );
179
                return r;
180
            }
181
        }
182
    
183
        private class Formatter_ILIKE implements Formatter<Code> {
184
            // Need for SpatiaLite
185
            @Override
186
            public boolean canApply(Code code) {
187
                if( code instanceof Caller ) {
188
                    return StringUtils.equalsIgnoreCase("ILIKE",((Caller)code).name());
189
                }
190
                return false;
191
            }
192

    
193
            @Override
194
            public String format(Code code) {
195
                Codes parameters = ((Caller)code).parameters();
196
                String p1 = parameters.get(0).toString(MyFormatter.this);
197
                String p2 = parameters.get(1).toString(MyFormatter.this);
198
                String r = MessageFormat.format(
199
                        "LOWER({0}) LIKE LOWER({1})", 
200
                        p1,
201
                        p2
202
                );
203
                return r;
204
            }
205
        }
206
    
207
        private class Formatter_NOT_IS_NULL implements Formatter<Code> {
208
            // Need for H2Spatial
209
            @Override
210
            public boolean canApply(Code code) {
211
                if( code instanceof Caller ) {
212
                    return StringUtils.equalsIgnoreCase("NOT_IS_NULL",((Caller)code).name());
213
                }
214
                return false;
215
            }
216

    
217
            @Override
218
            public String format(Code code) {
219
                Codes parameters = ((Caller)code).parameters();
220
                String p1 = parameters.get(0).toString(MyFormatter.this);
221
                String r = MessageFormat.format(
222
                        "( ({0}) IS NOT NULL )", 
223
                        p1
224
                );
225
                return r;
226
            }
227
        }
228

    
229
        private final Formatter<Code>[] formatters;
230
        private final ExpressionBuilder builder;
231

    
232
        public MyFormatter() {
233
            this.builder = ExpressionUtils.createExpressionBuilder();
234
            this.formatters = new Formatter[] {
235
//                new Formatter_constant_bytearray(),
236
//                new Formatter_constant_geometry(),
237
                new Formatter_IFNULL(),
238
                new Formatter_NOT_IS_NULL(),
239
                new Formatter_ST_intersects_H2Spatial(),
240
                new Formatter_ST_intersects_SpatiaLite("mytable", "the_geom"),
241
                new Formatter_ILIKE(),
242
                new Formatter_DECODE(),
243
            };
244
        }
245

    
246
        @Override
247
        public boolean canApply(Code code) {
248
            for (Formatter<Code> formatter : formatters) {
249
                if( formatter.canApply(code) ) {
250
                    return true;
251
                }
252
            }
253
            return false;
254
        }
255

    
256
        @Override
257
        public String format(Code code) {
258
            for (Formatter<Code> formatter : formatters) {
259
                if( formatter.canApply(code) ) {
260
                    return formatter.format(code);
261
                }
262
            }
263
            return code.toString(this);
264
        }
265
        
266
    }
267
    
268
    public TestCodeFormatter(String testName) {
269
        super(testName);
270
    }
271

    
272
    @Override
273
    protected void setUp() throws Exception {
274
        super.setUp();
275
        new DefaultLibrariesInitializer().fullInitialize();
276
    }
277

    
278
    @Override
279
    protected void tearDown() throws Exception {
280
        super.tearDown();
281
    }
282

    
283
    // TODO add test methods here. The name must begin with 'test'. For example:
284
    // public void testHello() {}
285
    
286
    protected LexicalAnalyzer createLexicalAnalyzer() {
287
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
288
        LexicalAnalyzer lexer = manager.createLexicalAnalyzer();
289
        return lexer;
290
    }
291

    
292
    protected org.gvsig.expressionevaluator.Compiler createCompiler() {
293
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
294
        org.gvsig.expressionevaluator.Compiler compiler = manager.createCompiler();
295
        compiler.setLexicalAnalyzer(createLexicalAnalyzer());
296
        return compiler;
297
    }
298
    
299
    private Formatter<Code> formatter() {
300
        return new MyFormatter();
301
    }
302

    
303
    public Code compileExpression(String source) {
304
        org.gvsig.expressionevaluator.Compiler compiler = createCompiler();
305
        Code code = compiler.compileExpression(source);
306
        return code;
307
    }
308
    
309
    public void testIdentifier1() {
310
        String source = "precio";
311

    
312
        Code code = compileExpression(source);
313
        assertEquals("\"precio\"", code.toString(formatter()));
314
    }
315

    
316
    public void testIdentifier2() {
317
        org.gvsig.expressionevaluator.Compiler compiler = createCompiler();
318
        compiler.getLexicalAnalyzer().setUseBracketsForIdentifiers(true);
319

    
320
        String source = "[precio]";
321

    
322
        Code code = compiler.compileExpression(source);
323
        assertEquals("\"precio\"", code.toString(formatter()));
324
    }
325

    
326
    public void testIdentifier3() {
327
        String source = "\"precio\"";
328

    
329
        Code code = compileExpression(source);
330
        assertEquals("\"precio\"", code.toString(formatter()));
331
    }
332

    
333

    
334
    public void testTrue() {
335
        String source = "true";
336

    
337
        Code code = compileExpression(source);
338
        assertEquals("TRUE", code.toString(formatter()));
339
    }
340

    
341
    public void testFalse() {
342
        String source = "false";
343

    
344
        Code code = compileExpression(source);
345
        assertEquals("FALSE", code.toString(formatter()));
346
    }
347

    
348
    public void testNull() {
349
        String source = "null";
350

    
351
        Code code = compileExpression(source);
352
        assertEquals("NULL", code.toString(formatter()));
353
    }
354

    
355
    public void testNotTrue() {
356
        String source = "not true";
357

    
358
        Code code = compileExpression(source);
359
        assertEquals("NOT(TRUE)", code.toString(formatter()));
360
    }
361

    
362
    public void testInteger() {
363
        String source = "23";
364

    
365
        Code code = compileExpression(source);
366
        assertEquals("23", code.toString(formatter()));
367
    }
368

    
369
    public void operator(String operatorName) {
370
        String source = "precio " + operatorName + " 23";
371

    
372
        Code code = compileExpression(source);
373
        assertEquals("(\"precio\" "+ operatorName + " 23)", code.toString(formatter()));
374
    }
375
    
376
    public void testOperators() {
377

    
378
        operator("=");
379
        operator("<>");
380
        operator(">");
381
        operator(">=");
382
        operator("<");
383
        operator("<=");
384
        operator("LIKE");
385
//        operator("ILIKE");
386
        operator("||");
387
        operator("+");
388
        operator("-");
389
        operator("*");
390
        operator("OR");
391
        operator("AND");
392
        operator("%");
393
        operator("IS");
394

    
395
        operator("~");
396
    }
397

    
398
    public void testILike() {
399
        String source = "precio ILike 23";
400

    
401
        Code code = compileExpression(source);
402
        assertEquals("LOWER(\"precio\") LIKE LOWER(23)", code.toString(formatter()));
403
    }
404
    
405
    public void testAddMul() {
406
        String source = "precio + 10 * 2 + 20 + 30";
407

    
408
        Code code = compileExpression(source);
409
        assertEquals("(((\"precio\" + (10 * 2)) + 20) + 30)", code.toString(formatter()));
410
    }
411
    
412
    public void testAddMulPar() {
413
        String source = "(precio + 10) * 2 + 20 + 30";
414

    
415
        Code code = compileExpression(source);
416
        assertEquals("((((\"precio\" + 10) * 2) + 20) + 30)", code.toString(formatter()));
417
    }
418
    
419
    public void testAbs() {
420
        String source = "precio + abs(10)";
421

    
422
        Code code = compileExpression(source);
423
        assertEquals("(\"precio\" + abs(10))", code.toString(formatter()));
424
    }
425
    
426
    public void testAbs2() {
427
        String source = "precio + abs(-10)";
428

    
429
        Code code = compileExpression(source);
430
        assertEquals("(\"precio\" + abs(-(10)))", code.toString(formatter()));
431
    }
432
    
433
    public void testPI() {
434
        String source = "precio + PI()";
435

    
436
        Code code = compileExpression(source);
437
        assertEquals("(\"precio\" + PI())", code.toString(formatter()));
438
    }
439
    
440
    public void testCeil() {
441
        String source = "precio + CEIL(PI())";
442

    
443
        Code code = compileExpression(source);
444
        assertEquals("(\"precio\" + CEIL(PI()))", code.toString(formatter()));
445
    }
446
    
447
    public void testGetitem1() {
448
        String source = "LIST('uno','dos','tres')[1]" ;
449

    
450
        Code code = compileExpression(source);
451
        assertEquals("GETITEM(LIST('uno', 'dos', 'tres'), 1)", code.toString(formatter()));
452
    }
453
    
454
    public void testConcat() {
455
        String source = "CONCAT(precio,' euros')";
456

    
457
        Code code = compileExpression(source);
458
        assertEquals("CONCAT(\"precio\", ' euros')", code.toString(formatter()));
459
    }
460
    
461
    public void test1() {
462
        String source = "NOMBRE03 = 'Torre d''En Besora (la)'";
463

    
464
        Code code = compileExpression(source);
465
        assertEquals("(\"NOMBRE03\" = 'Torre d''En Besora (la)')", code.toString(formatter()));
466
    }
467
    
468
    public void test2() {
469
        org.gvsig.expressionevaluator.Compiler compiler = createCompiler();
470
        compiler.getLexicalAnalyzer().setUseBracketsForIdentifiers(true);
471

    
472
        String source = "[1990] = 0.168873933773767";
473

    
474
        Code code = compiler.compileExpression(source);
475
        assertEquals("(\"1990\" = 0.168873933773767)", code.toString(formatter()));
476
    }
477

    
478
    public void test2fields() {
479
        org.gvsig.expressionevaluator.Compiler compiler = createCompiler();
480
        compiler.getLexicalAnalyzer().setUseBracketsForIdentifiers(true);
481

    
482
        String source = "[1990] = [precio]";
483

    
484
        Code code = compiler.compileExpression(source);
485
        assertEquals("(\"1990\" = \"precio\")", code.toString(formatter()));
486
    }
487
    
488
    
489
    public void testInvokeFunction1() {
490
        String source = "ST_Area(GEOMETRY)";
491

    
492
        Code code = compileExpression(source);
493
        assertEquals("ST_Area(\"GEOMETRY\")", code.toString(formatter()));
494
    }
495

    
496
    public void test3() throws CreateGeometryException {
497
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
498

    
499
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
500
        Point point = GeometryUtils.createPoint(10, 20);
501

    
502
        builder.set(        
503
            builder.ST_Intersects(
504
              builder.geometry(point,proj),
505
              builder.variable("the_geom")
506
            )
507
        );
508
        Code code = compileExpression(builder.toString());
509
        assertEquals(
510
                "ST_Intersects(ST_GeomFromWKB(DECODE('000000000140240000000000004034000000000000', 'hex'), 4326), \"the_geom\")",
511
                code.toString()
512
        );
513
        assertEquals(
514
                "( ((ST_GeomFromWKB(x'000000000140240000000000004034000000000000', 4326)) && (\"the_geom\")) AND ST_Intersects((ST_GeomFromWKB(x'000000000140240000000000004034000000000000', 4326)),(\"the_geom\") ))",
515
                code.toString(formatter())
516
        );
517
    }
518
    
519
    public void test4() throws CreateGeometryException {
520
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
521

    
522
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
523
        Point point = GeometryUtils.createPoint(10, 20);
524

    
525
        builder.set(        
526
            builder.function("ST_Intersects2",
527
                builder.geometry(point,proj),
528
                builder.variable("the_geom")
529
            )
530
        );
531
        Code code = compileExpression(builder.toString());
532
        assertEquals(
533
                "ST_Intersects2(ST_GeomFromWKB(DECODE('000000000140240000000000004034000000000000', 'hex'), 4326), \"the_geom\")",
534
                code.toString()
535
        );
536
        assertEquals(
537
                "(ST_Intersects(ST_GeomFromWKB(x'000000000140240000000000004034000000000000', 4326),\"the_geom\") AND ROWID IN ( SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'mytable' AND f_geometry_column = 'the_geom' AND search_frame = \"mytable\".\"the_geom\"))",
538
                code.toString(formatter())
539
        );
540
    }
541
    
542
}