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

History | View | Annotate | Download (16.4 KB)

1
package org.gvsig.expressionevaluator.impl;
2

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

    
51

    
52
@SuppressWarnings("UseSpecificCatch")
53
public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager {
54

    
55
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpressionEvaluatorManager.class);
56
    
57
    private Double accuracy;
58
    private final Map<String,SymbolTableFactory>symbolTableFactories;
59
    private final Map<String,GrammarFactory> grammarFactories;
60
    private Bookmarks<Object> bookmarks;
61
    private static final String BOOKMARKSANDHISTORY_NAME = "ExpressionManager";
62
    private History<Object> history;
63
    private SymbolTable inmutableSymbolTable;
64
    private ResourcesStorage scriptsResourcesStorage;
65
    private List<ClassLoader> loaders;
66
    private Formatter<ExpressionBuilder.Value> expressionBuilderFormatter;
67

    
68
    public DefaultExpressionEvaluatorManager() {
69
        this.symbolTableFactories = new HashMap<>();
70
        this.grammarFactories = new HashMap<>();
71
        this.loaders = new ArrayList<>();
72
        this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
73
        this.loaders.add(this.getClass().getClassLoader());
74
        this.expressionBuilderFormatter = new BaseFormatter();
75
    }
76

    
77
    @Override
78
    public SymbolTable getSymbolTable(String name) {
79
        if( name == null ) {
80
            return null;
81
        }
82
        SymbolTableFactory factory = this.symbolTableFactories.get(name.toUpperCase());
83
        if( factory == null ) {
84
            return null;
85
        }
86
        return factory.create();
87
    }
88

    
89
    @Override
90
    public Collection<SymbolTableFactory> getSymbolTableFactories() {
91
        return this.symbolTableFactories.values();
92
    }
93

    
94
    @Override
95
    public final void registerSymbolTable(SymbolTableFactory factory) {
96
        if( factory == null ) {
97
            throw new IllegalArgumentException("factory can't be null");
98
        }
99
        this.symbolTableFactories.put(factory.getName().toUpperCase(),factory);
100
        this.inmutableSymbolTable = null;
101
    }
102

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

    
130
    @Override
131
    public Object evaluate(SymbolTable symbolTable, Code code) {
132
        DefaultInterpreter interpreter = new DefaultInterpreter();
133
        if( symbolTable!=null ) {
134
            interpreter.setSymbolTable(symbolTable);
135
        }
136
        return interpreter.run(code);
137
    }
138

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

    
192
    @Override
193
    public Code compile(LexicalAnalyzer lex, String source) {
194
        Compiler compiler = this.createCompiler();
195
        compiler.setLexicalAnalyzer(lex);
196
        return compiler.compileExpression(source);
197
    }
198

    
199
    @Override
200
    public Code optimize(SymbolTable symbolTable, Code code) {
201
        Optimizer optimizer = this.createOptimizer();
202
        return optimizer.optimize(symbolTable, code);
203
    }
204

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

    
236
    @Override
237
    public CodeBuilder createCodeBuilder() {
238
        return new DefaultCodeBuilder(this);
239
    }
240

    
241
    @Override
242
    public Compiler createCompiler() {
243
        DefaultCompiler compiler = new DefaultCompiler(this);
244
        this.populateGrammars(compiler);
245
        return  compiler;
246
    }
247

    
248
    @Override
249
    public Interpreter createInterpreter() {
250
        Interpreter interpreter = new DefaultInterpreter();
251
        interpreter.setResourcesStorage(this.scriptsResourcesStorage);
252
        return interpreter;
253
    }
254

    
255
    @Override
256
    public Double getAccuracy() {
257
        return this.accuracy;
258
    }
259

    
260
    @Override
261
    public void setAccuracy(Double accuracy) {
262
        this.accuracy = accuracy;
263
    }
264

    
265
    @Override
266
    public Expression createExpression() {
267
        DefaultExpression e = new DefaultExpression(this);
268
        return e;
269
    }
270

    
271
    @Override
272
    public ExpressionBuilder createExpressionBuilder() {
273
        ExpressionBuilder x = new DefaultExpressionBuilder(this);
274
        return x;
275
    }
276

    
277
    @Override
278
    public Optimizer createOptimizer() {
279
        Optimizer x = new DefaultOptimizer(this);
280
        return x;
281
    }
282

    
283
    @Override
