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

History | View | Annotate | Download (29.7 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.io.IOException;
4
import java.io.PushbackReader;
5
import java.io.StringReader;
6
import org.gvsig.expressionevaluator.spi.BaseExpressionEvaluator;
7
import java.io.StringWriter;
8
import java.io.Writer;
9
import java.net.URI;
10
import java.util.ArrayList;
11
import org.gvsig.expressionevaluator.Grammar;
12
import org.gvsig.expressionevaluator.GrammarFactory;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.LinkedHashMap;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Objects;
20
import java.util.regex.Matcher;
21
import java.util.regex.Pattern;
22
import org.apache.commons.io.FilenameUtils;
23
import org.apache.commons.io.IOUtils;
24
import org.apache.commons.io.output.ProxyWriter;
25
import org.apache.commons.lang3.ArrayUtils;
26
import org.apache.commons.lang3.StringUtils;
27
import org.gvsig.expressionevaluator.Code;
28
import org.gvsig.expressionevaluator.CodeBuilder;
29
import org.gvsig.expressionevaluator.Expression;
30
import org.gvsig.expressionevaluator.ExpressionBuilder;
31
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
32
import org.gvsig.expressionevaluator.Interpreter;
33
import org.gvsig.expressionevaluator.LexicalAnalyzer;
34
import org.gvsig.expressionevaluator.MutableSymbolTable;
35
import org.gvsig.expressionevaluator.Optimizer;
36
import org.gvsig.expressionevaluator.SymbolTable;
37
import org.gvsig.expressionevaluator.SymbolTableFactory;
38
import org.gvsig.expressionevaluator.Compiler;
39
import org.gvsig.expressionevaluator.ConverterToCode;
40
import org.gvsig.expressionevaluator.ExpressionEvaluator;
41
import org.gvsig.expressionevaluator.Formatter;
42
import org.gvsig.expressionevaluator.GrammarSet;
43
import org.gvsig.expressionevaluator.ReprMethod;
44
import org.gvsig.expressionevaluator.UserOperator;
45
import org.gvsig.expressionevaluator.impl.converterstocode.ArrayToCode;
46
import org.gvsig.expressionevaluator.impl.converterstocode.BooleanToCode;
47
import org.gvsig.expressionevaluator.impl.converterstocode.CharsequenceToCode;
48
import org.gvsig.expressionevaluator.impl.converterstocode.IterableToCode;
49
import org.gvsig.expressionevaluator.impl.converterstocode.IteratorToCode;
50
import org.gvsig.expressionevaluator.impl.converterstocode.ListToCode;
51
import org.gvsig.expressionevaluator.impl.converterstocode.NullToCode;
52
import org.gvsig.expressionevaluator.impl.converterstocode.NumberToCode;
53
import org.gvsig.expressionevaluator.impl.converterstocode.ObjectToCode;
54
import org.gvsig.expressionevaluator.impl.repr.ReprNull;
55
import org.gvsig.expressionevaluator.impl.repr.ReprObject;
56
import org.gvsig.expressionevaluator.spi.formatter.value.BaseFormatter;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.bookmarksandhistory.Bookmarks;
59
import org.gvsig.tools.bookmarksandhistory.History;
60
import org.gvsig.tools.dispose.DisposeUtils;
61
import org.gvsig.tools.exception.BaseException;
62
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
63
import org.gvsig.tools.script.Script;
64
import org.gvsig.tools.util.FilteredIterable;
65
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
67

    
68

    
69
@SuppressWarnings("UseSpecificCatch")
70
public class DefaultExpressionEvaluatorManager implements ExpressionEvaluatorManager {
71

    
72
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpressionEvaluatorManager.class);
73
    
74
    private Double accuracy;
75
    private final Map<String,SymbolTableFactory>symbolTableFactories;
76
    private final Map<String,GrammarFactory> grammarFactories;
77
    private Bookmarks<Expression> bookmarks;
78
    private static final String BOOKMARKSANDHISTORY_NAME = "ExpressionManager";
79
    private History<Expression> history;
80
    private SymbolTable inmutableSymbolTable;
81
    private ResourcesStorage scriptsResourcesStorage;
82
    private final List<ClassLoader> loaders;
83
    private Formatter<ExpressionBuilder.Value> expressionBuilderFormatter;
84

    
85
    private Map<String,ConverterToCode> convertersToCode;
86
    private Map<String,ConverterToCode> convertersToCode0;
87
    
88
    private Map<String,UserOperator> userOperators;
89
    
90
    public DefaultExpressionEvaluatorManager() {
91
        this.symbolTableFactories = new HashMap<>();
92
        this.grammarFactories = new HashMap<>();
93
        this.loaders = new ArrayList<>();
94
        this.scriptsResourcesStorage = ResourcesStorage.EMPTY_RESOURCESSTORAGE;
95
        this.loaders.add(this.getClass().getClassLoader());
96
        this.expressionBuilderFormatter = new BaseFormatter();
97
    }
98

    
99
    @Override
100
    public SymbolTable getSymbolTable(String name) {
101
        if( name == null ) {
102
            return null;
103
        }
104
        SymbolTableFactory factory = this.symbolTableFactories.get(name.toUpperCase());
105
        if( factory == null ) {
106
            return null;
107
        }
108
        return factory.create();
109
    }
110

    
111
    @Override
112
    public Collection<SymbolTableFactory> getSymbolTableFactories() {
113
        return this.symbolTableFactories.values();
114
    }
115

    
116
    @Override
117
    public final void registerSymbolTable(SymbolTableFactory factory) {
118
        if( factory == null ) {
119
            throw new IllegalArgumentException("factory can't be null");
120
        }
121
        this.symbolTableFactories.put(factory.getName().toUpperCase(),factory);
122
        this.inmutableSymbolTable = null;
123
    }
124

    
125
    @Override
126
    public SymbolTable getInmutableSymbolTable() {
127
        if( this.inmutableSymbolTable==null ) {
128
            this.inmutableSymbolTable = new InmutableSymbolTable();
129
        }
130
        return this.inmutableSymbolTable;
131
    }
132
    
133
    @Override
134
    public Object evaluate(String source) {
135
        Compiler compiler = this.createCompiler();
136
        Code code = compiler.compileExpression(source);
137
        DefaultInterpreter interpreter = new DefaultInterpreter();
138
        return interpreter.run(code);
139
    }
140
    
141
    @Override
142
    public Object evaluate(SymbolTable symbolTable, String source) {
143
        Compiler compiler = this.createCompiler();
144
        Code code = compiler.compileExpression(source);
145
        return this.evaluate(symbolTable, code);
146
    }
147

    
148
    @Override
149
    public Object evaluate(SymbolTable symbolTable, Code code) {
150
        DefaultInterpreter interpreter = new DefaultInterpreter();
151
        if( symbolTable!=null ) {
152
            interpreter.setSymbolTable(symbolTable);
153
        }
154
        return interpreter.run(code);
155
    }
156

    
157
    @Override
158
    public String evaluateDynamicText(String source) {
159
        return evaluateDynamicText(null, source);
160
    }
161
    
162
    @Override
163
    public boolean isDynamicText(String source) {
164
        String[] sources = StringUtils.substringsBetween(source, DYNAMICTEXT_STARTTAG, DYNAMICTEXT_ENDTAG);
165
        if( ArrayUtils.isEmpty(sources) ) {
166
            return false;
167
        }
168
        return true;
169
    }
170

    
171

    
172
    private static final int MODE_EXPRESSION = 0;
173
    private static final int MODE_STATEMENT = 1;
174
    
175
    public static String dynamicTextToScript(String s, String contentsName) {
176
        PushbackReader reader = new PushbackReader(new StringReader(s),100);
177
        StringBuilder script = new StringBuilder();
178
        StringBuilder buffer = new StringBuilder();
179
        try {
180
            script.append("begin\n");
181
//            script.append(contentsName);
182
//            script.append(" := StringWriter();\n");
183
            int mode;
184
            int ch;
185
            int ch2;
186
            while(true) {
187
                ch = reader.read();
188
                if( ch == -1 ) {
189
                    break;
190
                }
191
                switch(ch) {
192
                    case '<':
193
                        ch2 = reader.read();
194
                        if( ch2 != '%') {
195
                            buffer.append((char)ch);
196
                            buffer.append((char)ch2);
197
                            break;
198
                        }
199
                        ch2 = reader.read();
200
                        if( ch2 == '=' ) {
201
                            mode = MODE_EXPRESSION;
202
                        } else {
203
                            mode = MODE_STATEMENT;
204
                            reader.unread(ch2);
205
                        }
206
                        if( buffer.length()>0 ) {
207
                            script.append(contentsName);
208
                            script.append(".append('");
209
                            script.append(buffer.toString());
210
                            script.append("');");
211
                        }
212
                        buffer.setLength(0);
213
                        while(true) {
214
                            ch = reader.read();
215
                            if( ch==-1) {
216
                                break;
217
                            }
218
                            if( ch == '%' ) {
219
                                ch2 = reader.read();
220
                                if( ch2 == '>') {
221
                                    if( mode == MODE_EXPRESSION ) {
222
                                        if( buffer.length()>0 ) {
223
                                            script.append(contentsName);
224
                                            script.append(".append(");
225
                                            script.append(buffer.toString());
226
                                            script.append(");");
227
                                        }
228
                                    } else {
229
                                        script.append(buffer.toString());
230
                                    }
231
                                    buffer.setLength(0);
232
                                    break;
233
                                } else {
234
                                    buffer.append((char)ch);
235
                                    buffer.append((char)ch2);
236
                                }
237
                            } else {
238
                                buffer.append((char)ch);
239
                            }
240
                        }
241
                        break;
242
                    case '\'':
243
                        buffer.append('\'');
244
                        buffer.append('\'');
245
                        break;
246
                    default:
247
                        buffer.append((char)ch);
248
                        break;
249
                }
250
            }
251
        } catch (IOException ex) {
252
            
253
        }
254
        if( buffer.length()>0 ) {
255
            script.append(contentsName);
256
            script.append(".append('");
257
            script.append(buffer.toString());
258
            script.append("');");        
259
            script.append("\n");
260
        }
261
//        script.append(contentsName);
262
//        script.append(".toString();\n");
263
        script.append("end\n");
264
        
265
        return script.toString();
266
    }
267
    
268
    @Override
269
    public String evaluateDynamicText(SymbolTable symbolTable, String source) {
270
        return evaluateDynamicText(symbolTable, source, null);
271
    }
272

    
273
    public static class AppendExWriter extends ProxyWriter {
274
        public AppendExWriter(Writer writer) {
275
            super(writer);
276
        }
277
        
278
        public Writer append(Object x) throws IOException {
279
            if( x!=null ) {
280
                this.append(x.toString());
281
            }
282
            return this;
283
        }
284
        
285
        public Writer getWriter() {
286
            return this.out;
287
        }
288
    }
289
    
290
    @Override
291
    public String evaluateDynamicText(SymbolTable symbolTable, String source, Writer output) {
292
        return this.evaluateDynamicText(symbolTable, source, output, scriptsResourcesStorage);
293
    }
294
    
295
    @Override
296
    public String evaluateDynamicText(SymbolTable symbolTable, String source, Writer output, ResourcesStorage resources) {
297
        try {
298
            if (!StringUtils.contains(source, DYNAMICTEXT_STARTTAG)) {
299
                if (output == null) {
300
                    return source;
301
                }
302
                output.append(source);
303
                return null;
304
            }
305
            AppendExWriter writer;
306
            if (output == null) {
307
                writer = new AppendExWriter(new StringWriter());
308
            } else {
309
                writer = new AppendExWriter(output);
310
            }
311
            String script = dynamicTextToScript(source, "contents");
312
            MutableSymbolTable st = this.createSymbolTable();
313
            if (symbolTable != null) {
314
                st.addSymbolTable(symbolTable);
315
            }
316
            st.setVar("contents", writer);
317
            
318
            Compiler compiler = this.createCompiler();
319
            DefaultInterpreter interpreter = new DefaultInterpreter();
320
            interpreter.setSymbolTable(st);
321
            if( resources!=null ) {
322
                interpreter.setResourcesStorage(resources);
323
            }
324
            
325
            Code code = compiler.compileExpression(script);
326
            interpreter.run(code);            
327

    
328
            if (output == null) {
329
                return ((StringWriter) writer.getWriter()).toString();
330
            }
331
            return null;
332
        } catch (IOException ex) {
333
            throw new RuntimeException("Can't evaluate dynamic-text.", ex);
334
        }
335
    }
336

    
337
    public String evaluateDynamicText_old(SymbolTable symbolTable, String source) {
338
        String[] sources = StringUtils.substringsBetween(source, DYNAMICTEXT_STARTTAG, DYNAMICTEXT_ENDTAG);
339
        if( ArrayUtils.isEmpty(sources) ) {
340
            return source;
341
        }
342
        String[] values = new String[sources.length];
343
        
344
        DefaultInterpreter interpreter = new DefaultInterpreter();
345
        if( symbolTable!=null ) {
346
            interpreter.setSymbolTable(symbolTable);
347
        }
348
        StringWriter writer = new StringWriter();
349
        interpreter.setWriter(writer);
350
        DefaultCompiler compiler = new DefaultCompiler(this);
351
        for (int i = 0; i < sources.length; i++) {
352
            String theSource = sources[i];
353
            if( StringUtils.startsWith(theSource, "=") ) {
354
                Code code = compiler.compileExpression(theSource.substring(1));
355
                Object value = interpreter.run(code);
356
                values[i] = Objects.toString(value, "");
357
            } else {
358
                Code code = compiler.compileExpression(theSource.substring(0));
359
                writer.getBuffer().setLength(0);
360
                interpreter.run(code);
361
                values[i] = writer.toString();
362
            }
363
            sources[i] = DYNAMICTEXT_STARTTAG+sources[i]+DYNAMICTEXT_ENDTAG;
364
        }
365
        String output = StringUtils.replaceEach(source, sources, values);
366
        return output;
367
    }
368
    
369
    @Override
370
    public Code compile(String source) {
371
        Compiler compiler = this.createCompiler();
372
        return compiler.compileExpression(source);
373
    }
374

    
375
    @Override
376
    public Code compile(LexicalAnalyzer lex, String source) {
377
        Compiler compiler = this.createCompiler();
378
        compiler.setLexicalAnalyzer(lex);
379
        return compiler.compileExpression(source);
380
    }
381

    
382
    @Override
383
    public Code optimize(SymbolTable symbolTable, Code code) {
384
        Optimizer optimizer = this.createOptimizer();
385
        return optimizer.optimize(symbolTable, code);
386
    }
387

    
388
    @Override
389
    public MutableSymbolTable createSymbolTable() {
390
        DefaultSymbolTable theSymbolTable = new DefaultSymbolTable();
391
        return theSymbolTable;
392
    }
393
    
394
    @Override
395
    public void populateSymbolTable(SymbolTable aSymbolTable) {
396
        for (SymbolTableFactory factory : this.getSymbolTableFactories() ) {
397
            try {
398
                if( factory.isAutoload() ) {
399
                    SymbolTable symbolTable = factory.create();
400
                    aSymbolTable.addSymbolTable(symbolTable);
401
                }
402
            } catch(Throwable th) {
403
                String factoryName = "Unknown";
404
                try {
405
                    factoryName = factory.getName();
406
                } catch(Throwable th2) {
407
                    // Do nothing
408
                }
409
                LOGGER.warn("Can't create symbol table '"+factoryName+"', ignore this symbol table.");
410
                LOGGER.debug("Error creating symbol table.",th);
411
            }
412
        }
413
    }
414
    
415
    @Override
416
    public LexicalAnalyzer createLexicalAnalyzer() {
417
        return new SQLLexicalAnalyzer();
418
    }
419

    
420
    @Override
421
    public CodeBuilder createCodeBuilder() {
422
        return new DefaultCodeBuilder(this);
423
    }
424

    
425
    @Override
426
    public Compiler createCompiler() {
427
        DefaultCompiler compiler = new DefaultCompiler(this);
428
        this.populateGrammars(compiler);
429
        return  compiler;
430
    }
431

    
432
    @Override
433
    public Interpreter createInterpreter() {
434
        Interpreter interpreter = new DefaultInterpreter();
435
        interpreter.setResourcesStorage(this.scriptsResourcesStorage);
436
        return interpreter;
437
    }
438

    
439
    @Override
440
    public Double getAccuracy() {
441
        return this.accuracy;
442
    }
443

    
444
    @Override
445
    public void setAccuracy(Double accuracy) {
446
        this.accuracy = accuracy;
447
    }
448

    
449
    @Override
450
    public Expression createExpression() {
451
        DefaultExpression e = new DefaultExpression(this);
452
        return e;
453
    }
454

    
455
    @Override
456
    public ExpressionBuilder createExpressionBuilder() {
457
        ExpressionBuilder x = new DefaultExpressionBuilder(this);
458
        return x;
459
    }
460

    
461
    @Override
462
    public Optimizer createOptimizer() {
463
        Optimizer x = new DefaultOptimizer(this);
464
        return x;
465
    }
466

    
467
    @Override
468
    public void registerGrammar(GrammarFactory factory) {
469
        if( factory==null ) {
470
            throw new IllegalArgumentException("factory can't be null");
471
        }
472
        this.grammarFactories.put(factory.getName(), factory);
473
    }
474

    
475
    @Override
476
    public Collection<GrammarFactory> getGrammarFactories() {
477
        return this.grammarFactories.values();
478
    }
479

    
480
    public void populateGrammars(Compiler compiler) {
481
        GrammarSet grammarSet = compiler.getGrammars();
482
        for (GrammarFactory factory : this.getGrammarFactories() ) {
483
            if( factory.isAutoload() ) {
484
                Grammar grammar = factory.create();
485
                grammarSet.add(grammar);
486
            }
487
        }
488
    }
489

    
490
    @Override
491
    public Grammar createGrammar(String name) {
492
        DefaultGrammar grammar = new DefaultGrammar(name);
493
        return grammar;
494
    }
495
    
496
    @Override
497
    public Bookmarks<Expression> getBookmarks() {
498
        if( this.bookmarks==null ) {
499
             this.bookmarks = ToolsLocator.getBookmarksAndHistoryManager().getBookmarksGroup(BOOKMARKSANDHISTORY_NAME); 
500

    
501
        }
502
        return this.bookmarks;
503
    }
504

    
505
    @Override
506
    public History<Expression> getHistory() {
507
        if( this.history==null ) {
508
            this.history = ToolsLocator.getBookmarksAndHistoryManager().getHistoryGroup(BOOKMARKSANDHISTORY_NAME);
509
        }
510
        return this.history;
511
    }
512
    
513
    @Override
514
    public Script createScript(String name, String code, String languaje) {
515
        SimpleScript sc = new SimpleScript(this.createInterpreter(), name, code);
516
        return sc;
517
    }
518

    
519
    @Override
520
    public Script locateScript(String name) {
521
        return loadScript(this.scriptsResourcesStorage, name);
522
    }
523

    
524
    @Override
525
    public Script loadScript(final URI location) {
526
        ResourcesStorage.Resource res = null;
527
        try {
528
            if( location==null ) {
529
                return null;
530
            }
531
            String resourceName = FilenameUtils.getBaseName(location.getPath());
532
            res = ResourcesStorage.createResource(resourceName, location);
533
            if( res == null || !res.exists() ) {
534
                return null;
535
            }
536
            Script script = loadScript(res, resourceName);
537
            return script;
538
        } catch (Exception ex) {
539
            LOGGER.warn("Can't load script from URI.", ex);
540
            return null;
541
        } finally {
542
            IOUtils.closeQuietly(res);
543
        }
544
    }
545

    
546

    
547
    @Override
548
    public Script loadScript(ResourcesStorage storage, String name) {
549
        ResourcesStorage.Resource res = null;
550
        try {
551
            if( storage==null ) {
552
                return null;
553
            }
554
            res = storage.getResource(name);
555
            if( res == null || !res.exists() ) {
556
                return null;
557
            }
558
            Script script = loadScript(res, name);
559
            return script;
560
        } catch (Exception ex) {
561
            LOGGER.warn("Can't load script from resources storage.", ex);
562
            return null;
563
        } finally {
564
            IOUtils.closeQuietly(res);
565
        }
566

    
567
    }
568

    
569
    private static final Pattern RE_LANG = Pattern.compile(".*lang[:]\\s*([a-zA-Z_][a-zA-Z_0-9_]*).*");
570
    private static final Pattern RE_ENCODING = Pattern.compile(".*encoding[:]\\s*([a-zA-Z_][a-zA-Z0-9_-]*).*");
571
    
572
    private Script loadScript(ResourcesStorage.Resource res, String name) {
573
        try {
574
            if( res == null || !res.exists() ) {
575
                return null;
576
            }
577
            String head = EncodingUtils.getFirstLine(res.asInputStream());
578
            IOUtils.closeQuietly(res); // Eliminar con org.gvsig.tools > 3.0.230
579
            if( StringUtils.isEmpty(head) ) {
580
                return null;
581
            }
582
            
583
            String encoding = EncodingUtils.getEncoding(head);
584
            
585
            String lang = "cosa";
586
            Matcher m = RE_LANG.matcher(head);
587
            if( m!=null && m.matches() && m.groupCount()==1 ) {
588
                String s = m.group(1);
589
                if( !StringUtils.isBlank(s) ) {
590
                    lang = s;
591
                }
592
            }
593
            String source;
594
            if( StringUtils.isBlank(encoding) ) {
595
                source = IOUtils.toString(res.asInputStream());
596
            } else {
597
                source = IOUtils.toString(res.asInputStream(), encoding);
598
            }
599
            Script script = this.createScript(name, source, lang);
600
            return script;
601
        } catch (Exception ex) {
602
            LOGGER.warn("Can't load script from resource.", ex);
603
            return null;
604
        } finally {
605
            IOUtils.closeQuietly(res);
606
        }
607

    
608
    }
609
    
610
    @Override
611
    public ResourcesStorage getScriptsResourcesStorage() {
612
        return this.scriptsResourcesStorage;
613
    }
614

    
615
    @Override
616
    public void setScriptsResourcesStorage(ResourcesStorage scriptsResourcesStorage) {
617
        if(this.scriptsResourcesStorage != null){
618
            DisposeUtils.disposeQuietly(this.scriptsResourcesStorage);
619
        }
620
        DisposeUtils.bind(scriptsResourcesStorage);
621
        this.scriptsResourcesStorage = scriptsResourcesStorage;
622
    }
623

    
624
    
625
    private final List<ReprMethod> reprMethods = new ArrayList<>();
626
    private final Map<Class,ReprMethod> reprMethodsCache = new HashMap<>();
627
    private final ReprMethod reprNull = new ReprNull();
628
    private final ReprMethod reprObject = new ReprObject();
629
    
630
    @Override
631
    public void addReprMethod(ReprMethod method) {
632
        this.reprMethods.add(method);
633
        this.reprMethodsCache.clear();
634
    }
635
    
636
    @Override
637
    public ReprMethod getReprMethod(Object value) {
638
        if( value == null ) {
639
            return this.reprNull;
640
        }
641
        ReprMethod method = this.reprMethodsCache.get(value.getClass());
642
        if( method!=null ) {
643
            return method;
644
        }
645
        for (ReprMethod theMethod : reprMethods) {
646
            if( theMethod.isApplicable(value) ) {
647
                this.reprMethodsCache.put(value.getClass(), theMethod);
648
                return theMethod;
649
            }
650
        }
651
        return this.reprObject;
652
    }
653

    
654
    @Override
655
    public void registerClassLoader(ClassLoader loader) {
656
      this.loaders.add(loader);
657
    }
658
    
659
    @Override
660
    public List<ClassLoader> getClassLoaders() {
661
      return Collections.unmodifiableList(loaders);
662
    }
663

    
664
    @Override
665
    public Formatter<ExpressionBuilder.Value> getExpressionBuilderFormatter() {
666
      return expressionBuilderFormatter;
667
    }
668

    
669
    @Override
670
    public void registerExpressionBuilderFormatter(Formatter<ExpressionBuilder.Value> formatter) {
671
      this.expressionBuilderFormatter = formatter;
672
    }
673

    
674
    @Override
675
    public ExpressionEvaluator createExpressionEvaluator(Expression expression) {
676
        return new BaseExpressionEvaluator(expression);
677
    }
678
    
679
    @Override
680
    public ExpressionEvaluator createEvaluator(String expression) {
681
        Expression exp = this.createExpression();
682
        exp.setPhrase(expression);
683
        return new BaseExpressionEvaluator(exp);
684
    }
685
    
686
    @Override
687
    public boolean hasHostExpressions(Code statement) {
688
        try {
689
            List<Code> hostExpressions = new ArrayList<>();
690
            statement.accept(
691
                    (Object code) -> {
692
                        if( !(code instanceof Code.Callable) ) {
693
                            return;
694
                        }
695
                        Code.Callable callable = (Code.Callable) code;
696
                        if( StringUtils.equalsIgnoreCase(callable.name(), ExpressionBuilder.FUNCTION_$HOSTEXPRESSION) ) {
697
                            hostExpressions.add(callable);
698
                        }
699
                    }, null
700
            );
701
            return !hostExpressions.isEmpty();
702
        } catch (BaseException ex) {
703
            throw new RuntimeException("Can't check host expressions", ex);
704
        }
705
    }
706

    
707
    @Override
708
    public boolean hasHostExpressions(ExpressionBuilder.Value statement) {
709
        return HostExpressionUtils.hasHostExpressions(statement);
710
    }
711

    
712
    @Override
713
    public Code resolveHostExpressions(Code statement, Interpreter interpreter) {
714
        return HostExpressionUtils.resolveHostExpressions(statement, interpreter);
715
    }
716
    
717
    @Override
718
    public ExpressionBuilder.Value resolveHostExpressions(ExpressionBuilder.Value statement, SymbolTable symbolTable) {
719
        return HostExpressionUtils.resolveHostExpressions(statement, symbolTable);
720
    }
721
    
722
    @Override
723
    public Code resolveHostExpressions(Code statement, SymbolTable symbolTable) {
724
        return HostExpressionUtils.resolveHostExpressions(statement, symbolTable);
725
    }
726
    
727
    @Override
728
    public Expression resolveHostExpressions(Expression expression, SymbolTable symbolTable) {
729
        return HostExpressionUtils.resolveHostExpressions(expression, symbolTable);
730
    }
731

    
732
    @Override
733
    public boolean hasHostExpressions(String statement) {
734
        return HostExpressionUtils.hasHostExpressions(statement);
735
    }
736

    
737
    @Override
738
    public ExpressionBuilder.Value getHostExpressionValue(ExpressionBuilder.Function hostExpression, ExpressionBuilder expbuilder) {
739
        return HostExpressionUtils.getHostExpressionValue(hostExpression, expbuilder);
740
    }
741

    
742
    @Override
743
    public ExpressionBuilder.Value getHostExpressionValue(ExpressionBuilder.Function hostExpression, ExpressionBuilder expbuilder, SymbolTable symbolTable) {
744
        return HostExpressionUtils.getHostExpressionValue(hostExpression, expbuilder, symbolTable);
745
    }
746

    
747
    public void initConvertersToCode() {
748
        this.convertersToCode0 = new LinkedHashMap<>();
749
        ConverterToCode[] converters = new ConverterToCode[] { 
750
            new NullToCode(),
751
            new CharsequenceToCode(),
752
            new NumberToCode(),
753
            new BooleanToCode(),
754
            new IteratorToCode(),
755
            new IterableToCode(),
756
            new ListToCode(),
757
            new ArrayToCode(),
758
            new ObjectToCode()
759
        };
760
        for (ConverterToCode converter : converters) {
761
            this.convertersToCode0.put(converter.getName(),converter);
762
        }
763
        this.convertersToCode = new LinkedHashMap<>();
764
    }
765
    
766
    @Override
767
    public void registerCodeConverter(ConverterToCode converter) {
768
        if( this.convertersToCode == null ) {
769
            this.initConvertersToCode();
770
        }
771
        this.convertersToCode.put(converter.getName(), converter);
772
    }
773

    
774
    @Override
775
    public ConverterToCode getConverterToCode(Object ob) {
776
        if( this.convertersToCode == null ) {
777
            this.initConvertersToCode();
778
        }
779
        for (ConverterToCode converter : this.convertersToCode.values()) {
780
            if( converter.isApplicable(ob) ) {
781
                return converter;
782
            }
783
        }
784
        for (ConverterToCode converter : this.convertersToCode0.values()) {
785
            if( converter.isApplicable(ob) ) {
786
                return converter;
787
            }
788
        }
789
        return null;
790
    }
791

    
792
    @Override
793
    public ExpressionBuilder.Value convertToValue(Object obj) {
794
        Code code = this.convertToCode(obj);
795
        ExpressionBuilder.Value value = code.toValue();
796
        return value;
797
    }
798

    
799
    @Override
800
    public Code convertToCode(Object obj) {
801
        return convertToCode(null, obj, null);
802
    }
803
    
804
    @Override
805
    public Code convertToCode(CodeBuilder builder, Object obj, Map<String,Object> props) {
806
        if( this.convertersToCode == null ) {
807
            this.initConvertersToCode();
808
        }
809
        if( builder == null ) {
810
            builder = this.createCodeBuilder();
811
        }
812
        for (ConverterToCode converter : this.convertersToCode.values()) {
813
            if( converter.isApplicable(obj) ) {
814
                return converter.toCode(builder, obj, props);
815
            }
816
        }
817
        for (ConverterToCode converter : this.convertersToCode0.values()) {
818
            if( converter.isApplicable(obj) ) {
819
                return converter.toCode(builder, obj, props);
820
            }
821
        }
822
        return null;
823
    }
824
    
825
    public ConverterToCode getConverterToCodeByName(String name) {
826
        ConverterToCode converter = this.convertersToCode.get(name);
827
        if( converter!=null ) {
828
            return converter;
829
        }
830
        converter = this.convertersToCode0.get(name);
831
        return converter;
832
    }
833

    
834
    @Override
835
    public void registerUserOperator(UserOperator userOperator) {
836
        if( this.userOperators == null ) {
837
            this.userOperators = new HashMap<>();
838
        }
839
        this.userOperators.put(userOperator.name(), userOperator);
840
    }
841

    
842
    @Override
843
    public Iterable<UserOperator> getUserDefinedOperators(String precedence) {
844
        if( this.userOperators == null ) {
845
            return Collections.EMPTY_LIST;
846
        }
847
        if( StringUtils.isBlank(precedence) ) {
848
            return this.userOperators.values();
849
        }
850
        return new FilteredIterable<>(
851
                this.userOperators.values(), 
852
                (UserOperator t) -> StringUtils.equalsIgnoreCase(precedence, t.precedence())
853
        );
854
    }
855

    
856
}
857