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

History | View | Annotate | Download (28.6 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import org.gvsig.expressionevaluator.spi.BaseExpressionEvaluator;
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.Codes;
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.function.programming.$HostExpressionFunction;
39
import org.gvsig.expressionevaluator.impl.repr.ReprNull;
40
import org.gvsig.expressionevaluator.impl.repr.ReprObject;
41
import org.gvsig.expressionevaluator.spi.formatter.value.BaseFormatter;
42
import org.gvsig.tools.ToolsLocator;
43
import org.gvsig.tools.bookmarksandhistory.Bookmarks;
44
import org.gvsig.tools.bookmarksandhistory.History;
45
import org.gvsig.tools.dispose.DisposeUtils;
46
import org.gvsig.tools.exception.BaseException;
47
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
48
import org.gvsig.tools.script.Script;
49
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51

    
52

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
319
        }
320
        return this.bookmarks;
321
    }
322

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

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

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

    
364

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

    
385
    }
386

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

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

    
433
    @Override
434
    public void setScriptsResourcesStorage(ResourcesStorage scriptsResourcesStorage) {
435
        if(this.scriptsResourcesStorage != null){
436
            DisposeUtils.disposeQuietly(this.scriptsResourcesStorage);
437
        }
438
        DisposeUtils.bind(scriptsResourcesStorage);
439
        this.scriptsResourcesStorage = scriptsResourcesStorage;
440
    }
441

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

    
472
    @Override
473
    public void registerClassLoader(ClassLoader loader) {
474
      this.loaders.add(loader);
475
    }
476
    
477
    @Override
478
    public List<ClassLoader> getClassLoaders() {
479
      return Collections.unmodifiableList(loaders);
480
    }
481

    
482
    @Override
483
    public Formatter<ExpressionBuilder.Value> getExpressionBuilderFormatter() {
484
      return expressionBuilderFormatter;
485
    }
486

    
487
    @Override
488
    public void registerExpressionBuilderFormatter(Formatter<ExpressionBuilder.Value> formatter) {
489
      this.expressionBuilderFormatter = formatter;
490
    }
491

    
492
    @Override
493
    public ExpressionEvaluator createExpressionEvaluator(Expression expression) {
494
        return new BaseExpressionEvaluator(expression);
495
    }
496
    
497
    @Override
498
    public ExpressionEvaluator createEvaluator(String expression) {
499
        Expression exp = this.createExpression();
500
        exp.setPhrase(expression);
501
        return new BaseExpressionEvaluator(exp);
502
    }
503
    
504
    @Override
505
    public boolean hasHostExpressions(Code statement) {
506
        try {
507
            List<Code> hostExpressions = new ArrayList<>();
508
            statement.accept(
509
                    (Object code) -> {
510
                        if( !(code instanceof Code.Callable) ) {
511
                            return;
512
                        }
513
                        Code.Callable callable = (Code.Callable) code;
514
                        if( StringUtils.equalsIgnoreCase(callable.name(), ExpressionBuilder.FUNCTION_$HOSTEXPRESSION) ) {
515
                            hostExpressions.add(callable);
516
                        }
517
                    }, null
518
            );
519
            return !hostExpressions.isEmpty();
520
        } catch (BaseException ex) {
521
            throw new RuntimeException("Can't check host expressions", ex);
522
        }
523
    }
524

    
525
    @Override
526
    public boolean hasHostExpressions(ExpressionBuilder.Value statement) {
527
        List<ExpressionBuilder.Function> hostExpressions = new ArrayList<>();
528
        statement.accept((ExpressionBuilder.Visitable value) -> {
529
                if( !(value instanceof ExpressionBuilder.Function) ) {
530
                    return;
531
                }
532
                ExpressionBuilder.Function function = (ExpressionBuilder.Function) value;
533
                if( StringUtils.equalsIgnoreCase(function.name(), ExpressionBuilder.FUNCTION_$HOSTEXPRESSION) ) {
534
                    hostExpressions.add(function);
535
                }
536
        }, null);
537
        return !hostExpressions.isEmpty();
538
    }
539

    
540
    public boolean hasHostExpressions(String statement) {
541
        Compiler compiler = this.createCompiler();
542
        Code code = compiler.compileExpression(statement);
543
        return this.hasHostExpressions(code);
544
    }
545
    
546
    public List<Code> getHostExpressions(Code statement) throws Exception {
547
        List<Code> hostExpressions = new ArrayList<>();
548
        Code newstatement = (Code) statement.clone();
549
        newstatement.accept(
550
                (Object code) -> {
551
                    if( !(code instanceof Code.Callable) ) {
552
                        return;
553
                    }
554
                    Code.Callable callable = (Code.Callable) code;
555
                    if( StringUtils.equalsIgnoreCase(callable.name(), ExpressionBuilder.FUNCTION_$HOSTEXPRESSION) ) {
556
                        hostExpressions.add(callable);
557
                    }
558
                }, null 
559
        );
560
        return hostExpressions;
561
    }
