source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java@ 4191

Last change on this file since 4191 was 4191, checked in by stoecker, 13 years ago

remove old debug stuff

  • Property svn:eol-style set to native
File size: 13.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.mapcss;
3
4import static org.openstreetmap.josm.tools.Utils.equal;
5
6import java.awt.Color;
7import java.lang.reflect.Array;
8import java.lang.reflect.InvocationTargetException;
9import java.lang.reflect.Method;
10import java.util.ArrayList;
11import java.util.Arrays;
12import java.util.List;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.actions.search.SearchCompiler;
16import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
17import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.gui.mappaint.Cascade;
20import org.openstreetmap.josm.gui.mappaint.Environment;
21import org.openstreetmap.josm.tools.CheckParameterUtil;
22import org.openstreetmap.josm.tools.Utils;
23
24public interface Expression {
25 public Object evaluate(Environment env);
26
27 public static class LiteralExpression implements Expression {
28 Object literal;
29
30 public LiteralExpression(Object literal) {
31 CheckParameterUtil.ensureParameterNotNull(literal);
32 this.literal = literal;
33 }
34
35 @Override
36 public Object evaluate(Environment env) {
37 return literal;
38 }
39
40 @Override
41 public String toString() {
42 if (literal instanceof float[])
43 return Arrays.toString((float[]) literal);
44 return "<"+literal.toString()+">";
45 }
46 }
47
48 public static class FunctionExpression implements Expression {
49 String name;
50 List<Expression> args;
51
52 public FunctionExpression(String name, List<Expression> args) {
53 this.name = name;
54 this.args = args;
55 }
56
57 public static class EvalFunctions {
58 Environment env;
59
60 public Object eval(Object o) {
61 return o;
62 }
63
64 public static float plus(float... args) {
65 float res = 0;
66 for (float f : args) {
67 res += f;
68 }
69 return res;
70 }
71
72 public Float minus(float... args) {
73 if (args.length == 0)
74 return 0f;
75 if (args.length == 1)
76 return -args[0];
77 float res = args[0];
78 for (int i=1; i<args.length; ++i) {
79 res -= args[i];
80 }
81 return res;
82 }
83
84 public static float times(float... args) {
85 float res = 1;
86 for (float f : args) {
87 res *= f;
88 }
89 return res;
90 }
91
92 public Float devided_by(float... args) {
93 if (args.length == 0)
94 return 1f;
95 float res = args[0];
96 for (int i=1; i<args.length; ++i) {
97 if (args[i] == 0f)
98 return null;
99 res /= args[i];
100 }
101 return res;
102 }
103
104 public static List list(Object... args) {
105 return Arrays.asList(args);
106 }
107
108 public Color rgb(float r, float g, float b) {
109 Color c = null;
110 try {
111 c = new Color(r, g, b);
112 } catch (IllegalArgumentException e) {
113 return null;
114 }
115 return c;
116 }
117
118 public float red(Color c) {
119 return Utils.color_int2float(c.getRed());
120 }
121
122 public float green(Color c) {
123 return Utils.color_int2float(c.getGreen());
124 }
125
126 public float blue(Color c) {
127 return Utils.color_int2float(c.getBlue());
128 }
129
130 public String concat(Object... args) {
131 StringBuilder res = new StringBuilder();
132 for (Object f : args) {
133 res.append(f.toString());
134 }
135 return res.toString();
136 }
137
138 public Object prop(String key) {
139 return prop(key, null);
140 }
141
142 public Object prop(String key, String layer) {
143 Cascade c;
144 if (layer == null) {
145 c = env.mc.getCascade(env.layer);
146 } else {
147 c = env.mc.getCascade(layer);
148 }
149 return c.get(key);
150 }
151
152 public Boolean is_prop_set(String key) {
153 return is_prop_set(key, null);
154 }
155
156 public Boolean is_prop_set(String key, String layer) {
157 Cascade c;
158 if (layer == null) {
159 // env.layer is null if expression is evaluated
160 // in ExpressionCondition, but MultiCascade.getCascade
161 // handles this
162 c = env.mc.getCascade(env.layer);
163 } else {
164 c = env.mc.getCascade(layer);
165 }
166 return c.containsKey(key);
167 }
168
169 public String tag(String key) {
170 return env.osm.get(key);
171 }
172
173 public String parent_tag(String key) {
174 if (env.parent == null) {
175 // we don't have a matched parent, so just search all referrers
176 for (OsmPrimitive parent : env.osm.getReferrers()) {
177 String value = parent.get(key);
178 if (value != null)
179 return value;
180 }
181 return null;
182 }
183 return env.parent.get(key);
184 }
185
186 public boolean has_tag_key(String key) {
187 return env.osm.hasKey(key);
188 }
189
190 public Float index() {
191 if (env.index == null)
192 return null;
193 return new Float(env.index + 1);
194 }
195
196 public String role() {
197 return env.getRole();
198 }
199
200 public boolean not(boolean b) {
201 return !b;
202 }
203
204 public boolean greater_equal(float a, float b) {
205 return a >= b;
206 }
207
208 public boolean less_equal(float a, float b) {
209 return a <= b;
210 }
211
212 public boolean greater(float a, float b) {
213 return a > b;
214 }
215
216 public boolean less(float a, float b) {
217 return a < b;
218 }
219
220 public int length(String s) {
221 return s.length();
222 }
223
224 @SuppressWarnings("unchecked")
225 public boolean equal(Object a, Object b) {
226 // make sure the casts are done in a meaningful way, so
227 // the 2 objects really can be considered equal
228 for (Class klass : new Class[] {
229 Float.class, Boolean.class, Color.class, float[].class, String.class }) {
230 Object a2 = Cascade.convertTo(a, klass);
231 Object b2 = Cascade.convertTo(b, klass);
232 if (a2 != null && b2 != null && a2.equals(b2))
233 return true;
234 }
235 return false;
236 }
237
238 public Boolean JOSM_search(String s) {
239 Match m;
240 try {
241 m = SearchCompiler.compile(s, false, false);
242 } catch (ParseError ex) {
243 return null;
244 }
245 return m.match(env.osm);
246 }
247
248 public String JOSM_pref(String s, String def) {
249 String res = Main.pref.get(s, null);
250 return res != null ? res : def;
251 }
252
253 public Color JOSM_pref_color(String s, Color def) {
254 Color res = Main.pref.getColor(s, null);
255 return res != null ? res : def;
256 }
257 }
258
259 @Override
260 public Object evaluate(Environment env) {
261 if (equal(name, "cond")) { // this needs special handling since only one argument should be evaluated
262 if (args.size() != 3)
263 return null;
264 Boolean b = Cascade.convertTo(args.get(0).evaluate(env), boolean.class);
265 if (b == null)
266 return null;
267 return args.get(b ? 1 : 2).evaluate(env);
268 }
269 if (equal(name, "and")) {
270 for (Expression arg : args) {
271 Boolean b = Cascade.convertTo(arg.evaluate(env), boolean.class);
272 if (b == null || !b)
273 return false;
274 }
275 return true;
276 }
277 if (equal(name, "or")) {
278 for (Expression arg : args) {
279 Boolean b = Cascade.convertTo(arg.evaluate(env), boolean.class);
280 if (b != null && b)
281 return true;
282 }
283 return false;
284 }
285 EvalFunctions fn = new EvalFunctions();
286 fn.env = env;
287 Method[] customMethods = EvalFunctions.class.getDeclaredMethods();
288 List<Method> allMethods = new ArrayList<Method>();
289 allMethods.addAll(Arrays.asList(customMethods));
290 try {
291 allMethods.add(Math.class.getMethod("abs", float.class));
292 allMethods.add(Math.class.getMethod("acos", double.class));
293 allMethods.add(Math.class.getMethod("asin", double.class));
294 allMethods.add(Math.class.getMethod("atan", double.class));
295 allMethods.add(Math.class.getMethod("atan2", double.class, double.class));
296 allMethods.add(Math.class.getMethod("ceil", double.class));
297 allMethods.add(Math.class.getMethod("cos", double.class));
298 allMethods.add(Math.class.getMethod("cosh", double.class));
299 allMethods.add(Math.class.getMethod("exp", double.class));
300 allMethods.add(Math.class.getMethod("floor", double.class));
301 allMethods.add(Math.class.getMethod("log", double.class));
302 allMethods.add(Math.class.getMethod("max", float.class, float.class));
303 allMethods.add(Math.class.getMethod("min", float.class, float.class));
304 allMethods.add(Math.class.getMethod("random"));
305 allMethods.add(Math.class.getMethod("round", float.class));
306 allMethods.add(Math.class.getMethod("signum", double.class));
307 allMethods.add(Math.class.getMethod("sin", double.class));
308 allMethods.add(Math.class.getMethod("sinh", double.class));
309 allMethods.add(Math.class.getMethod("sqrt", double.class));
310 allMethods.add(Math.class.getMethod("tan", double.class));
311 allMethods.add(Math.class.getMethod("tanh", double.class));
312 } catch (NoSuchMethodException ex) {
313 throw new RuntimeException(ex);
314 } catch (SecurityException ex) {
315 throw new RuntimeException(ex);
316 }
317 for (Method m : allMethods) {
318 if (!m.getName().equals(name)) {
319 continue;
320 }
321 Class<?>[] expectedParameterTypes = m.getParameterTypes();
322 Object[] convertedArgs = new Object[expectedParameterTypes.length];
323
324 if (expectedParameterTypes.length == 1 && expectedParameterTypes[0].isArray())
325 {
326 Class<?> arrayComponentType = expectedParameterTypes[0].getComponentType();
327 Object arrayArg = Array.newInstance(arrayComponentType, args.size());
328 for (int i=0; i<args.size(); ++i)
329 {
330 Object o = Cascade.convertTo(args.get(i).evaluate(env), arrayComponentType);
331 if (o == null)
332 return null;
333 Array.set(arrayArg, i, o);
334 }
335 convertedArgs[0] = arrayArg;
336 } else {
337 if (args.size() != expectedParameterTypes.length) {
338 continue;
339 }
340 for (int i=0; i<args.size(); ++i) {
341 convertedArgs[i] = Cascade.convertTo(args.get(i).evaluate(env), expectedParameterTypes[i]);
342 if (convertedArgs[i] == null)
343 return null;
344 }
345 }
346 Object result = null;
347 try {
348 result = m.invoke(fn, convertedArgs);
349 } catch (IllegalAccessException ex) {
350 throw new RuntimeException(ex);
351 } catch (IllegalArgumentException ex) {
352 throw new RuntimeException(ex);
353 } catch (InvocationTargetException ex) {
354 System.err.println(ex);
355 return null;
356 }
357 return result;
358 }
359 return null;
360 }
361
362 @Override
363 public String toString() {
364 return name + "(" + Utils.join(", ", args) + ")";
365 }
366
367 }
368}
Note: See TracBrowser for help on using the repository browser.