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

History | View | Annotate | Download (16.1 KB)

1
package org.gvsig.expressionevaluator.impl;
2

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

    
49

    
50
@SuppressWarnings("UseSpecificCatch")
51
public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager {
52

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
315
        }
316
        return this.bookmarks;
317
    }
318

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

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

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

    
360

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

    
381
    }
382

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

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

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

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

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

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

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