Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / feature / spi / ExpressionEvaluatorBase.java @ 43093

History | View | Annotate | Download (16.3 KB)

1

    
2
package org.gvsig.fmap.dal.feature.spi;
3

    
4
import gnu.jel.CompilationException;
5
import gnu.jel.CompiledExpression;
6
import gnu.jel.DVMap;
7
import java.util.ArrayList;
8
import java.util.Date;
9
import java.util.List;
10
import java.util.regex.Matcher;
11
import java.util.regex.Pattern;
12
import org.cresques.cts.IProjection;
13
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.Find_SRID;
14
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_AsBinary;
15
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_AsEWKB;
16
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_AsText;
17
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Contains;
18
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Crosses;
19
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Disjoint;
20
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Envelope;
21
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Equals;
22
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_GeomFromEWKB;
23
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_GeomFromText;
24
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_GeomFromWKB;
25
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Intersects;
26
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_IsClosed;
27
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Overlaps;
28
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_SRID;
29
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Touches;
30
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ST_Within;
31
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.isNull;
32
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.lcase;
33
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.notIsNull;
34
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_AND;
35
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_EQ;
36
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_GE;
37
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_GT;
38
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_ILIKE;
39
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_LE;
40
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_LIKE;
41
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_LT;
42
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_NE;
43
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_OR;
44
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.operator_not;
45
import static org.gvsig.fmap.dal.ExpressionBuilder.Config.ucase;
46
import org.gvsig.fmap.dal.ExpressionEvaluator;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.GeometryException;
49
import org.gvsig.fmap.geom.GeometryLocator;
50
import org.gvsig.fmap.geom.GeometryManager;
51
import org.gvsig.fmap.geom.operation.GeometryOperationException;
52
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
53
import org.gvsig.fmap.geom.primitive.Closeable;
54
import org.gvsig.fmap.geom.primitive.Envelope;
55
import org.gvsig.tools.evaluator.EvaluatorData;
56
import org.gvsig.tools.evaluator.EvaluatorException;
57
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
58

    
59

    
60
public class ExpressionEvaluatorBase extends ExpressionBuilderBase implements ExpressionEvaluator {
61

    
62
    public class JELConfig extends ConfigBase {
63
        
64
        public JELConfig() {
65
            super();
66
            
67
            this.set(has_spatial_functions,true);
68
            this.set(constant_true, "true");
69
            this.set(constant_false, "false");
70
            this.set(quote_for_identifiers, "");
71
            this.set(quote_for_strings, "\"");
72
            this.set(geometry_type_support, GeometrySupportType.WKT);
73
            this.set(group, "( {0} )");
74
            
75
            this.set(Find_SRID , "Find_SRID(({0}), ({1}), ({2}))");
76
            this.set(ST_SRID , "ST_SRID({0})");
77
            this.set(ST_AsText , "ST_AsText({0})");
78
            this.set(ST_AsBinary, "ST_AsBinary({0})");
79
            this.set(ST_AsEWKB, "ST_AsWKB({0})");
80
            this.set(ST_Contains, "ST_Contains(({0}), ({1}))");            
81
            this.set(ST_Crosses,  "ST_Crosses(({0}), ({1}))");
82
            this.set(ST_Disjoint ,  "ST_Disjoint(({0}), ({1}))");
83
            this.set(ST_Equals ,  "ST_Equals(({0}), ({1}))");
84
            this.set(ST_IsClosed,  "ST_IsClosed({0})");
85
            this.set(ST_Overlaps,  "ST_Overlaps(({0}), ({1}))");
86
            this.set(ST_Touches,  "ST_Touches(({0}), ({1}))");
87
            this.set(ST_Within, "ST_Within(({0}), ({1}))");            
88
            this.set(ST_Envelope, "ST_Envelope({0})");
89
            this.set(ST_Intersects, "ST_Intersects(({0}), ({1}))");
90
            this.set(ST_GeomFromText, "ST_GeomFromText({0}, ({1}))");
91
            this.set(ST_GeomFromWKB, "ST_GeomFromWKB(({0}), ({1}))");
92
            this.set(ST_GeomFromEWKB, "ST_GeomFromEWKB(({0}), ({1}))");
93
            this.set(lcase, "LCASE({0})");
94
            this.set(ucase, "UCASE({0})");
95
            this.set(isNull, "( ({0}) == null )");
96
            this.set(notIsNull, "( ! (({0}) == null) )");
97
            this.set(operator_not, "( ! ({0}) )");
98
            
99
            this.set(operator_AND, "{0} && {1}");
100
            this.set(operator_OR, "{0} || {1}");
101
            this.set(operator_EQ, "( ({0}) == ({1}) )");
102
            this.set(operator_NE, "( ({0}) != ({1}) )");
103
            this.set(operator_GT, "( ({0}) > ({1}) )");
104
            this.set(operator_GE, "( ({0}) >= ({1}) )");
105
            this.set(operator_LT, "( ({0}) < ({1}) )");
106
            this.set(operator_LE, "( ({0}) <= ({1}) )");
107
            this.set(operator_LIKE, "LIKE( ({0}), ({1}) )");
108
            this.set(operator_ILIKE, "ILIKE( ({0}), ({1}) )");
109

    
110
            this.set(operator_add, "{0} + {1}");
111
            this.set(operator_subst, "{0} - {1}");
112
            this.set(operator_mult, "{0} * {1}");
113
            this.set(operator_div, "{0} / {1}");
114
            this.set(operator_concat, "{0} + {1}");
115
        }
116
    }
117
    
118
    public static class JELFunctions {
119
        public static String Find_SRID(Object a, Object b, Object c) {
120
            return null;
121
        }
122
        
123
        public static String ST_SRID(Geometry geom) {
124
            return null;
125
        }
126
        
127
        public static String ST_AsText(Geometry geom) throws GeometryOperationException, GeometryOperationNotSupportedException {
128
            return geom.convertToWKT();
129
        }
130
        
131
        public static byte[] ST_AsBinary(Geometry geom) throws GeometryOperationException, GeometryOperationNotSupportedException {
132
            return geom.convertToWKB();
133
        }
134
        
135
        public static byte[] ST_AsEWKB(Geometry geom) throws GeometryOperationException, GeometryOperationNotSupportedException {
136
            return geom.convertToEWKB();
137
        }
138
        
139
        public static Envelope ST_Envelope(Geometry geom) throws GeometryOperationException, GeometryOperationNotSupportedException {
140
            return geom.getEnvelope();
141
        }            
142
        
143
        public static boolean ST_Contains(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
144
            return geom1.contains(geom2);
145
        }            
146
        
147
        public static boolean ST_Crosses(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
148
            return geom1.crosses(geom2);
149
        }            
150
        
151
        public static boolean ST_Disjoint(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
152
            return geom1.disjoint(geom2);
153
        }            
154
        
155
        public static boolean ST_Overlaps(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
156
            return geom1.overlaps(geom2);
157
        }            
158
        
159
        public static boolean ST_Touches(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
160
            return geom1.touches(geom2);
161
        }            
162
        
163
        public static boolean ST_Within(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
164
            return geom1.within(geom2);
165
        }            
166
        
167
        public static boolean ST_Intersects(Geometry geom1, Geometry geom2) throws GeometryOperationException, GeometryOperationNotSupportedException {
168
            return geom1.intersects(geom2);
169
        }            
170
        
171
        public static boolean ST_Equals(Geometry geom1, Geometry geom2) {
172
            return geom1.equals(geom2);
173
        }            
174
        
175
        public static boolean ST_IsClosed(Geometry geom1) throws GeometryOperationException, GeometryOperationNotSupportedException {
176
            if( geom1 instanceof Closeable  ) {
177
                return ((Closeable)geom1).isClosed();
178
            }
179
            return true;
180
        }            
181
        
182
        public static Geometry ST_GeomFromText(String geom, IProjection srs) throws GeometryException {
183
            GeometryManager manager = GeometryLocator.getGeometryManager();
184
            return manager.createFrom(geom,srs);
185
        }            
186
        
187
        public static Geometry ST_GeomFromWKB(byte[] geom, IProjection srs) throws GeometryException {
188
            GeometryManager manager = GeometryLocator.getGeometryManager();
189
            return manager.createFrom(geom,srs);
190
        }            
191
        
192
        public static Geometry ST_GeomFromEWKB(byte[] geom, IProjection srs) throws GeometryException {
193
            GeometryManager manager = GeometryLocator.getGeometryManager();
194
            return manager.createFrom(geom,srs);
195
        }            
196
            
197
        public static String LCASE(Object x) {
198
            if( x == null ) {
199
                return null;
200
            }
201
            return x.toString().toLowerCase();
202
        }            
203
            
204
        public static String UCASE(Object x) {
205
            if( x == null ) {
206
                return null;
207
            }
208
            return x.toString().toLowerCase();
209
        }            
210
          
211
        private static final Integer ZERO_OR_MORE_CHARS = 0;
212
        private static final Integer ONE_CHAR = 1;
213

    
214
        public static boolean LIKE(Object x1, Object x2) {
215
            if (x1 == null || x2 == null) {
216
                return false;
217
            }
218
            String source = x1.toString();
219
            String match = x2.toString();
220

    
221
            List<Object> format = new ArrayList<>();
222
            StringBuilder fill = new StringBuilder();
223
            final int plen = match.length();
224
            Character lastSymbol = null;
225
            for (int i = 0; i < plen; i++) {
226
                boolean f = false;
227
                char c = match.charAt(i);
228
                if (lastSymbol == '\\') {
229
                    lastSymbol = null;
230
                    fill.append(c);
231
                } else {
232
                    if (c == '%') {
233
                        if (fill.length() > 0) {
234
                            format.add(fill.toString());
235
                            fill.setLength(0);
236
                        }
237
                        format.add(ZERO_OR_MORE_CHARS);
238
                    } else if (c == '_') {
239
                        if (fill.length() > 0) {
240
                            format.add(fill.toString());
241
                            fill.setLength(0);
242
                        }
243
                        format.add(ONE_CHAR);
244
                    } else {
245
                        fill.append(c);
246
                    }
247
                    lastSymbol = c;
248
                }
249
                if (fill.length() > 0) {
250
                    format.add(fill.toString());
251
                }
252
            }
253

    
254
            StringBuilder repattern = new StringBuilder("^");
255
            for (Object o : format) {
256
                if (o == ZERO_OR_MORE_CHARS) {
257
                    repattern.append(".*?");
258
                } else if (o == ONE_CHAR) {
259
                    repattern.append(".?");
260
                } else {
261
                    repattern.append((String) o);
262
                }
263
            }
264

    
265
            Pattern pattern = Pattern.compile(repattern.toString());
266
            Matcher m = pattern.matcher(source);
267
            return m.find();
268
        }
269
            
270
        public static boolean ILIKE(Object x1, Object x2) {
271
            if (x1 == null || x2 == null) {
272
                return false;
273
            }
274
            x1 = x1.toString().toLowerCase();
275
            x2 = x2.toString().toLowerCase();
276
            return LIKE(x1, x2);
277
        }
278
            
279
    }
280
    
281
    protected class VariableProvider extends DVMap {
282
        private EvaluatorData data;
283

    
284
        public VariableProvider() {
285
        }
286
        
287
        public void setValues(EvaluatorData data) {
288
            this.data = data;
289
        }
290
        
291
        @Override
292
        public String getTypeName(String name) {
293
            Object value = this.data.getDataValue(name);
294
            return value.getClass().getSimpleName();
295
        }
296

    
297
        public double getDoubleProperty(String name) {
298
            Object value = this.data.getDataValue(name);
299
            return (double) value;
300
        }        
301

    
302
        public float getFloatProperty(String name) {
303
            Object value = this.data.getDataValue(name);
304
            return (float) (double) value;
305
        }        
306
        
307
        public int getIntegerProperty(String name) {
308
            Object value = this.data.getDataValue(name);
309
            return (int) (double) value;
310
        }        
311
        
312
        public long getLongProperty(String name) {
313
            Object value = this.data.getDataValue(name);
314
            return (long) (double) value;
315
        }        
316
        
317
        public String getStringProperty(String name) {
318
            Object value = this.data.getDataValue(name);
319
            return (String) value;
320
        }        
321

    
322
        public Date getDateProperty(String name) {
323
            Object value = this.data.getDataValue(name);
324
            return (Date) value;
325
        }        
326
    }
327
    
328
    protected VariableProvider jel_variables = null;
329
    protected Object[] jel_context = null;
330
    protected CompiledExpression jel_expression = null;
331
    protected Config jel_config = new JELConfig();
332
    protected EvaluatorFieldsInfo fieldsInfo = null; // For compatibility 
333
    
334
    public ExpressionEvaluatorBase() {
335
        super();
336
    }
337
    
338
    public void compile() {
339
        jel_variables = new VariableProvider();
340
        gnu.jel.Library lib = new gnu.jel.Library(
341
                new Class[]{ Math.class, JELFunctions.class }, 
342
                new Class[]{ jel_variables.getClass() }, 
343
                new Class[0],
344
                jel_variables,
345
                null
346
        );
347
        jel_context = new Object[] { jel_variables };
348
        Config config = this.config;
349
        try {
350
            this.config = jel_config;
351
            String expr = this.value.toString();
352
            jel_expression = gnu.jel.Evaluator.compile(expr, lib);
353
        } catch (CompilationException ex) {
354
            throw new RuntimeException("Can't compile expression.", ex);
355
        } finally {
356
            this.config = config;
357
        }
358
    }
359
    
360
    public void clear() {
361
        this.set(null);
362
        this.jel_expression = null;
363
    }
364
    
365
    @Override
366
    public Object evaluate(EvaluatorData data) throws EvaluatorException {
367
        try {
368
            if( jel_variables == null ) {
369
                this.compile();
370
            }
371
            jel_variables.setValues(data);
372
            return jel_expression.evaluate(jel_context);
373
        } catch (Throwable th) {
374
            throw new EvaluatorException(
375
                    "Can't evaluate expression", 
376
                    th, 
377
                    "ExpressionEvaluatorBase_evaluate_error", 
378
                    0
379
                );
380
        }
381
    }
382

    
383
    @Override
384
    public String getName() {
385
        return "Generic expression evaluator";
386
    }
387

    
388
    @Override
389
    public String getDescription() {
390
        return "";
391
    }
392

    
393
    @Override
394
    public String getSQL() {
395
        return this.value.toString();
396
    }
397

    
398
    @Override
399
    public EvaluatorFieldsInfo getFieldsInfo() {
400
        if( this.fieldsInfo==null ) {
401
            this.fieldsInfo = new EvaluatorFieldsInfo();
402
            for( Variable var : this.getVariables() ) {
403
                this.fieldsInfo.addFieldValue(var.getName());
404
            }
405
        }
406
        return this.fieldsInfo;
407
    }
408

    
409
    
410
    
411
}