Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.api / src / main / java / org / gvsig / expressionevaluator / spi / AbstractSymbolTable.java @ 47184

History | View | Annotate | Download (9.52 KB)

1 43983 jjdelcerro
package org.gvsig.expressionevaluator.spi;
2
3
import java.util.ArrayList;
4
import java.util.Collection;
5
import java.util.Collections;
6
import java.util.HashMap;
7
import java.util.HashSet;
8
import java.util.Iterator;
9
import java.util.List;
10
import java.util.Map;
11
import java.util.Set;
12
import org.apache.commons.lang3.StringUtils;
13
import org.gvsig.expressionevaluator.Function;
14 45980 jjdelcerro
import org.gvsig.expressionevaluator.MutableSymbolTable;
15 43983 jjdelcerro
import org.gvsig.expressionevaluator.SymbolTable;
16 45739 jjdelcerro
import org.gvsig.tools.util.GetItemByKey;
17 47184 jjdelcerro
import org.slf4j.Logger;
18
import org.slf4j.LoggerFactory;
19 43983 jjdelcerro
20
/**
21
 *
22
 * @author jjdelcerro
23
 */
24 45739 jjdelcerro
public abstract class AbstractSymbolTable implements SymbolTable, GetItemByKey<String, Object> {
25 43983 jjdelcerro
26 47184 jjdelcerro
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSymbolTable.class);
27
28 43983 jjdelcerro
    private final String name;
29
30
31 45980 jjdelcerro
    protected Map<String, Object> vars;
32 45620 jjdelcerro
33 45980 jjdelcerro
    protected List<SymbolTable> symbolTables;
34 43983 jjdelcerro
    protected Map<String, Function> functions;
35 44139 jjdelcerro
    protected Map<String, Function> functionAlias;
36 43983 jjdelcerro
37
    public AbstractSymbolTable() {
38
        this(null);
39
    }
40
41
    public AbstractSymbolTable(String name) {
42 45739 jjdelcerro
        if( name == null ) {
43
            this.name = "Anonymous";
44
        } else {
45
            this.name = name;
46
        }
47 43983 jjdelcerro
        this.symbolTables = new ArrayList<>();
48
        this.vars = null;
49
        this.functions = null;
50 44139 jjdelcerro
        this.functionAlias = null;
51 43983 jjdelcerro
    }
52
53
    @Override
54
    public String getName() {
55
        return name;
56
    }
57 43987 jjdelcerro
58 45620 jjdelcerro
    public void addFunction(Function function) {
59 43987 jjdelcerro
        if (function == null) {
60
            throw new IllegalArgumentException("function can't be null");
61
        }
62
        this.getFunctions().put(function.name().toUpperCase(), function);
63 44139 jjdelcerro
        List<String> aliases = function.aliases();
64
        if( aliases == null || aliases.isEmpty() ) {
65
            return;
66
        }
67
        Map<String, Function> theFunctionAlias = this.getFunctionAlias();
68
        for (String alias : aliases) {
69
            if( alias!=null ) {
70
                theFunctionAlias.put(alias, function);
71
            }
72
        }
73 43987 jjdelcerro
    }
74 43983 jjdelcerro
75 45620 jjdelcerro
    public void addFunctions(Collection<Function> functions) {
76
        for (Function function : functions) {
77
            this.addFunction(function);
78
        }
79
    }
80
81
    public void removeFunction(String name) {
82
        if( StringUtils.isEmpty(name) ) {
83
            throw new IllegalArgumentException("name can't be null");
84
        }
85
        this.functions.remove(name.toUpperCase());
86
    }
87
88 43983 jjdelcerro
    @Override
89 44215 jjdelcerro
    public boolean addSymbolTable(SymbolTable symbolTable) {
90 44838 jjdelcerro
        if( symbolTable==null ) {
91
          throw new IllegalArgumentException("Invalid symbol table (null)");
92
        }
93 47184 jjdelcerro
        if (this == symbolTable && this.symbolTables.contains(symbolTable)) {
94 44215 jjdelcerro
            return false;
95 43983 jjdelcerro
        }
96 44836 jjdelcerro
        this.symbolTables.add(0,symbolTable);
97 44215 jjdelcerro
        return true;
98 43983 jjdelcerro
    }
