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 @ 44644
History | View | Annotate | Download (14.9 KB)
1 | 43521 | jjdelcerro | package org.gvsig.expressionevaluator.impl; |
---|---|---|---|
2 | |||
3 | 44389 | jjdelcerro | import java.io.StringWriter; |
4 | 44339 | jjdelcerro | import java.net.URI; |
5 | 44644 | jjdelcerro | import java.util.ArrayList; |
6 | 44139 | jjdelcerro | import org.gvsig.expressionevaluator.Grammar; |
7 | import org.gvsig.expressionevaluator.GrammarFactory; |
||
8 | 43983 | jjdelcerro | import java.util.Collection; |
9 | 43939 | jjdelcerro | import java.util.HashMap; |
10 | 44644 | jjdelcerro | import java.util.List; |
11 | 43939 | jjdelcerro | import java.util.Map; |
12 | 44389 | jjdelcerro | import java.util.Objects; |
13 | 44392 | jjdelcerro | import java.util.regex.Matcher; |
14 | import java.util.regex.Pattern; |
||
15 | 44339 | jjdelcerro | import org.apache.commons.io.FilenameUtils; |
16 | import org.apache.commons.io.IOUtils; |
||
17 | 44389 | jjdelcerro | import org.apache.commons.lang3.ArrayUtils; |
18 | import org.apache.commons.lang3.StringUtils; |
||
19 | 43521 | jjdelcerro | import org.gvsig.expressionevaluator.Code; |
20 | import org.gvsig.expressionevaluator.CodeBuilder; |
||
21 | 43983 | jjdelcerro | import org.gvsig.expressionevaluator.Expression; |
22 | 44006 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionBuilder; |
23 | 43521 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
24 | import org.gvsig.expressionevaluator.Interpreter; |
||
25 | import org.gvsig.expressionevaluator.LexicalAnalyzer; |
||
26 | import org.gvsig.expressionevaluator.MutableSymbolTable; |
||
27 | 44009 | jjdelcerro | import org.gvsig.expressionevaluator.Optimizer; |
28 | 43521 | jjdelcerro | import org.gvsig.expressionevaluator.SymbolTable; |
29 | 44126 | jjdelcerro | import org.gvsig.expressionevaluator.SymbolTableFactory; |
30 | 44139 | jjdelcerro | import org.gvsig.expressionevaluator.Compiler; |
31 | import org.gvsig.expressionevaluator.GrammarSet; |
||
32 | 44644 | jjdelcerro | import org.gvsig.expressionevaluator.ReprMethod; |
33 | import org.gvsig.expressionevaluator.impl.repr.ReprNull; |
||
34 | import org.gvsig.expressionevaluator.impl.repr.ReprObject; |
||
35 | 44390 | jjdelcerro | import org.gvsig.tools.bookmarksandhistory.Bookmarks; |
36 | import org.gvsig.tools.bookmarksandhistory.History; |
||
37 | import org.gvsig.tools.bookmarksandhistory.impl.BaseBookmarks; |
||
38 | import org.gvsig.tools.bookmarksandhistory.impl.BaseHistory; |
||
39 | 44392 | jjdelcerro | import org.gvsig.tools.resourcesstorage.ResourcesStorage; |
40 | 44339 | jjdelcerro | import org.gvsig.tools.script.Script; |
41 | 44006 | jjdelcerro | import org.slf4j.Logger; |
42 | import org.slf4j.LoggerFactory; |
||
43 | 43521 | jjdelcerro | |
44 | |||
45 | 44339 | jjdelcerro | @SuppressWarnings("UseSpecificCatch") |
46 | 43521 | jjdelcerro | public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager { |
47 | |||
48 | 44006 | jjdelcerro | private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpressionEvaluatorManager.class); |
49 | |||
50 | 43521 | jjdelcerro | private Double accuracy; |
51 | 44126 | jjdelcerro | private final Map<String,SymbolTableFactory>symbolTableFactories; |
52 | 44139 | jjdelcerro | private final Map<String,GrammarFactory> grammarFactories; |
53 | 44390 | jjdelcerro | private Bookmarks<Expression> bookmarks; |
54 | private History<Expression> history; |
||
55 | 44446 | jjdelcerro | private SymbolTable inmutableSymbolTable;
|
56 | 44533 | jjdelcerro | private ResourcesStorage scriptsResourcesStorage;
|
57 | 43521 | jjdelcerro | |
58 | public DefaultExpressionEvaluatorManager() {
|
||
59 | 44126 | jjdelcerro | this.symbolTableFactories = new HashMap<>(); |
60 | 44139 | jjdelcerro | this.grammarFactories = new HashMap<>(); |
61 | 44533 | jjdelcerro | this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
|
62 | 43939 | jjdelcerro | } |
63 | |||
64 | 43521 | jjdelcerro | @Override
|
65 | 43983 | jjdelcerro | public SymbolTable getSymbolTable(String name) { |
66 | 44126 | jjdelcerro | if( name == null ) { |
67 | return null; |
||
68 | } |
||
69 | SymbolTableFactory factory = this.symbolTableFactories.get(name.toUpperCase());
|
||
70 | if( factory == null ) { |
||
71 | return null; |
||
72 | } |
||
73 | 44389 | jjdelcerro | return factory.create();
|
74 | 43939 | jjdelcerro | } |
75 | |||
76 | @Override
|
||
77 | 44126 | jjdelcerro | public Collection<SymbolTableFactory> getSymbolTableFactories() { |
78 | return this.symbolTableFactories.values(); |
||
79 | 43939 | jjdelcerro | } |
80 | |||
81 | @Override
|
||
82 | 44126 | jjdelcerro | public final void registerSymbolTable(SymbolTableFactory factory) { |
83 | if( factory == null ) { |
||
84 | throw new IllegalArgumentException("factory can't be null"); |
||
85 | 44006 | jjdelcerro | } |
86 | 44126 | jjdelcerro | this.symbolTableFactories.put(factory.getName().toUpperCase(),factory);
|
87 | 44446 | jjdelcerro | this.inmutableSymbolTable = null; |
88 | 43939 | jjdelcerro | } |
89 | 43987 | jjdelcerro | |
90 | 43939 | jjdelcerro | @Override
|
91 | 44446 | jjdelcerro | public SymbolTable getInmutableSymbolTable() {
|
92 | if( this.inmutableSymbolTable==null ) { |
||
93 | this.inmutableSymbolTable = new InmutableSymbolTable(); |
||
94 | } |
||
95 | return this.inmutableSymbolTable; |
||
96 | } |
||
97 | |||
98 | @Override
|
||
99 | 43521 | jjdelcerro | public Object evaluate(String source) { |
100 | DefaultInterpreter interpreter = new DefaultInterpreter();
|
||
101 | 44644 | jjdelcerro | DefaultCompiler compiler = new DefaultCompiler(this); |
102 | 43521 | jjdelcerro | Code code = compiler.compileExpression(source); |
103 | return interpreter.run(code);
|
||
104 | } |
||
105 | 44389 | jjdelcerro | |
106 | 43521 | jjdelcerro | @Override
|
107 | public Object evaluate(SymbolTable symbolTable, String source) { |
||
108 | DefaultInterpreter interpreter = new DefaultInterpreter();
|
||
109 | 44644 | jjdelcerro | DefaultCompiler compiler = new DefaultCompiler(this); |
110 | 43521 | jjdelcerro | Code code = compiler.compileExpression(source); |
111 | 44446 | jjdelcerro | if( symbolTable!=null ) { |
112 | interpreter.setSymbolTable(symbolTable); |
||
113 | } |
||
114 | 43521 | jjdelcerro | return interpreter.run(code);
|
115 | } |
||
116 | |||
117 | @Override
|
||
118 | public Object evaluate(SymbolTable symbolTable, Code code) { |
||
119 | DefaultInterpreter interpreter = new DefaultInterpreter();
|
||
120 | 44446 | jjdelcerro | if( symbolTable!=null ) { |
121 | interpreter.setSymbolTable(symbolTable); |
||
122 | } |
||
123 | 43521 | jjdelcerro | return interpreter.run(code);
|
124 | } |
||
125 | |||
126 | @Override
|
||
127 | 44397 | jjdelcerro | public String evaluateDynamicText(String source) { |
128 | return evaluateDynamicText(null, source); |
||
129 | 44389 | jjdelcerro | } |
130 | |||
131 | @Override
|
||
132 | 44397 | jjdelcerro | public boolean isDynamicText(String source) { |
133 | 44389 | jjdelcerro | String[] sources = StringUtils.substringsBetween(source, "<%", "%>"); |
134 | if( ArrayUtils.isEmpty(sources) ) {
|
||
135 | 44397 | jjdelcerro | return false; |
136 | } |
||
137 | return true; |
||
138 | } |
||
139 | |||
140 | @Override
|
||
141 | public String evaluateDynamicText(SymbolTable symbolTable, String source) { |
||
142 | String[] sources = StringUtils.substringsBetween(source, "<%", "%>"); |
||
143 | if( ArrayUtils.isEmpty(sources) ) {
|
||
144 | 44389 | jjdelcerro | return source;
|
145 | } |
||
146 | String[] values = new String[sources.length]; |
||
147 | |||
148 | DefaultInterpreter interpreter = new DefaultInterpreter();
|
||
149 | if( symbolTable!=null ) { |
||
150 | interpreter.setSymbolTable(symbolTable); |
||
151 | } |
||
152 | StringWriter writer = new StringWriter(); |
||
153 | interpreter.setWriter(writer); |
||
154 | 44644 | jjdelcerro | DefaultCompiler compiler = new DefaultCompiler(this); |
155 | 44389 | jjdelcerro | for (int i = 0; i < sources.length; i++) { |
156 | String theSource = sources[i];
|
||
157 | if( StringUtils.startsWith(theSource, "=") ) { |
||
158 | Code code = compiler.compileExpression(theSource.substring(1));
|
||
159 | Object value = interpreter.run(code);
|
||
160 | values[i] = Objects.toString(value, "");
|
||
161 | } else {
|
||
162 | Code code = compiler.compileExpression(theSource.substring(1));
|
||
163 | writer.getBuffer().setLength(0);
|
||
164 | interpreter.run(code); |
||
165 | values[i] = writer.toString(); |
||
166 | } |
||
167 | 44390 | jjdelcerro | sources[i] = "<%"+sources[i]+"%>"; |
168 | 44389 | jjdelcerro | } |
169 | String output = StringUtils.replaceEach(source, sources, values);
|
||
170 | return output;
|
||
171 | } |
||
172 | |||
173 | @Override
|
||
174 | 43521 | jjdelcerro | public Code compile(String source) { |
175 | 44139 | jjdelcerro | Compiler compiler = this.createCompiler(); |
176 | 43521 | jjdelcerro | return compiler.compileExpression(source);
|
177 | } |
||
178 | |||
179 | @Override
|
||
180 | public Code compile(LexicalAnalyzer lex, String source) { |
||
181 | 44139 | jjdelcerro | Compiler compiler = this.createCompiler(); |
182 | 43521 | jjdelcerro | compiler.setLexicalAnalyzer(lex); |
183 | return compiler.compileExpression(source);
|
||
184 | } |
||
185 | |||
186 | @Override
|
||
187 | 44019 | jjdelcerro | public Code optimize(SymbolTable symbolTable, Code code) {
|
188 | Optimizer optimizer = this.createOptimizer();
|
||
189 | return optimizer.optimize(symbolTable, code);
|
||
190 | } |
||
191 | |||
192 | @Override
|
||
193 | 43521 | jjdelcerro | public MutableSymbolTable createSymbolTable() {
|
194 | 43987 | jjdelcerro | DefaultSymbolTable theSymbolTable = new DefaultSymbolTable();
|
195 | return theSymbolTable;
|
||
196 | 43521 | jjdelcerro | } |
197 | 43939 | jjdelcerro | |
198 | 43987 | jjdelcerro | public void populateSymbolTable(SymbolTable aSymbolTable) { |
199 | 44126 | jjdelcerro | for (SymbolTableFactory factory : this.getSymbolTableFactories() ) { |
200 | 44394 | jjdelcerro | try {
|
201 | if( factory.isAutoload() ) {
|
||
202 | SymbolTable symbolTable = factory.create(); |
||
203 | aSymbolTable.addSymbolTable(symbolTable); |
||
204 | } |
||
205 | } catch(Throwable th) { |
||
206 | String factoryName = "Unknown"; |
||
207 | try {
|
||
208 | factoryName = factory.getName(); |
||
209 | } catch(Throwable th2) { |
||
210 | // Do nothing
|
||
211 | } |
||
212 | LOGGER.warn("Can't create symbol table '"+factoryName+"'.", th); |
||
213 | 43987 | jjdelcerro | } |
214 | } |
||
215 | } |
||
216 | |||
217 | 43521 | jjdelcerro | @Override
|
218 | public LexicalAnalyzer createLexicalAnalyzer() {
|
||
219 | return new SQLLexicalAnalyzer(); |
||
220 | } |
||
221 | |||
222 | @Override
|
||
223 | public CodeBuilder createCodeBuilder() {
|
||
224 | 44644 | jjdelcerro | return new DefaultCodeBuilder(this); |
225 | 43521 | jjdelcerro | } |
226 | |||
227 | @Override
|
||
228 | public Compiler createCompiler() { |
||
229 | 44644 | jjdelcerro | DefaultCompiler compiler = new DefaultCompiler(this); |
230 | 44139 | jjdelcerro | this.populateGrammars(compiler);
|
231 | return compiler;
|
||
232 | 43521 | jjdelcerro | } |
233 | |||
234 | @Override
|
||
235 | public Interpreter createInterpreter() {
|
||
236 | 44533 | jjdelcerro | Interpreter interpreter = new DefaultInterpreter();
|
237 | interpreter.setResourcesStorage(this.scriptsResourcesStorage);
|
||
238 | return interpreter;
|
||
239 | 43521 | jjdelcerro | } |
240 | |||
241 | @Override
|
||
242 | public Double getAccuracy() { |
||
243 | return this.accuracy; |
||
244 | } |
||
245 | |||
246 | @Override
|
||
247 | public void setAccuracy(Double accuracy) { |
||
248 | this.accuracy = accuracy;
|
||
249 | } |
||
250 | 43983 | jjdelcerro | |
251 | @Override
|
||
252 | public Expression createExpression() { |
||
253 | 44644 | jjdelcerro | DefaultExpression e = new DefaultExpression(this); |
254 | 43983 | jjdelcerro | return e;
|
255 | } |
||
256 | 44006 | jjdelcerro | |
257 | @Override
|
||
258 | public ExpressionBuilder createExpressionBuilder() {
|
||
259 | 44644 | jjdelcerro | ExpressionBuilder x = new DefaultExpressionBuilder(this); |
260 | 44006 | jjdelcerro | return x;
|
261 | } |
||
262 | 44009 | jjdelcerro | |
263 | @Override
|
||
264 | public Optimizer createOptimizer() {
|
||
265 | 44644 | jjdelcerro | Optimizer x = new DefaultOptimizer(this); |
266 | 44009 | jjdelcerro | return x;
|
267 | } |
||
268 | 44139 | jjdelcerro | |
269 | @Override
|
||
270 | public void registerGrammar(GrammarFactory factory) { |
||
271 | if( factory==null ) { |
||
272 | throw new IllegalArgumentException("factory can't be null"); |
||
273 | } |
||
274 | this.grammarFactories.put(factory.getName(), factory);
|
||
275 | } |
||
276 | |||
277 | @Override
|
||
278 | public Collection<GrammarFactory> getGrammarFactories() { |
||
279 | return this.grammarFactories.values(); |
||
280 | } |
||
281 | |||
282 | public void populateGrammars(Compiler compiler) { |
||
283 | GrammarSet grammarSet = compiler.getGrammars(); |
||
284 | for (GrammarFactory factory : this.getGrammarFactories() ) { |
||
285 | if( factory.isAutoload() ) {
|
||
286 | 44389 | jjdelcerro | Grammar grammar = factory.create(); |
287 | 44139 | jjdelcerro | grammarSet.add(grammar); |
288 | } |
||
289 | } |
||
290 | } |
||
291 | |||
292 | 44263 | jjdelcerro | @Override
|
293 | 44139 | jjdelcerro | public Grammar createGrammar(String name) { |
294 | DefaultGrammar grammar = new DefaultGrammar(name);
|
||
295 | return grammar;
|
||
296 | } |
||
297 | 44263 | jjdelcerro | |
298 | @Override
|
||
299 | 44390 | jjdelcerro | public Bookmarks<Expression> getBookmarks() { |
300 | 44263 | jjdelcerro | if( this.bookmarks==null ) { |
301 | 44392 | jjdelcerro | this.bookmarks = new BaseBookmarks<>(); |
302 | 44263 | jjdelcerro | } |
303 | return this.bookmarks; |
||
304 | } |
||
305 | |||
306 | @Override
|
||
307 | 44390 | jjdelcerro | public History<Expression> getHistory() { |
308 | 44263 | jjdelcerro | if( this.history==null ) { |
309 | 44392 | jjdelcerro | this.history = new BaseHistory<>(20); |
310 | 44263 | jjdelcerro | } |
311 | return this.history; |
||
312 | } |
||
313 | 44339 | jjdelcerro | |
314 | @Override
|
||
315 | public Script createScript(String name, String code, String languaje) { |
||
316 | 44389 | jjdelcerro | SimpleScript sc = new SimpleScript(this.createInterpreter(), name, code); |
317 | 44339 | jjdelcerro | return sc;
|
318 | } |
||
319 | |||
320 | @Override
|
||
321 | public Script locateScript(String name) { |
||
322 | 44533 | jjdelcerro | return loadScript(this.scriptsResourcesStorage, name); |
323 | 44339 | jjdelcerro | } |
324 | |||
325 | @Override
|
||
326 | 44392 | jjdelcerro | public Script loadScript(final URI location) { |
327 | ResourcesStorage.Resource res = null;
|
||
328 | 44339 | jjdelcerro | try {
|
329 | 44392 | jjdelcerro | if( location==null ) { |
330 | return null; |
||
331 | } |
||
332 | res = ResourcesStorage.createResource(location); |
||
333 | if( res == null || !res.exists() ) { |
||
334 | return null; |
||
335 | } |
||
336 | Script script = loadScript(res, FilenameUtils.getBaseName(location.getPath())); |
||
337 | return script;
|
||
338 | } catch (Exception ex) { |
||
339 | LOGGER.warn("Can't load script from URI.", ex);
|
||
340 | 44339 | jjdelcerro | return null; |
341 | } finally {
|
||
342 | 44392 | jjdelcerro | IOUtils.closeQuietly(res); |
343 | 44339 | jjdelcerro | } |
344 | } |
||
345 | 44392 | jjdelcerro | |
346 | |||
347 | @Override
|
||
348 | public Script loadScript(ResourcesStorage storage, String name) { |
||
349 | ResourcesStorage.Resource res = null;
|
||
350 | try {
|
||
351 | if( storage==null ) { |
||
352 | return null; |
||
353 | } |
||
354 | res = storage.getResource(name); |
||
355 | if( res == null || !res.exists() ) { |
||
356 | return null; |
||
357 | } |
||
358 | Script script = loadScript(res, name); |
||
359 | return script;
|
||
360 | } catch (Exception ex) { |
||
361 | LOGGER.warn("Can't load script from resources storage.", ex);
|
||
362 | return null; |
||
363 | } finally {
|
||
364 | IOUtils.closeQuietly(res); |
||
365 | } |
||
366 | |||
367 | } |
||
368 | |||
369 | 44592 | jjdelcerro | private static final Pattern RE_LANG = Pattern.compile(".*lang[:]\\s*([a-zA-Z_][a-zA-Z_0-9_]*).*"); |
370 | private static final Pattern RE_ENCODING = Pattern.compile(".*encoding[:]\\s*([a-zA-Z_][a-zA-Z0-9_-]*).*"); |
||
371 | 44392 | jjdelcerro | |
372 | private Script loadScript(ResourcesStorage.Resource res, String name) { |
||
373 | try {
|
||
374 | if( res == null || !res.exists() ) { |
||
375 | return null; |
||
376 | } |
||
377 | byte[] head_bytes = new byte[500]; |
||
378 | IOUtils.read(res.asInputStream(), head_bytes); |
||
379 | IOUtils.closeQuietly(res); |
||
380 | String head = new String(head_bytes); |
||
381 | if( StringUtils.isEmpty(head) ) {
|
||
382 | return null; |
||
383 | } |
||
384 | 44592 | jjdelcerro | head = StringUtils.split(head, "\n")[0]; |
385 | 44339 | jjdelcerro | |
386 | 44392 | jjdelcerro | String lang = "cosa"; |
387 | String encoding = null; |
||
388 | Matcher m = RE_LANG.matcher(head);
|
||
389 | 44592 | jjdelcerro | if( m!=null && m.matches() && m.groupCount()==1 ) { |
390 | 44392 | jjdelcerro | String s = m.group(1); |
391 | if( !StringUtils.isBlank(s) ) {
|
||
392 | lang = s; |
||
393 | } |
||
394 | } |
||
395 | m = RE_ENCODING.matcher(head); |
||
396 | 44592 | jjdelcerro | if( m!=null && m.matches() && m.groupCount()==1 ) { |
397 | 44392 | jjdelcerro | String s = m.group(1); |
398 | if( !StringUtils.isBlank(s) ) {
|
||
399 | encoding = s; |
||
400 | } |
||
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 | 44533 | jjdelcerro | |
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 | 44644 | jjdelcerro | |
430 | 44533 | jjdelcerro | |
431 | 44644 | jjdelcerro | 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 | 43521 | jjdelcerro | } |