Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.geometry / org.gvsig.expressionevaluator.geometry.lib / org.gvsig.expressionevaluator.geometry.lib.impl / src / test / java / org / gvsig / expresionevaluator / impl / TestCodeFormatter.java @ 44644

History | View | Annotate | Download (13.5 KB)

1
package org.gvsig.expresionevaluator.impl;
2

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

    
24
public class TestCodeFormatter extends TestCase {
25

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

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

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

    
44
        private class Formatter_constant_geometry implements Formatter<Code> {
45

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

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

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

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

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

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

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

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

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

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

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

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

    
228
        private final Formatter<Code>[] formatters;
229
        private final GeometryExpressionBuilder builder;
230

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

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

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

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

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

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

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

    
302
    public Code compileExpression(String source) {
303
        org.gvsig.expressionevaluator.Compiler compiler = createCompiler();
304
        Code code = compiler.compileExpression(source);
305
        return code;
306
    }
307

    
308
    public void test3() throws CreateGeometryException {
309
        GeometryExpressionBuilder builder = GeometryExpressionUtils.createExpressionBuilder();
310

    
311
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
312
        Point point = GeometryUtils.createPoint(10, 20);
313

    
314
        builder.set(        
315
            builder.ST_Intersects(
316
              builder.geometry(point,proj),
317
              builder.variable("the_geom")
318
            )
319
        );
320
        Code code = compileExpression(builder.toString());
321
        assertEquals(
322
                "ST_Intersects(ST_GeomFromWKB(DECODE('000000000140240000000000004034000000000000', 'hex'), 4326), \"the_geom\")",
323
                code.toString()
324
        );
325
        assertEquals(
326
                "( ((ST_GeomFromWKB(x'000000000140240000000000004034000000000000', 4326)) && (\"the_geom\")) AND ST_Intersects((ST_GeomFromWKB(x'000000000140240000000000004034000000000000', 4326)),(\"the_geom\") ))",
327
                code.toString(formatter())
328
        );
329
    }
330
    
331
    public void test4() throws CreateGeometryException {
332
        GeometryExpressionBuilder builder = GeometryExpressionUtils.createExpressionBuilder();
333

    
334
        IProjection proj = CRSFactory.getCRS("EPSG:4326");
335
        Point point = GeometryUtils.createPoint(10, 20);
336

    
337
        builder.set(        
338
            builder.function("ST_Intersects2",
339
                builder.geometry(point,proj),
340
                builder.variable("the_geom")
341
            )
342
        );
343
        Code code = compileExpression(builder.toString());
344
        assertEquals(
345
                "ST_Intersects2(ST_GeomFromWKB(DECODE('000000000140240000000000004034000000000000', 'hex'), 4326), \"the_geom\")",
346
                code.toString()
347
        );
348
        assertEquals(
349
                "(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\"))",
350
                code.toString(formatter())
351
        );
352
    }
353
    
354
}