99
100 44215 jjdelcerro
    @Override
101
    public boolean containsSymbolTable(SymbolTable symbolTable) {
102
        return this.symbolTables.contains(symbolTable);
103
    }
104
105
    @Override
106
    public boolean removeSymbolTable(SymbolTable symbolTable) {
107
        boolean n = this.symbolTables.remove(symbolTable);
108
        return n;
109
    }
110
111 43983 jjdelcerro
    protected Map<String, Object> getVars() {
112
        if (this.vars == null) {
113
            this.vars = new HashMap<>();
114
        }
115
        return this.vars;
116
    }
117
118 45620 jjdelcerro
    public void setVar(String name, Object value) {
119
        if( StringUtils.isEmpty(name) ) {
120
            throw new IllegalArgumentException("name can't be null");
121
        }
122
        this.getVars().put(name.toUpperCase(), value);
123
    }
124
125
    public void removeVar(String name) {
126
        if( StringUtils.isEmpty(name) ) {
127
            throw new IllegalArgumentException("name can't be null");
128
        }
129
        this.getVars().remove(name.toUpperCase());
130
    }
131
132 43983 jjdelcerro
    protected Map<String, Function> getFunctions() {
133
        if (this.functions == null) {
134
            this.functions = new HashMap<>();
135
        }
136
        return this.functions;
137
    }
138
139 44139 jjdelcerro
    protected Map<String, Function> getFunctionAlias() {
140
        if (this.functionAlias == null) {
141
            this.functionAlias = new HashMap<>();
142
        }
143
        return this.functionAlias;
144
    }
145
146 43983 jjdelcerro
    @Override
147
    public boolean exists(String name) {
148
        if (StringUtils.isEmpty(name)) {
149
            return false;
150
        }
151 45620 jjdelcerro
        if (this.getVars().containsKey(name.toUpperCase())) {
152
            return true;
153 43983 jjdelcerro
        }
154 45739 jjdelcerro
        if( StringUtils.equalsIgnoreCase(name, "$symboltable") )  {
155
            return true;
156
        }
157 43983 jjdelcerro
        for (SymbolTable other : this.symbolTables) {
158 47184 jjdelcerro
            if( other == this ) {
159
                continue;
160
            }
161 43983 jjdelcerro
            if (other.exists(name)) {
162
                return true;
163
            }
164
        }
165
        return false;
166
    }
167
168
    @Override
169
    public Object value(String name) {
170
        if (StringUtils.isEmpty(name)) {
171
            return null;
172
        }
173 45620 jjdelcerro
        name = name.toUpperCase();
174
        if (this.getVars().containsKey(name)) {
175
            return this.getVars().get(name);
176 43983 jjdelcerro
        }
177 45739 jjdelcerro
        if( name.equals("$SYMBOLTABLE") ) {
178
            return this;
179
        }
180 43983 jjdelcerro
        for (SymbolTable other : this.symbolTables) {
181
            if (other.exists(name)) {
182
                return other.value(name);
183
            }
184 45739 jjdelcerro
            if( StringUtils.equalsIgnoreCase(name, other.getName())) {
185
                return other;
186
            }
187 43983 jjdelcerro
        }
188
        return null;
189
    }
190
191
    @Override
192 45739 jjdelcerro
    public Object get(String name) {
193
        return this.value(name);
194
    }
195
196
    @Override
197 43983 jjdelcerro
    public Function function(String name) {
198
        if (StringUtils.isEmpty(name)) {
199
            return null;
200
        }
201
        if (this.functions != null) {
202
            name = name.toUpperCase();
203
            if (this.functions.containsKey(name)) {
204
                return this.functions.get(name);
205
            }
206
        }
207 44139 jjdelcerro
        if (this.functionAlias != null) {
208
            name = name.toUpperCase();
209
            if (this.functionAlias.containsKey(name)) {
210
                return this.functionAlias.get(name);
211
            }
212
        }
213 43983 jjdelcerro
        for (SymbolTable other : this.symbolTables) {
214
            Function fn = other.function(name);
215
            if (fn != null) {
216
                return fn;
217
            }
218
        }
219 44533 jjdelcerro
        return null;
220 43983 jjdelcerro
    }