562

    
563
    public List<ExpressionBuilder.Value> getHostExpressions(ExpressionBuilder.Value statement) throws Exception {
564
        List<ExpressionBuilder.Value> hostExpressions = new ArrayList<>();
565
        ExpressionBuilder.Value newstatement = (ExpressionBuilder.Value) statement.clone();
566
        newstatement.accept((ExpressionBuilder.Visitable value) -> {
567
                if( !(value instanceof ExpressionBuilder.Function) ) {
568
                    return;
569
                }
570
                ExpressionBuilder.Function function = (ExpressionBuilder.Function) value;
571
                if( StringUtils.equalsIgnoreCase(function.name(), ExpressionBuilder.FUNCTION_$HOSTEXPRESSION) ) {
572
                    hostExpressions.add(function);
573
                }
574
        }, null);
575
        return hostExpressions;
576
    }
577

    
578
    public ExpressionBuilder.Value getHostExpressionValue(ExpressionBuilder.Function hostExpression, ExpressionBuilder expbuilder) {
579
        return this.getHostExpressionValue(hostExpression, expbuilder, null, null);        
580
    }
581
    
582
    public ExpressionBuilder.Value getHostExpressionValue(ExpressionBuilder.Function hostExpression, ExpressionBuilder expbuilder, SymbolTable symbolTable) {
583
        Interpreter interpreter = this.createInterpreter();
584
        if( symbolTable!=null ) {
585
            interpreter.setSymbolTable(symbolTable);
586
        }
587
        return this.getHostExpressionValue(hostExpression, expbuilder, null, interpreter);        
588
    }
589
    
590
    public ExpressionBuilder.Value getHostExpressionValue(ExpressionBuilder.Function hostExpression, ExpressionBuilder expbuilder, Compiler compiler, Interpreter interpreter) {
591
        if( expbuilder == null ) {
592
            expbuilder = this.createExpressionBuilder();
593
        }
594
        if( compiler == null ) {
595
            compiler = this.createCompiler();
596
        }
597
        if( interpreter == null ) {
598
            interpreter = this.createInterpreter();
599
        }
600
        List<ExpressionBuilder.Value> params = hostExpression.parameters();
601
        String mode_specifier;
602
        ExpressionBuilder.Value exp;
603
        switch(params.size()) {
604
            case 1:
605
            default:
606
                exp = params.get(0);
607
                mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_IN;
608
                break;
609
            case 2:
610
                exp = params.get(0);
611
                mode_specifier = Objects.toString(((ExpressionBuilder.Constant)params.get(1)).value(),"IN").toUpperCase();
612
                break;
613
        }
614
        Code code = compiler.compileExpression(exp.toString());
615
        Object v = interpreter.run(code);
616
        ExpressionBuilder.Value value;
617
        switch(mode_specifier) {
618
            case $HostExpressionFunction.MODE_SPECIFIER_IN:
619
            default:
620
                value = expbuilder.constant(v);
621
                break;
622
            case $HostExpressionFunction.MODE_SPECIFIER_OUT:
623
            case $HostExpressionFunction.MODE_SPECIFIER_INOUT:
624
                throw new UnsupportedOperationException("Mode OUT/INOUT not implemented");
625
            case $HostExpressionFunction.MODE_SPECIFIER_ID:
626
                value = expbuilder.variable(Objects.toString(v, null));
627
                break;
628
        }
629
        return value;
630
    }
631
    
632
    public List<ExpressionBuilder.Value> getHostExpressionsValuesFromValues(Interpreter interpreter, List<ExpressionBuilder.Value> hostExpressions) throws Exception {
633
        ExpressionBuilder expbuilder = this.createExpressionBuilder();
634
        Compiler compiler = this.createCompiler();
635
        List<ExpressionBuilder.Value> values = new ArrayList<>();        
636
        for (ExpressionBuilder.Value value : hostExpressions) {            
637
            ExpressionBuilder.Function hostExpression = (ExpressionBuilder.Function)value;
638
            values.add(this.getHostExpressionValue(hostExpression, expbuilder, compiler, interpreter));
639
        }
640
        return values;
641
    }
642
        