284
    public void registerGrammar(GrammarFactory factory) {
285
        if( factory==null ) {
286
            throw new IllegalArgumentException("factory can't be null");
287
        }
288
        this.grammarFactories.put(factory.getName(), factory);
289
    }
290

    
291
    @Override
292
    public Collection<GrammarFactory> getGrammarFactories() {
293
        return this.grammarFactories.values();
294
    }
295

    
296
    public void populateGrammars(Compiler compiler) {
297
        GrammarSet grammarSet = compiler.getGrammars();
298
        for (GrammarFactory factory : this.getGrammarFactories() ) {
299
            if( factory.isAutoload() ) {
300
                Grammar grammar = factory.create();
301
                grammarSet.add(grammar);
302
            }
303
        }
304
    }
305

    
306
    @Override
307
    public Grammar createGrammar(String name) {
308
        DefaultGrammar grammar = new DefaultGrammar(name);
309
        return grammar;
310
    }
311
    
312
    @Override
313
    public Bookmarks<Object> getBookmarks() {
314
        if( this.bookmarks==null ) {
315
             this.bookmarks = ToolsLocator.getBookmarksAndHistoryManager().getBookmarksGroup(BOOKMARKSANDHISTORY_NAME); //new BaseBookmarks<>();.
316

    
317
        }
318
        return this.bookmarks;
319
    }
320

    
321
    @Override
322
    public History<Object> getHistory() {
323
        if( this.history==null ) {
324
            this.history = ToolsLocator.getBookmarksAndHistoryManager().getHistoryGroup(BOOKMARKSANDHISTORY_NAME); //new BaseHistory<>(20);
325
        }
326
        return this.history;
327
    }
328
    
329
    @Override
330
    public Script createScript(String name, String code, String languaje) {
331
        SimpleScript sc = new SimpleScript(this.createInterpreter(), name, code);
332
        return sc;
333
    }
334

    
335
    @Override
336
    public Script locateScript(String name) {
337
        return loadScript(this.scriptsResourcesStorage, name);
338
    }
339

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

    
362

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

    
383
    }
384

    
385
    private static final Pattern RE_LANG = Pattern.compile(".*lang[:]\\s*([a-zA-Z_][a-zA-Z_0-9_]*).*");
386
    private static final Pattern RE_ENCODING = Pattern.compile(".*encoding[:]\\s*([a-zA-Z_][a-zA-Z0-9_-]*).*");
387
    
388
    private Script loadScript(ResourcesStorage.Resource res, String name) {
389
        try {
390
            if( res == null || !res.exists() ) {
391
                return null;
392
            }
393
            String head = EncodingUtils.getFirstLine(res.asInputStream());
394
            IOUtils.closeQuietly(res); // Eliminar con org.gvsig.tools > 3.0.230
395
            if( StringUtils.isEmpty(head) ) {
396
                return null;
397
            }
398
            
399
            String encoding = EncodingUtils.getEncoding(head);
400
            
401
            String lang = "cosa";
402
            Matcher m = RE_LANG.matcher(head);
403
            if( m!=null && m.matches() && m.groupCount()==1 ) {
404
                String s = m.group(1);
405
                if( !StringUtils.isBlank(s) ) {
406
                    lang = s;
407
                }
408
            }
409
            String source;
410
            if( StringUtils.isBlank(encoding) ) {
411
                source = IOUtils.toString(res.asInputStream());
412
            } else {
413
                source = IOUtils.toString(res.asInputStream(), encoding);
414
            }
415
            Script script = this.createScript(name, source, lang);
416
            return script;
417
        } catch (Exception ex) {
418
            LOGGER.warn("Can't load script from resource.", ex);
419
            return null;
420
        } finally {
421
            IOUtils.closeQuietly(res);
422
        }
423

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

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

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

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

    
476
    @Override
477
    public Formatter<ExpressionBuilder.Value> getExpressionBuilderFormatter() {
478
      return expressionBuilderFormatter;
479
    }
480

    
481
    @Override
482
    public void registerExpressionBuilderFormatter(Formatter<ExpressionBuilder.Value> formatter) {
483
      this.expressionBuilderFormatter = formatter;
484
    }
485

    
486
    @Override
487
    public ExpressionEvaluator createExpressionEvaluator(Expression expression) {
488
        return new BaseExpressionEvaluator(expression);
489
    }
490
    
491
}
492