221
222
    @Override
223
    public Collection<String> variables() {
224
        Set<String> theVars = new HashSet<>();
225
        for (SymbolTable symbolTable : this.symbolTables) {
226
            theVars.addAll(symbolTable.variables());
227
        }
228 44398 jjdelcerro
        theVars.addAll(this.localvariables());
229 43983 jjdelcerro
        return Collections.unmodifiableCollection(theVars);
230
    }
231
232
    @Override
233
    public Collection<Function> functions() {
234
        Set<Function> theFunctions = new HashSet<>();
235
        for (SymbolTable symbolTable : this.symbolTables) {
236
            theFunctions.addAll(symbolTable.functions());
237
        }
238
        if (this.functions != null) {
239
            theFunctions.addAll(this.functions.values());
240
        }
241
        return Collections.unmodifiableCollection(theFunctions);
242
    }
243
244
    @Override
245 44338 jjdelcerro
    public Collection<Function> localfunctions() {
246
        if( this.functions == null ) {
247
            return Collections.EMPTY_LIST;
248
        }
249
        return Collections.unmodifiableCollection(this.functions.values());
250
    }
251
252
    @Override
253 44340 jjdelcerro
    public Collection<String> localvariables() {
254 45703 jjdelcerro
        if( this.getVars().isEmpty()) {
255 44340 jjdelcerro
            return Collections.EMPTY_LIST;
256
        }
257
        return Collections.unmodifiableCollection(this.vars.keySet());
258
    }
259
260
    @Override
261 43983 jjdelcerro
    public Iterator<Function> iterator() {
262
        return this.functions().iterator();
263
    }
264
265
    @Override
266
    public SymbolTable clone() throws CloneNotSupportedException {
267 45980 jjdelcerro
        AbstractSymbolTable other = (AbstractSymbolTable) super.clone();
268
        if( this instanceof MutableSymbolTable ) {
269 46010 jjdelcerro
            if( this.vars!=null ) {
270
                other.vars = new HashMap<>(this.vars);
271
            }
272
            if( this.functions!=null ) {
273
                other.functions = new HashMap<>(this.functions);
274
            }
275
            if( this.functionAlias!=null ) {
276
                other.functionAlias = new HashMap<>(this.functionAlias);
277
            }
278 45980 jjdelcerro
        }
279
        other.symbolTables = new ArrayList<>();
280 46010 jjdelcerro
        if( this.symbolTables!=null ) {
281
            for (SymbolTable symbolTable : this.symbolTables) {
282
                other.symbolTables.add(symbolTable.clone());
283
            }
284 45980 jjdelcerro
        }
285 43983 jjdelcerro
        return other;
286
    }
287
288 44205 jjdelcerro
    @Override
289
    public boolean isSQLCompatible(String name) {
290
        Function f = function(name);
291
        if( f!=null ) {
292
            return f.isSQLCompatible();
293
        }
294
        return true;
295
    }
296
297 45739 jjdelcerro
    public List<SymbolTable> getSymbolTables() {
298
        return Collections.unmodifiableList(symbolTables);
299
    }
300
301
    @Override
302
    public String toString() {
303
        return this.name;
304
    }
305
306 47184 jjdelcerro
    protected void fixSymbolTables(Set<SymbolTable> visiteds) {
307
        if( visiteds == null ) {
308
            visiteds = new HashSet<>();
309
        }
310
        visiteds.add(this);
311
        List<SymbolTable> toRemove = new ArrayList<>();
312
        for (SymbolTable other : this.symbolTables) {
313
            if( other == null ) {
314
                continue;
315
            }
316
            if( visiteds.contains(other) ) {
317
                toRemove.add(other);
318
                LOGGER.warn("Remove symbol table '"+other.getName()+"', recursive reference.");
319
            } else if( other instanceof AbstractSymbolTable ) {
320
                ((AbstractSymbolTable) other).fixSymbolTables(visiteds);
321
            }
322
        }
323
        for (SymbolTable symbolTable : toRemove) {
324
            this.symbolTables.remove(symbolTable);
325
        }
326
    }
327
328
    public void fixSymbolTables() {
329
        this.fixSymbolTables(null);
330
    }
331 43983 jjdelcerro
}