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 / DefaultExpressionEvaluatorManager.java @ 44644

History | View | Annotate | Download (14.9 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.io.StringWriter;
4
import java.net.URI;
5
import java.util.ArrayList;
6
import org.gvsig.expressionevaluator.Grammar;
7
import org.gvsig.expressionevaluator.GrammarFactory;
8
import java.util.Collection;
9
import java.util.HashMap;
10
import java.util.List;
11
import java.util.Map;
12
import java.util.Objects;
13
import java.util.regex.Matcher;
14
import java.util.regex.Pattern;
15
import org.apache.commons.io.FilenameUtils;
16
import org.apache.commons.io.IOUtils;
17
import org.apache.commons.lang3.ArrayUtils;
18
import org.apache.commons.lang3.StringUtils;
19
import org.gvsig.expressionevaluator.Code;
20
import org.gvsig.expressionevaluator.CodeBuilder;
21
import org.gvsig.expressionevaluator.Expression;
22
import org.gvsig.expressionevaluator.ExpressionBuilder;
23
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
24
import org.gvsig.expressionevaluator.Interpreter;
25
import org.gvsig.expressionevaluator.LexicalAnalyzer;
26
import org.gvsig.expressionevaluator.MutableSymbolTable;
27
import org.gvsig.expressionevaluator.Optimizer;
28
import org.gvsig.expressionevaluator.SymbolTable;
29
import org.gvsig.expressionevaluator.SymbolTableFactory;
30
import org.gvsig.expressionevaluator.Compiler;
31
import org.gvsig.expressionevaluator.GrammarSet;
32
import org.gvsig.expressionevaluator.ReprMethod;
33
import org.gvsig.expressionevaluator.impl.repr.ReprNull;
34
import org.gvsig.expressionevaluator.impl.repr.ReprObject;
35
import org.gvsig.tools.bookmarksandhistory.Bookmarks;
36
import org.gvsig.tools.bookmarksandhistory.History;
37
import org.gvsig.tools.bookmarksandhistory.impl.BaseBookmarks;
38
import org.gvsig.tools.bookmarksandhistory.impl.BaseHistory;
39
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
40
import org.gvsig.tools.script.Script;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

    
44

    
45
@SuppressWarnings("UseSpecificCatch")
46
public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager {
47

    
48
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpressionEvaluatorManager.class);
49
    
50
    private Double accuracy;
51
    private final Map<String,SymbolTableFactory>symbolTableFactories;
52
    private final Map<String,GrammarFactory> grammarFactories;
53
    private Bookmarks<Expression> bookmarks;
54
    private History<Expression> history;
55
    private SymbolTable inmutableSymbolTable;
56
    private ResourcesStorage scriptsResourcesStorage;
57

    
58
    public DefaultExpressionEvaluatorManager() {
59
        this.symbolTableFactories = new HashMap<>();
60
        this.grammarFactories = new HashMap<>();
61
        this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
62
    }
63

    
64
    @Override
65
    public SymbolTable getSymbolTable(String name) {
66
        if( name == null ) {
67
            return null;
68
        }
69
        SymbolTableFactory factory = this.symbolTableFactories.get(name.toUpperCase());
70
        if( factory == null ) {
71
            return null;
72
        }
73
        return factory.create();
74
    }
75

    
76
    @Override
77
    public Collection<SymbolTableFactory> getSymbolTableFactories() {
78
        return this.symbolTableFactories.values();
79
    }
80

    
81
    @Override
82
    public final void registerSymbolTable(SymbolTableFactory factory) {
83
        if( factory == null ) {
84
            throw new IllegalArgumentException("factory can't be null");
85
        }
86
        this.symbolTableFactories.put(factory.getName().toUpperCase(),factory);
87
        this.inmutableSymbolTable = null;
88
    }
89

    
90
    @Override
91
    public SymbolTable getInmutableSymbolTable() {
92
        if( this.inmutableSymbolTable==null ) {
93
            this.inmutableSymbolTable = new InmutableSymbolTable();
94
        }
95
        return this.inmutableSymbolTable;
96
    }
97
    
98
    @Override
99
    public Object evaluate(String source) {
100
        DefaultInterpreter interpreter = new DefaultInterpreter();
101
        DefaultCompiler compiler = new DefaultCompiler(this);
102
        Code code = compiler.compileExpression(source);
103
        return interpreter.run(code);
104
    }
105
    
106
    @Override
107
    public Object evaluate(SymbolTable symbolTable, String source) {
108
        DefaultInterpreter interpreter = new DefaultInterpreter();
109
        DefaultCompiler compiler = new DefaultCompiler(this);
110
        Code code = compiler.compileExpression(source);
111
        if( symbolTable!=null ) {
112
            interpreter.setSymbolTable(symbolTable);
113
        }
114
        return interpreter.run(code);
115
    }
116

    
117
    @Override
118
    public Object evaluate(SymbolTable symbolTable, Code code) {
119
        DefaultInterpreter interpreter = new DefaultInterpreter();
120
        if( symbolTable!=null ) {
121
            interpreter.setSymbolTable(symbolTable);
122
        }
123
        return interpreter.run(code);
124
    }
125

    
126
    @Override
127
    public String evaluateDynamicText(String source) {
128
        return evaluateDynamicText(null, source);
129
    }
130
    
131
    @Override
132
    public boolean isDynamicText(String source) {
133
        String[] sources = StringUtils.substringsBetween(source, "<%", "%>");
134
        if( ArrayUtils.isEmpty(sources) ) {
135
            return false;
136
        }
137
        return true;
138
    }
139
    
140
    @Override
141
    public String evaluateDynamicText(SymbolTable symbolTable, String source) {
142
        String[] sources = StringUtils.substringsBetween(source, "<%", "%>");
143
        if( ArrayUtils.isEmpty(sources) ) {
144
            return source;
145
        }
146
        String[] values = new String[sources.length];
147
        
148
        DefaultInterpreter interpreter = new DefaultInterpreter();
149
        if( symbolTable!=null ) {
150
            interpreter.setSymbolTable(symbolTable);
151
        }
152
        StringWriter writer = new StringWriter();
153
        interpreter.setWriter(writer);
154
        DefaultCompiler compiler = new DefaultCompiler(this);
155
        for (int i = 0; i < sources.length; i++) {
156
            String theSource = sources[i];
157
            if( StringUtils.startsWith(theSource, "=") ) {
158
                Code code = compiler.compileExpression(theSource.substring(1));
159
                Object value = interpreter.run(code);
160
                values[i] = Objects.toString(value, "");
161
            } else {
162
                Code code = compiler.compileExpression(theSource.substring(1));
163
                writer.getBuffer().setLength(0);
164
                interpreter.run(code);
165
                values[i] = writer.toString();
166
            }
167
            sources[i] = "<%"+sources[i]+"%>";
168
        }
169
        String output = StringUtils.replaceEach(source, sources, values);
170
        return output;
171
    }
172
    
173
    @Override
174
    public Code compile(String source) {
175
        Compiler compiler = this.createCompiler();
176
        return compiler.compileExpression(source);
177
    }
178

    
179
    @Override
180
    public Code compile(LexicalAnalyzer lex, String source) {
181
        Compiler compiler = this.createCompiler();
182
        compiler.setLexicalAnalyzer(lex);
183
        return compiler.compileExpression(source);
184
    }
185

    
186
    @Override
187
    public Code optimize(SymbolTable symbolTable, Code code) {
188
        Optimizer optimizer = this.createOptimizer();
189
        return optimizer.optimize(symbolTable, code);
190
    }
191

    
192
    @Override
193
    public MutableSymbolTable createSymbolTable() {
194
        DefaultSymbolTable theSymbolTable = new DefaultSymbolTable();
195
        return theSymbolTable;
196
    }
197
    
198
    public void populateSymbolTable(SymbolTable aSymbolTable) {
199
        for (SymbolTableFactory factory : this.getSymbolTableFactories() ) {
200
            try {
201
                if( factory.isAutoload() ) {
202
                    SymbolTable symbolTable = factory.create();
203
                    aSymbolTable.addSymbolTable(symbolTable);
204
                }
205
            } catch(Throwable th) {
206
                String factoryName = "Unknown";
207
                try {
208
                    factoryName = factory.getName();
209
                } catch(Throwable th2) {
210
                    // Do nothing
211
                }
212
                LOGGER.warn("Can't create symbol table '"+factoryName+"'.", th);
213
            }
214
        }
215
    }
216
    
217
    @Override
218
    public LexicalAnalyzer createLexicalAnalyzer() {
219
        return new SQLLexicalAnalyzer();
220
    }
221

    
222
    @Override
223
    public CodeBuilder createCodeBuilder() {
224
        return new DefaultCodeBuilder(this);
225
    }
226

    
227
    @Override
228
    public Compiler createCompiler() {
229
        DefaultCompiler compiler = new DefaultCompiler(this);
230
        this.populateGrammars(compiler);
231
        return  compiler;
232
    }
233

    
234
    @Override
235
    public Interpreter createInterpreter() {
236
        Interpreter interpreter = new DefaultInterpreter();
237
        interpreter.setResourcesStorage(this.scriptsResourcesStorage);
238
        return interpreter;
239
    }
240

    
241
    @Override
242
    public Double getAccuracy() {
243
        return this.accuracy;
244
    }
245

    
246
    @Override
247
    public void setAccuracy(Double accuracy) {
248
        this.accuracy = accuracy;
249
    }
250

    
251
    @Override
252
    public Expression createExpression() {
253
        DefaultExpression e = new DefaultExpression(this);
254
        return e;
255
    }
256

    
257
    @Override
258
    public ExpressionBuilder createExpressionBuilder() {
259
        ExpressionBuilder x = new DefaultExpressionBuilder(this);
260
        return x;
261
    }
262

    
263
    @Override
264
    public Optimizer createOptimizer() {
265
        Optimizer x = new DefaultOptimizer(this);
266
        return x;
267
    }
268

    
269
    @Override
270
    public void registerGrammar(GrammarFactory factory) {
271
        if( factory==null ) {
272
            throw new IllegalArgumentException("factory can't be null");
273
        }
274
        this.grammarFactories.put(factory.getName(), factory);
275
    }
276

    
277
    @Override
278
    public Collection<GrammarFactory> getGrammarFactories() {
279
        return this.grammarFactories.values();
280
    }
281

    
282
    public void populateGrammars(Compiler compiler) {
283
        GrammarSet grammarSet = compiler.getGrammars();
284
        for (GrammarFactory factory : this.getGrammarFactories() ) {
285
            if( factory.isAutoload() ) {
286
                Grammar grammar = factory.create();
287
                grammarSet.add(grammar);
288
            }
289
        }
290
    }
291

    
292
    @Override
293
    public Grammar createGrammar(String name) {
294
        DefaultGrammar grammar = new DefaultGrammar(name);
295
        return grammar;
296
    }
297
    
298
    @Override
299
    public Bookmarks<Expression> getBookmarks() {
300
        if( this.bookmarks==null ) {
301
            this.bookmarks = new BaseBookmarks<>();
302
        }
303
        return this.bookmarks;
304
    }
305

    
306
    @Override
307
    public History<Expression> getHistory() {
308
        if( this.history==null ) {
309
            this.history = new BaseHistory<>(20);
310
        }
311
        return this.history;
312
    }
313
    
314
    @Override
315
    public Script createScript(String name, String code, String languaje) {
316
        SimpleScript sc = new SimpleScript(this.createInterpreter(), name, code);
317
        return sc;
318
    }
319

    
320
    @Override
321
    public Script locateScript(String name) {
322
        return loadScript(this.scriptsResourcesStorage, name);
323
    }
324

    
325
    @Override
326
    public Script loadScript(final URI location) {
327
        ResourcesStorage.Resource res = null;
328
        try {
329
            if( location==null ) {
330
                return null;
331
            }
332
            res = ResourcesStorage.createResource(location);
333
            if( res == null || !res.exists() ) {
334
                return null;
335
            }
336
            Script script = loadScript(res, FilenameUtils.getBaseName(location.getPath()));
337
            return script;
338
        } catch (Exception ex) {
339
            LOGGER.warn("Can't load script from URI.", ex);
340
            return null;
341
        } finally {
342
            IOUtils.closeQuietly(res);
343
        }
344
    }
345

    
346

    
347
    @Override
348
    public Script loadScript(ResourcesStorage storage, String name) {
349
        ResourcesStorage.Resource res = null;
350
        try {
351
            if( storage==null ) {
352
                return null;
353
            }
354
            res = storage.getResource(name);
355
            if( res == null || !res.exists() ) {
356
                return null;
357
            }
358
            Script script = loadScript(res, name);
359
            return script;
360
        } catch (Exception ex) {
361
            LOGGER.warn("Can't load script from resources storage.", ex);
362
            return null;
363
        } finally {
364
            IOUtils.closeQuietly(res);
365
        }
366

    
367
    }
368

    
369
    private static final Pattern RE_LANG = Pattern.compile(".*lang[:]\\s*([a-zA-Z_][a-zA-Z_0-9_]*).*");
370
    private static final Pattern RE_ENCODING = Pattern.compile(".*encoding[:]\\s*([a-zA-Z_][a-zA-Z0-9_-]*).*");
371
    
372
    private Script loadScript(ResourcesStorage.Resource res, String name) {
373
        try {
374
            if( res == null || !res.exists() ) {
375
                return null;
376
            }
377
            byte[] head_bytes = new byte[500];
378
            IOUtils.read(res.asInputStream(), head_bytes);
379
            IOUtils.closeQuietly(res);
380
            String head = new String(head_bytes);
381
            if( StringUtils.isEmpty(head) ) {
382
                return null;
383
            }
384
            head = StringUtils.split(head, "\n")[0];
385
            
386
            String lang = "cosa";
387
            String encoding = null;
388
            Matcher m = RE_LANG.matcher(head);
389
            if( m!=null && m.matches() && m.groupCount()==1 ) {
390
                String s = m.group(1);
391
                if( !StringUtils.isBlank(s) ) {
392
                    lang = s;
393
                }
394
            }
395
            m = RE_ENCODING.matcher(head);
396
            if( m!=null && m.matches() && m.groupCount()==1 ) {
397
                String s = m.group(1);
398
                if( !StringUtils.isBlank(s) ) {
399
                    encoding = s;
400
                }
401
            }
402

    
403
            String source;
404
            if( StringUtils.isBlank(encoding) ) {
405
                source = IOUtils.toString(res.asInputStream());
406
            } else {
407
                source = IOUtils.toString(res.asInputStream(), encoding);
408
            }
409
            Script script = this.createScript(name, source, lang);
410
            return script;
411
        } catch (Exception ex) {
412
            LOGGER.warn("Can't load script from resource.", ex);
413
            return null;
414
        } finally {
415
            IOUtils.closeQuietly(res);
416
        }
417

    
418
    }
419
    
420
    @Override
421
    public ResourcesStorage getScriptsResourcesStorage() {
422
        return this.scriptsResourcesStorage;
423
    }
424

    
425
    @Override
426
    public void setScriptsResourcesStorage(ResourcesStorage scriptsResourcesStorage) {
427
        this.scriptsResourcesStorage = scriptsResourcesStorage;
428
    }
429

    
430
    
431
    private final List<ReprMethod> reprMethods = new ArrayList<>();
432
    private final Map<Class,ReprMethod> reprMethodsCache = new HashMap<>();
433
    private final ReprMethod reprNull = new ReprNull();
434
    private final ReprMethod reprObject = new ReprObject();
435
    
436
    @Override
437
    public void addReprMethod(ReprMethod method) {
438
        this.reprMethods.add(method);
439
        this.reprMethodsCache.clear();
440
    }
441
    
442
    @Override
443
    public ReprMethod getReprMethod(Object value) {
444
        if( value == null ) {
445
            return this.reprNull;
446
        }
447
        ReprMethod method = this.reprMethodsCache.get(value.getClass());
448
        if( method!=null ) {
449
            return method;
450
        }
451
        for (ReprMethod theMethod : reprMethods) {
452
            if( theMethod.isApplicable(value) ) {
453
                this.reprMethodsCache.put(value.getClass(), theMethod);
454
                return theMethod;
455
            }
456
        }
457
        return this.reprObject;
458
    }
459
}
460