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

History | View | Annotate | Download (15.4 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.GrammarSet;
33
import org.gvsig.expressionevaluator.ReprMethod;
34
import org.gvsig.expressionevaluator.impl.repr.ReprNull;
35
import org.gvsig.expressionevaluator.impl.repr.ReprObject;
36
import org.gvsig.tools.bookmarksandhistory.Bookmarks;
37
import org.gvsig.tools.bookmarksandhistory.History;
38
import org.gvsig.tools.bookmarksandhistory.impl.BaseBookmarks;
39
import org.gvsig.tools.bookmarksandhistory.impl.BaseHistory;
40
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
41
import org.gvsig.tools.script.Script;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
44

    
45

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

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

    
60
    public DefaultExpressionEvaluatorManager() {
61
        this.symbolTableFactories = new HashMap<>();
62
        this.grammarFactories = new HashMap<>();
63
        this.loaders = new ArrayList<>();
64
        this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
65
        this.loaders.add(this.getClass().getClassLoader());
66
    }
67

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

    
80
    @Override
81
    public Collection<SymbolTableFactory> getSymbolTableFactories() {
82
        return this.symbolTableFactories.values();
83
    }
84

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

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

    
121
    @Override
122
    public Object evaluate(SymbolTable symbolTable, Code code) {
123
        DefaultInterpreter interpreter = new DefaultInterpreter();
124
        if( symbolTable!=null ) {
125
            interpreter.setSymbolTable(symbolTable);
126
        }
127
        return interpreter.run(code);
128
    }
129

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

    
183
    @Override
184
    public Code compile(LexicalAnalyzer lex, String source) {
185
        Compiler compiler = this.createCompiler();
186
        compiler.setLexicalAnalyzer(lex);
187
        return compiler.compileExpression(source);
188
    }
189

    
190
    @Override
191
    public Code optimize(SymbolTable symbolTable, Code code) {
192
        Optimizer optimizer = this.createOptimizer();
193
        return optimizer.optimize(symbolTable, code);
194
    }
195

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

    
226
    @Override
227
    public CodeBuilder createCodeBuilder() {
228
        return new DefaultCodeBuilder(this);
229
    }
230

    
231
    @Override
232
    public Compiler createCompiler() {
233
        DefaultCompiler compiler = new DefaultCompiler(this);
234
        this.populateGrammars(compiler);
235
        return  compiler;
236
    }
237

    
238
    @Override
239
    public Interpreter createInterpreter() {
240
        Interpreter interpreter = new DefaultInterpreter();
241
        interpreter.setResourcesStorage(this.scriptsResourcesStorage);
242
        return interpreter;
243
    }
244

    
245
    @Override
246
    public Double getAccuracy() {
247
        return this.accuracy;
248
    }
249

    
250
    @Override
251
    public void setAccuracy(Double accuracy) {
252
        this.accuracy = accuracy;
253
    }
254

    
255
    @Override
256
    public Expression createExpression() {
257
        DefaultExpression e = new DefaultExpression(this);
258
        return e;
259
    }
260

    
261
    @Override
262
    public ExpressionBuilder createExpressionBuilder() {
263
        ExpressionBuilder x = new DefaultExpressionBuilder(this);
264
        return x;
265
    }
266

    
267
    @Override
268
    public Optimizer createOptimizer() {
269
        Optimizer x = new DefaultOptimizer(this);
270
        return x;
271
    }
272

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

    
281
    @Override
282
    public Collection<GrammarFactory> getGrammarFactories() {
283
        return this.grammarFactories.values();
284
    }
285

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

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

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

    
324
    @Override
325
    public Script locateScript(String name) {
326
        return loadScript(this.scriptsResourcesStorage, name);
327
    }
328

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

    
351

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

    
372
    }
373

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

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

    
423
    }
424
    
425
    @Override
426
    public ResourcesStorage getScriptsResourcesStorage() {
427
        return this.scriptsResourcesStorage;
428
    }
429

    
430
    @Override
431
    public void setScriptsResourcesStorage(ResourcesStorage scriptsResourcesStorage) {
432
        this.scriptsResourcesStorage = scriptsResourcesStorage;
433
    }
434

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

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