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

History | View | Annotate | Download (15.8 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.bookmarksandhistory.Bookmarks;
40
import org.gvsig.tools.bookmarksandhistory.History;
41
import org.gvsig.tools.bookmarksandhistory.impl.BaseBookmarks;
42
import org.gvsig.tools.bookmarksandhistory.impl.BaseHistory;
43
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
44
import org.gvsig.tools.script.Script;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
356

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

    
377
    }
378

    
379
    private static final Pattern RE_LANG = Pattern.compile(".*lang[:]\\s*([a-zA-Z_][a-zA-Z_0-9_]*).*");
380
    private static final Pattern RE_ENCODING = Pattern.compile(".*encoding[:]\\s*([a-zA-Z_][a-zA-Z0-9_-]*).*");
381
    
382
    private Script loadScript(ResourcesStorage.Resource res, String name) {
383
        try {
384
            if( res == null || !res.exists() ) {
385
                return null;
386
            }
387
            String head = EncodingUtils.getFirstLine(res.asInputStream());
388
            IOUtils.closeQuietly(res); // Eliminar con org.gvsig.tools > 3.0.230
389
            if( StringUtils.isEmpty(head) ) {
390
                return null;
391
            }
392
            
393
            String encoding = EncodingUtils.getEncoding(head);
394
            
395
            String lang = "cosa";
396
            Matcher m = RE_LANG.matcher(head);
397
            if( m!=null && m.matches() && m.groupCount()==1 ) {
398
                String s = m.group(1);
399
                if( !StringUtils.isBlank(s) ) {
400
                    lang = s;
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
    @Override
461
    public void registerClassLoader(ClassLoader loader) {
462
      this.loaders.add(loader);
463
    }
464
    
465
    @Override
466
    public List<ClassLoader> getClassLoaders() {
467
      return Collections.unmodifiableList(loaders);
468
    }
469

    
470
    @Override
471
    public Formatter<ExpressionBuilder.Value> getExpressionBuilderFormatter() {
472
      return expressionBuilderFormatter;
473
    }
474

    
475
    @Override
476
    public void registerExpressionBuilderFormatter(Formatter<ExpressionBuilder.Value> formatter) {
477
      this.expressionBuilderFormatter = formatter;
478
    }
479
    
480
}
481