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

History | View | Annotate | Download (15.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.Collections;
10
import java.util.HashMap;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Objects;
14
import java.util.regex.Matcher;
15
import java.util.regex.Pattern;
16
import org.apache.commons.io.FilenameUtils;
17
import org.apache.commons.io.IOUtils;
18
import org.apache.commons.lang3.ArrayUtils;
19
import org.apache.commons.lang3.StringUtils;
20
import org.gvsig.expressionevaluator.Code;
21
import org.gvsig.expressionevaluator.CodeBuilder;
22
import org.gvsig.expressionevaluator.Expression;
23
import org.gvsig.expressionevaluator.ExpressionBuilder;
24
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
25
import org.gvsig.expressionevaluator.Interpreter;
26
import org.gvsig.expressionevaluator.LexicalAnalyzer;
27
import org.gvsig.expressionevaluator.MutableSymbolTable;
28
import org.gvsig.expressionevaluator.Optimizer;
29
import org.gvsig.expressionevaluator.SymbolTable;
30
import org.gvsig.expressionevaluator.SymbolTableFactory;
31
import org.gvsig.expressionevaluator.Compiler;
32
import org.gvsig.expressionevaluator.Formatter;
33
import org.gvsig.expressionevaluator.GrammarSet;
34
import org.gvsig.expressionevaluator.ReprMethod;
35
import org.gvsig.expressionevaluator.impl.repr.ReprNull;
36
import org.gvsig.expressionevaluator.impl.repr.ReprObject;
37
import org.gvsig.expressionevaluator.spi.formatter.value.BaseFormatter;
38
import org.gvsig.tools.bookmarksandhistory.Bookmarks;
39
import org.gvsig.tools.bookmarksandhistory.History;
40
import org.gvsig.tools.bookmarksandhistory.impl.BaseBookmarks;
41
import org.gvsig.tools.bookmarksandhistory.impl.BaseHistory;
42
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
43
import org.gvsig.tools.script.Script;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47

    
48
@SuppressWarnings("UseSpecificCatch")
49
public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager {
50

    
51
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpressionEvaluatorManager.class);
52
    
53
    private Double accuracy;
54
    private final Map<String,SymbolTableFactory>symbolTableFactories;
55
    private final Map<String,GrammarFactory> grammarFactories;
56
    private Bookmarks<Expression> bookmarks;
57
    private History<Expression> history;
58
    private SymbolTable inmutableSymbolTable;
59
    private ResourcesStorage scriptsResourcesStorage;
60
    private List<ClassLoader> loaders;
61
    private Formatter<ExpressionBuilder.Value> expressionBuilderFormatter;
62

    
63
    public DefaultExpressionEvaluatorManager() {
64
        this.symbolTableFactories = new HashMap<>();
65
        this.grammarFactories = new HashMap<>();
66
        this.loaders = new ArrayList<>();
67
        this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
68
        this.loaders.add(this.getClass().getClassLoader());
69
        this.expressionBuilderFormatter = new BaseFormatter();
70
    }
71

    
72
    @Override
73
    public SymbolTable getSymbolTable(String name) {
74
        if( name == null ) {
75
            return null;
76
        }
77
        SymbolTableFactory factory = this.symbolTableFactories.get(name.toUpperCase());
78
        if( factory == null ) {
79
            return null;
80
        }
81
        return factory.create();
82
    }
83

    
84
    @Override
85
    public Collection<SymbolTableFactory> getSymbolTableFactories() {
86
        return this.symbolTableFactories.values();
87
    }
88

    
89
    @Override
90
    public final void registerSymbolTable(SymbolTableFactory factory) {
91
        if( factory == null ) {
92
            throw new IllegalArgumentException("factory can't be null");
93
        }
94
        this.symbolTableFactories.put(factory.getName().toUpperCase(),factory);
95
        this.inmutableSymbolTable = null;
96
    }
97

    
98
    @Override
99
    public SymbolTable getInmutableSymbolTable() {
100
        if( this.inmutableSymbolTable==null ) {
101
            this.inmutableSymbolTable = new InmutableSymbolTable();
102
        }
103
        return this.inmutableSymbolTable;
104
    }
105
    
106
    @Override
107
    public Object evaluate(String source) {
108
        DefaultInterpreter interpreter = new DefaultInterpreter();
109
        DefaultCompiler compiler = new DefaultCompiler(this);
110
        Code code = compiler.compileExpression(source);
111
        return interpreter.run(code);
112
    }
113
    
114
    @Override
115
    public Object evaluate(SymbolTable symbolTable, String source) {
116
        DefaultInterpreter interpreter = new DefaultInterpreter();
117
        DefaultCompiler compiler = new DefaultCompiler(this);
118
        Code code = compiler.compileExpression(source);
119
        if( symbolTable!=null ) {
120
            interpreter.setSymbolTable(symbolTable);
121
        }
122
        return interpreter.run(code);
123
    }
124

    
125
    @Override
126
    public Object evaluate(SymbolTable symbolTable, Code code) {
127
        DefaultInterpreter interpreter = new DefaultInterpreter();
128
        if( symbolTable!=null ) {
129
            interpreter.setSymbolTable(symbolTable);
130
        }
131
        return interpreter.run(code);
132
    }
133

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

    
187
    @Override
188
    public Code compile(LexicalAnalyzer lex, String source) {
189
        Compiler compiler = this.createCompiler();
190
        compiler.setLexicalAnalyzer(lex);
191
        return compiler.compileExpression(source);
192
    }
193

    
194
    @Override
195
    public Code optimize(SymbolTable symbolTable, Code code) {
196
        Optimizer optimizer = this.createOptimizer();
197
        return optimizer.optimize(symbolTable, code);
198
    }
199

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

    
230
    @Override
231
    public CodeBuilder createCodeBuilder() {
232
        return new DefaultCodeBuilder(this);
233
    }
234

    
235
    @Override
236
    public Compiler createCompiler() {
237
        DefaultCompiler compiler = new DefaultCompiler(this);
238
        this.populateGrammars(compiler);
239
        return  compiler;
240
    }
241

    
242
    @Override
243
    public Interpreter createInterpreter() {
244
        Interpreter interpreter = new DefaultInterpreter();
245
        interpreter.setResourcesStorage(this.scriptsResourcesStorage);
246
        return interpreter;
247
    }
248

    
249
    @Override
250
    public Double getAccuracy() {
251
        return this.accuracy;
252
    }
253

    
254
    @Override
255
    public void setAccuracy(Double accuracy) {
256
        this.accuracy = accuracy;
257
    }
258

    
259
    @Override
260
    public Expression createExpression() {
261
        DefaultExpression e = new DefaultExpression(this);
262
        return e;
263
    }
264

    
265
    @Override
266
    public ExpressionBuilder createExpressionBuilder() {
267
        ExpressionBuilder x = new DefaultExpressionBuilder(this);
268
        return x;
269
    }
270

    
271
    @Override
272
    public Optimizer createOptimizer() {
273
        Optimizer x = new DefaultOptimizer(this);
274
        return x;
275
    }
276

    
277
    @Override
278
    public void registerGrammar(GrammarFactory factory) {
279
        if( factory==null ) {
280
            throw new IllegalArgumentException("factory can't be null");
281
        }
282
        this.grammarFactories.put(factory.getName(), factory);
283
    }
284

    
285
    @Override
286
    public Collection<GrammarFactory> getGrammarFactories() {
287
        return this.grammarFactories.values();
288
    }
289

    
290
    public void populateGrammars(Compiler compiler) {
291
        GrammarSet grammarSet = compiler.getGrammars();
292
        for (GrammarFactory factory : this.getGrammarFactories() ) {
293
            if( factory.isAutoload() ) {
294
                Grammar grammar = factory.create();
295
                grammarSet.add(grammar);
296
            }
297
        }
298
    }
299

    
300
    @Override
301
    public Grammar createGrammar(String name) {
302
        DefaultGrammar grammar = new DefaultGrammar(name);
303
        return grammar;
304
    }
305
    
306
    @Override
307
    public Bookmarks<Expression> getBookmarks() {
308
        if( this.bookmarks==null ) {
309
            this.bookmarks = new BaseBookmarks<>();
310
        }
311
        return this.bookmarks;
312
    }
313

    
314
    @Override
315
    public History<Expression> getHistory() {
316
        if( this.history==null ) {
317
            this.history = new BaseHistory<>(20);
318
        }
319
        return this.history;
320
    }
321
    
322
    @Override
323
    public Script createScript(String name, String code, String languaje) {
324
        SimpleScript sc = new SimpleScript(this.createInterpreter(), name, code);
325
        return sc;
326
    }
327

    
328
    @Override
329
    public Script locateScript(String name) {
330
        return loadScript(this.scriptsResourcesStorage, name);
331
    }
332

    
333
    @Override
334
    public Script loadScript(final URI location) {
335
        ResourcesStorage.Resource res = null;
336
        try {
337
            if( location==null ) {
338
                return null;
339
            }
340
            String resourceName = FilenameUtils.getBaseName(location.getPath());
341
            res = ResourcesStorage.createResource(resourceName, location);
342
            if( res == null || !res.exists() ) {
343
                return null;
344
            }
345
            Script script = loadScript(res, resourceName);
346
            return script;
347
        } catch (Exception ex) {
348
            LOGGER.warn("Can't load script from URI.", ex);
349
            return null;
350
        } finally {
351
            IOUtils.closeQuietly(res);
352
        }
353
    }
354

    
355

    
356
    @Override
357
    public Script loadScript(ResourcesStorage storage, String name) {
358
        ResourcesStorage.Resource res = null;
359
        try {
360
            if( storage==null ) {
361
                return null;
362
            }
363
            res = storage.getResource(name);
364
            if( res == null || !res.exists() ) {
365
                return null;
366
            }
367
            Script script = loadScript(res, name);
368
            return script;
369
        } catch (Exception ex) {
370
            LOGGER.warn("Can't load script from resources storage.", ex);
371
            return null;
372
        } finally {
373
            IOUtils.closeQuietly(res);
374
        }
375

    
376
    }
377

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

    
412
            String source;
413
            if( StringUtils.isBlank(encoding) ) {
414
                source = IOUtils.toString(res.asInputStream());
415
            } else {
416
                source = IOUtils.toString(res.asInputStream(), encoding);
417
            }
418
            Script script = this.createScript(name, source, lang);
419
            return script;
420
        } catch (Exception ex) {
421
            LOGGER.warn("Can't load script from resource.", ex);
422
            return null;
423
        } finally {
424
            IOUtils.closeQuietly(res);
425
        }
426

    
427
    }
428
    
429
    @Override
430
    public ResourcesStorage getScriptsResourcesStorage() {
431
        return this.scriptsResourcesStorage;
432
    }
433

    
434
    @Override
435
    public void setScriptsResourcesStorage(ResourcesStorage scriptsResourcesStorage) {
436
        this.scriptsResourcesStorage = scriptsResourcesStorage;
437
    }
438

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

    
469
    @Override
470
    public void registerClassLoader(ClassLoader loader) {
471
      this.loaders.add(loader);
472
    }
473
    
474
    @Override
475
    public List<ClassLoader> getClassLoaders() {
476
      return Collections.unmodifiableList(loaders);
477
    }
478

    
479
    @Override
480
    public Formatter<ExpressionBuilder.Value> getExpressionBuilderFormatter() {
481
      return expressionBuilderFormatter;
482
    }
483

    
484
    @Override
485
    public void registerExpressionBuilderFormatter(Formatter<ExpressionBuilder.Value> formatter) {
486
      this.expressionBuilderFormatter = formatter;
487
    }
488
    
489
}
490