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 / DefaultExpression.java @ 47734

History | View | Annotate | Download (12.1 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.lang.ref.WeakReference;
4
import java.util.Objects;
5
import javax.json.JsonObject;
6
import org.apache.commons.lang3.StringUtils;
7
import org.apache.commons.lang3.builder.ToStringBuilder;
8
import org.gvsig.expressionevaluator.Code;
9
import org.gvsig.expressionevaluator.Compiler;
10
import org.gvsig.expressionevaluator.Expression;
11
import org.gvsig.expressionevaluator.ExpressionEvaluator;
12
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
13
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
14
import org.gvsig.expressionevaluator.ExpressionUtils;
15
import org.gvsig.expressionevaluator.Interpreter;
16
import org.gvsig.expressionevaluator.Optimizer;
17
import org.gvsig.expressionevaluator.SymbolTable;
18
import org.gvsig.json.Json;
19
import org.gvsig.json.JsonManager;
20
import org.gvsig.json.JsonObjectBuilder;
21
import org.gvsig.json.SupportToJson;
22
import org.gvsig.tools.ToolsLocator;
23
import org.gvsig.tools.dynobject.DynStruct;
24
import org.gvsig.tools.evaluator.Evaluator;
25
import org.gvsig.tools.packageutils.Version;
26
import org.gvsig.tools.packageutils.impl.DefaultVersion;
27
import org.gvsig.tools.persistence.PersistenceManager;
28
import org.gvsig.tools.persistence.PersistentState;
29
import org.gvsig.tools.persistence.exception.PersistenceException;
30
import org.gvsig.tools.script.ScriptManager;
31
import org.gvsig.tools.util.LabeledValue;
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
/**
36
 *
37
 * @author jjdelcerro
38
 */
39
public class DefaultExpression implements Expression, LabeledValue<Expression> {
40
    
41
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExpression.class);
42
    
43
    private static final Version VERSION_2_6_0_1 = ToolsLocator.getPackageManager().createVersion("2.6.0-1");
44

    
45
    //?Ojo!, esto est? copiado de DataAccessGrammarFactory por cuestiones de dependencias. Si lo tocamos hay que tocarlo en los dos lados
46
    public static final String COMPATIBILITY_SELECT_ID = "SELECT";
47
    public static final String COMPATIBILITY_SELECT_OPTIONAL_SEMICOLON_AT_END = "OPTIONAL_SEMICOLON_AT_END";
48
    
49
    private String phrase = null;
50

    
51
    private Code code = null;
52
    private Interpreter interpreter;
53
    private boolean hasNotBeenOptimized = true;
54
    private SymbolTable mySymbolTable = null;
55
    private WeakReference<SymbolTable> lastSymbolTable = null;    
56
    private boolean useBracketsForIdentifiers = false;
57
    protected ExpressionEvaluatorManager manager;
58

    
59
    public DefaultExpression() {
60
        this(ExpressionEvaluatorLocator.getExpressionEvaluatorManager());
61
    }
62

    
63
    public DefaultExpression(ExpressionEvaluatorManager manager) {
64
        this.manager = manager;
65
    }
66
    
67
    @Override
68
    public String getLabel() {
69
        return StringUtils.abbreviate(
70
                StringUtils.normalizeSpace(this.getPhrase()),
71
                35
72
        );
73
    }
74

    
75
    @Override
76
    public Expression getValue() {
77
        return this;
78
    }
79

    
80
    @Override
81
    public boolean equals(Object obj) {
82
        if( obj == null || !(obj instanceof Expression) ) {
83
            return false;
84
        }
85
        String this_s = this.toJSON();
86
        String other_s = ((Expression)obj).toJSON();
87
        return this_s.equals(other_s);
88
    }
89

    
90
    @Override
91
    public int hashCode() {
92
        String this_s = this.toJSON();
93
        return Objects.hashCode(this_s);
94
    }
95
    
96
    @Override
97
    public SymbolTable getSymbolTable() {
98
        if( this.mySymbolTable==null ) {
99
            this.mySymbolTable = ExpressionUtils.createSymbolTable();
100
        }
101
        return this.mySymbolTable;
102
    }
103

    
104
    @Override
105
    public String getPhrase() {
106
        return this.phrase;
107
    }
108

    
109
    @Override
110
    public boolean isPhraseEmpty() {
111
        return StringUtils.isBlank(this.phrase);
112
    }
113

    
114
    @Override
115
    public boolean isEmpty() {
116
        if( !StringUtils.isBlank(this.phrase) ) {
117
            return false;
118
        }
119
        return true;
120
    }
121

    
122
    @Override
123
    public Expression setPhrase(String phrase) {
124
        this.phrase = phrase;
125
        this.code = null;
126
        this.hasNotBeenOptimized = true;
127
        return this;
128
    }
129

    
130
    @Override
131
    public void clear() {
132
        this.phrase = null;
133
        this.code = null;
134
        this.interpreter = null;
135
        this.hasNotBeenOptimized = true;
136
    }
137

    
138
    @Override
139
    public Code getCode() {
140
        if (this.code == null) {
141
            Compiler compiler = this.manager.createCompiler();
142
            compiler.getLexicalAnalyzer().setUseBracketsForIdentifiers(
143
                    this.useBracketsForIdentifiers
144
            );
145
            this.code = compiler.compileExpression(this.phrase);
146
        }
147
        return code;
148
    }
149

    
150
    @Override
151
    public void setSQLCompatible(boolean sqlCompatible) {
152
        this.getInterpreter().setSQLCompatible(sqlCompatible);
153
    }
154

    
155
    @Override
156
    public boolean isSQLCompatible() {
157
        return this.getInterpreter().isSQLCompatible();
158
    }
159

    
160
    private Interpreter getInterpreter() {
161
        if (this.interpreter == null) {
162
            this.interpreter = this.manager.createInterpreter();
163
        }
164
        return this.interpreter;
165
    }
166
    
167
    @Override
168
    public Object execute(SymbolTable symbolTable) {
169
        if (this.interpreter == null) {
170
            this.interpreter = this.manager.createInterpreter();
171
        }        
172
        boolean added = false;
173
        if( symbolTable!=null ) {
174
            added = this.getSymbolTable().addSymbolTable(symbolTable);
175
            if( this.lastSymbolTable==null ) {
176
                this.lastSymbolTable = new WeakReference<>(symbolTable);            
177
            } else if( this.lastSymbolTable.get()!=symbolTable ) {  //FIXME: siempre da true
178
                this.link(this.getSymbolTable());
179
                this.hasNotBeenOptimized = true;            
180
            }
181
        }
182
        try {
183
            this.interpreter.setSymbolTable(this.getSymbolTable());
184
            if( this.hasNotBeenOptimized  ) {
185
                try {
186
                    Optimizer optimizer = this.manager.createOptimizer();
187
                    optimizer.setSymbolTable(this.getSymbolTable());
188
                    this.code = optimizer.optimize(this.getCode());
189
                } catch(Throwable th) {
190
                    // Si no es capaz de optimizar la expresion no, peta y la
191
                    // ejecuta tal cual.
192
                }
193
                this.hasNotBeenOptimized = false;
194
            }
195
            Code code_exp = this.getCode();
196
            if( this.manager.hasHostExpressions(code_exp) ) {
197
                code_exp = this.manager.resolveHostExpressions(code_exp, interpreter);
198
            }
199
            Object x = this.interpreter.run(code_exp);
200

    
201
            return x;
202
        } finally {
203
            if( added ) {
204
                this.getSymbolTable().removeSymbolTable(symbolTable);
205
            }
206
        }
207
    }
208

    
209
    @Override
210
    public void link(SymbolTable symbolTable) {
211
        if (this.interpreter == null) {
212
            this.interpreter = this.manager.createInterpreter();
213
        }
214
        this.lastSymbolTable = new WeakReference<>(symbolTable);            
215
        this.interpreter.setSymbolTable(symbolTable);
216
        if( this.hasNotBeenOptimized  ) {
217
            Optimizer optimizer = new DefaultOptimizer(this.manager, symbolTable);
218
            this.code = optimizer.optimize(this.getCode());
219
            this.hasNotBeenOptimized = false;
220
        }
221
        this.interpreter.link(this.getCode());
222
    }
223

    
224
    @Override
225
    public void saveToState(PersistentState state) throws PersistenceException {
226
        state.set("version", VERSION_2_6_0_1);
227
        state.set("phrase", this.phrase);
228
    }
229

    
230
    @Override
231
    public void loadFromState(PersistentState state) throws PersistenceException {
232
        ScriptManager scriptManager = ToolsLocator.getScriptManager();
233

    
234
        this.clear();
235

    
236
        Version version = (Version) state.get("version");
237
        this.phrase = state.getString("phrase");
238
        this.fixCompatibility(version);
239

    
240
    }
241

    
242
    public static void registerPersistence() {
243
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
244
        if (manager.getDefinition("Expression") == null) {
245
            DynStruct definition = manager.addDefinition(DefaultExpression.class,
246
                    "Expression", "Expression persistence definition", null, null);
247
            definition.addDynFieldString("phrase").setMandatory(false);
248

    
249
            definition.addDynFieldObject("version")
250
                    .setClassOfValue(DefaultVersion.class)
251
                    .setMandatory(false);
252

    
253
        }
254
    }
255

    
256
    @Override
257
    public JsonObject toJson() {
258
        return this.toJsonBuilder().build();
259
    }
260

    
261
    @Override
262
    public JsonObjectBuilder toJsonBuilder() {
263
        JsonObjectBuilder builder = Json.createObjectBuilder();
264
        builder.add_class(this);
265
        builder.add("phrase", this.phrase);
266
        builder.add("version", VERSION_2_6_0_1.toString());
267
        return builder;
268
    }
269
    
270
    @Override
271
    public void fromJson(JsonObject values) {
272
        this.clear();
273
        if( values.containsKey("phrase") ) {
274
            this.phrase = values.getString("phrase");
275
        }
276
        String version_s = values.getString("version", null);
277
        Version version = ToolsLocator.getPackageManager().createVersion(version_s);
278
        this.fixCompatibility(version);
279

    
280
    }
281
    
282
    @Deprecated
283
    @Override
284
    public String toJSON() {
285
        return toJson().toString();
286
    }
287

    
288
    @Deprecated
289
    @Override
290
    public void fromJSON(String json) {
291
        this.fromJson(Json.createObject(json));
292
    }
293

    
294
    @Override
295
    public Expression clone() throws CloneNotSupportedException {
296
        Expression other = (Expression) super.clone();
297
//        other.fromJSON(this.toJSON());
298
        other.fromJson(this.toJson());
299
        return other;
300
    }
301

    
302
    @Override
303
    public String toString() {
304
        try {
305
            ToStringBuilder builder = new ToStringBuilder(this);
306
            builder.append("phrase", this.phrase);
307
            return builder.toString();
308
        } catch (Exception e) {
309
            return super.toString();
310
        }
311
    }
312
    
313
    @Override
314
    public void setUseBracketsForIdentifiers(boolean useBracketsForIdentifiers) {
315
        this.useBracketsForIdentifiers = useBracketsForIdentifiers;
316
    }
317
    
318
    @Override
319
    public boolean getUseBracketsForIdentifiers() {
320
        return this.useBracketsForIdentifiers;
321
    }
322

    
323
    @Override
324
    public Evaluator toEvaluator() {
325
        ExpressionEvaluator evaluator = this.manager.createExpressionEvaluator(this);
326
        return evaluator;
327
    }
328
    
329
    public static void selfRegister() {
330
        Json.registerSerializer(new TheJsonSerializer());
331
    }
332

    
333
    private void fixCompatibility(Version version) {
334
        if (version == null || version.compareTo(VERSION_2_6_0_1) < 0) {
335
            try {
336
                if (StringUtils.isNotBlank(this.phrase)) {
337
                    ExpressionEvaluatorManager expressionManager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
338
                    org.gvsig.expressionevaluator.Compiler compiler = expressionManager.createCompiler();
339
                    compiler.addCompatibility(
340
                            COMPATIBILITY_SELECT_ID,
341
                            COMPATIBILITY_SELECT_OPTIONAL_SEMICOLON_AT_END
342
                    );
343
                    Code code = compiler.compileExpressionQuietly(this.phrase);
344
                    if (code != null) {
345
                        code.link();
346
                        this.phrase = code.toString(new Code.EmptyFormatter(true, 4));
347
                    }
348
                }
349
            } catch (Throwable t) {
350
                LOGGER.warn("Can't check select compatibility in select ("+this.phrase+")", t);
351
            }
352
        }
353
    }
354
    
355
    private static class TheJsonSerializer implements JsonManager.JsonSerializer {
356
        
357
        public TheJsonSerializer() {            
358
        }
359

    
360
        @Override
361
        public Class getObjectClass() {
362
            return DefaultExpression.class;
363
        }
364

    
365
        @Override
366
        public Object toObject(JsonObject json) {
367
            DefaultExpression o = new DefaultExpression();
368
            o.fromJson(json);
369
            return o;
370
        }
371

    
372
        @Override
373
        public JsonObjectBuilder toJsonBuilder(Object value) {
374
            return ((SupportToJson)value).toJsonBuilder();
375
        }
376
        
377
    }
378

    
379

    
380

    
381
}