643
    public List<Code> getHostExpressionsValuesFromCodes(Interpreter interpreter, List<Code> hostExpressions) throws Exception {
644
        CodeBuilder codeBuilder = ((DefaultInterpreter)interpreter).getCodeBuilder();
645
        List<Code> values = new ArrayList<>();
646
        for (Code code : hostExpressions) {
647
            Code.Callable hostExpression = (Code.Callable)code;
648
            Codes params = hostExpression.parameters();
649
            String mode_specifier;
650
            Code exp;
651
            switch(params.size()) {
652
                case 1:
653
                default:
654
                    exp = params.get(0);
655
                    mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_IN;
656
                    break;
657
                case 2:
658
                    exp = params.get(0);
659
                    mode_specifier = Objects.toString(((Code.Constant)params.get(1)).value(),"IN").toUpperCase();
660
                    break;
661
            }
662
            Object v = interpreter.run(exp);
663
            Code replacement;
664
            switch(mode_specifier) {
665
                case $HostExpressionFunction.MODE_SPECIFIER_IN:
666
                default:
667
                    replacement = codeBuilder.constant(v);
668
                    break;
669
                case $HostExpressionFunction.MODE_SPECIFIER_OUT:
670
                case $HostExpressionFunction.MODE_SPECIFIER_INOUT:
671
                    throw new UnsupportedOperationException("Mode OUT/INOUT not implemented");
672
                case $HostExpressionFunction.MODE_SPECIFIER_ID:
673
                    replacement = codeBuilder.identifier(Objects.toString(v, null));
674
                    break;
675
            }
676
            values.add(replacement);
677
        }
678
        return values;
679
    }
680
        
681

    
682
    @Override
683
    public Code resolveHostExpressions(Code statement, Interpreter interpreter) {
684
        try {
685
            if( !hasHostExpressions(statement) ) {
686
                return statement;
687
            }
688
            Code newstatement = (Code) statement.clone();
689
            List<Code> hostExpressions = getHostExpressions(newstatement);
690
            if (hostExpressions.isEmpty()) {
691
                return statement;
692
            }
693
            List<Code> replacements = getHostExpressionsValuesFromCodes(interpreter, hostExpressions);
694

    
695
            for (int i = 0; i < hostExpressions.size(); i++) {
696
                Code hostExpression = hostExpressions.get(i);
697
                Code value = replacements.get(i);
698
                newstatement.replace(hostExpression, value);
699
            }
700
            return newstatement;
701
        } catch (Exception ex) {
702
            throw new RuntimeException("Can't resolve host expressions", ex);
703
        }
704
    }
705
    
706
    @Override
707
    public ExpressionBuilder.Value resolveHostExpressions(ExpressionBuilder.Value statement, SymbolTable symbolTable) {
708
        try {
709
            if( !hasHostExpressions(statement) ) {
710
                return statement;
711
            }
712
            ExpressionBuilder.Value newstatement = (ExpressionBuilder.Value) statement.clone();
713
            List<ExpressionBuilder.Value> hostExpressions = getHostExpressions(newstatement);
714
            if (hostExpressions.isEmpty()) {
715
                return statement;
716
            }
717
            
718
            Interpreter interpreter = this.createInterpreter();
719
            if( symbolTable!=null ) {
720
                interpreter.setSymbolTable(symbolTable);
721
            }
722
            List<ExpressionBuilder.Value> replacements = this.getHostExpressionsValuesFromValues(interpreter, hostExpressions);
723

    
724
            for (int i = 0; i < hostExpressions.size(); i++) {
725
                ExpressionBuilder.Value hostExpression = hostExpressions.get(i);
726
                ExpressionBuilder.Value value = replacements.get(i);
727
                newstatement.replace(hostExpression, value);
728
            }
729
            return newstatement;
730
        } catch (Exception ex) {
731
            throw new RuntimeException("Can't resolve host expressions", ex);
732
        }
733
    }
734
    
735
    @Override
736
    public Code resolveHostExpressions(Code statement, SymbolTable symbolTable) {
737
        try {
738
            if( !hasHostExpressions(statement) ) {
739
                return statement;
740
            }
741
            Code newstatement = (Code) statement.clone();
742
            List<Code> hostExpressions = getHostExpressions(newstatement);
743
            if (hostExpressions.isEmpty()) {
744
                return statement;
745
            }
746
            Interpreter interpreter = this.createInterpreter();
747
            if( symbolTable!=null ) {
748
                interpreter.setSymbolTable(symbolTable);
749
            }
750
            List<Code> replacements = this.getHostExpressionsValuesFromCodes(interpreter, hostExpressions);
751

    
752
            for (int i = 0; i < hostExpressions.size(); i++) {
753
                Code hostExpression = hostExpressions.get(i);
754
                Code value = replacements.get(i);
755
                newstatement.replace(hostExpression, value);
756
            }
757
            return newstatement;
758
        } catch (Exception ex) {
759
            throw new RuntimeException("Can't resolve host expressions", ex);
760
        }
761
    }
762
    
763
    @Override
764
    public Expression resolveHostExpressions(Expression expression, SymbolTable symbolTable) {
765
            Code newcode = this.resolveHostExpressions(expression.getCode(), symbolTable);
766
            if( newcode == expression.getCode() ) {
767
                // No hay "hosts expressions", devolvemos la expresion original.
768
                return expression;
769
            }
770
            DefaultExpression exp = new DefaultExpression(this);
771
            exp.setPhrase(newcode.toValue().toString());
772
            return exp;
773
    }
774

    
775
}
776