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

History | View | Annotate | Download (11.8 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.gvsig.expressionevaluator.Code;
8
import org.gvsig.expressionevaluator.Compiler;
9
import org.gvsig.expressionevaluator.Expression;
10
import org.gvsig.expressionevaluator.ExpressionEvaluator;
11
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
12
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
13
import org.gvsig.expressionevaluator.ExpressionUtils;
14
import org.gvsig.expressionevaluator.Interpreter;
15
import org.gvsig.expressionevaluator.Optimizer;
16
import org.gvsig.expressionevaluator.SymbolTable;
17
import org.gvsig.json.Json;
18
import org.gvsig.json.JsonManager;
19
import org.gvsig.json.JsonObjectBuilder;
20
import org.gvsig.json.SupportToJson;
21
import org.gvsig.tools.ToolsLocator;
22
import org.gvsig.tools.dynobject.DynStruct;
23
import org.gvsig.tools.evaluator.Evaluator;
24
import org.gvsig.tools.packageutils.Version;
25
import org.gvsig.tools.packageutils.impl.DefaultVersion;
26
import org.gvsig.tools.persistence.PersistenceManager;
27
import org.gvsig.tools.persistence.PersistentState;
28
import org.gvsig.tools.persistence.exception.PersistenceException;
29
import org.gvsig.tools.script.ScriptManager;
30
import org.gvsig.tools.util.LabeledValue;
31
import org.slf4j.Logger;
32
import org.slf4j.LoggerFactory;
33

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
233
        this.clear();
234

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

    
239
    }
240

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

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

    
252
        }
253
    }
254

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

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

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

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

    
293
    @Override
294
    public String toString() {
295
        return this.toJson().toString();
296
    }
297

    
298
    @Override
299
    public Expression clone() throws CloneNotSupportedException {
300
        Expression other = (Expression) super.clone();
301
        other.fromJSON(this.toJSON());
302
        return other;
303
    }
304

    
305
    @Override
306
    public void setUseBracketsForIdentifiers(boolean useBracketsForIdentifiers) {
307
        this.useBracketsForIdentifiers = useBracketsForIdentifiers;
308
    }
309
    
310
    @Override
311
    public boolean getUseBracketsForIdentifiers() {
312
        return this.useBracketsForIdentifiers;
313
    }
314

    
315
    @Override
316
    public Evaluator toEvaluator() {
317
        ExpressionEvaluator evaluator = this.manager.createExpressionEvaluator(this);
318
        return evaluator;
319
    }
320
    
321
    public static void selfRegister() {
322
        Json.registerSerializer(new TheJsonSerializer());
323
    }
324

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

    
352
        @Override
353
        public Class getObjectClass() {
354
            return DefaultExpression.class;
355
        }
356

    
357
        @Override
358
        public Object toObject(JsonObject json) {
359
            DefaultExpression o = new DefaultExpression();
360
            o.fromJson(json);
361
            return o;
362
        }
363

    
364
        @Override
365
        public JsonObjectBuilder toJsonBuilder(Object value) {
366
            return ((SupportToJson)value).toJsonBuilder();
367
        }
368
        
369
    }
370

    
371

    
372

    
373
}