source: josm/trunk/src/org/openstreetmap/josm/tools/template_engine/ContextSwitchTemplate.java@ 15343

Last change on this file since 15343 was 14093, checked in by Don-vip, 6 years ago

drop unitils library. It was only added to avoid implementing hashCode/equals in template engine and search classes

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools.template_engine;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.List;
10
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.RelationMember;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.osm.search.SearchCompiler.And;
17import org.openstreetmap.josm.data.osm.search.SearchCompiler.Child;
18import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
19import org.openstreetmap.josm.data.osm.search.SearchCompiler.Not;
20import org.openstreetmap.josm.data.osm.search.SearchCompiler.Or;
21import org.openstreetmap.josm.data.osm.search.SearchCompiler.Parent;
22
23/**
24 * The context switch offers possibility to use tags of referenced primitive when constructing primitive name.
25 * @author jttt
26 * @since 4546
27 */
28public class ContextSwitchTemplate implements TemplateEntry {
29
30 private static final TemplateEngineDataProvider EMPTY_PROVIDER = new TemplateEngineDataProvider() {
31 @Override
32 public Object getTemplateValue(String name, boolean special) {
33 return null;
34 }
35
36 @Override
37 public Collection<String> getTemplateKeys() {
38 return Collections.emptyList();
39 }
40
41 @Override
42 public boolean evaluateCondition(Match condition) {
43 return false;
44 }
45 };
46
47 private abstract static class ContextProvider extends Match {
48 protected Match condition;
49
50 abstract List<OsmPrimitive> getPrimitives(OsmPrimitive root);
51
52 @Override
53 public int hashCode() {
54 return 31 + ((condition == null) ? 0 : condition.hashCode());
55 }
56
57 @Override
58 public boolean equals(Object obj) {
59 if (this == obj)
60 return true;
61 if (obj == null || getClass() != obj.getClass())
62 return false;
63 ContextProvider other = (ContextProvider) obj;
64 if (condition == null) {
65 if (other.condition != null)
66 return false;
67 } else if (!condition.equals(other.condition))
68 return false;
69 return true;
70 }
71 }
72
73 private static class ParentSet extends ContextProvider {
74 private final Match childCondition;
75
76 ParentSet(Match child) {
77 this.childCondition = child;
78 }
79
80 @Override
81 public boolean match(OsmPrimitive osm) {
82 throw new UnsupportedOperationException();
83 }
84
85 @Override
86 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
87 List<OsmPrimitive> children;
88 if (childCondition instanceof ContextProvider) {
89 children = ((ContextProvider) childCondition).getPrimitives(root);
90 } else if (childCondition.match(root)) {
91 children = Collections.singletonList(root);
92 } else {
93 children = Collections.emptyList();
94 }
95
96 List<OsmPrimitive> result = new ArrayList<>();
97 for (OsmPrimitive child: children) {
98 for (OsmPrimitive parent: child.getReferrers(true)) {
99 if (condition == null || condition.match(parent)) {
100 result.add(parent);
101 }
102 }
103 }
104 return result;
105 }
106
107 @Override
108 public int hashCode() {
109 return 31 * super.hashCode() + ((childCondition == null) ? 0 : childCondition.hashCode());
110 }
111
112 @Override
113 public boolean equals(Object obj) {
114 if (this == obj)
115 return true;
116 if (!super.equals(obj) || getClass() != obj.getClass())
117 return false;
118 ParentSet other = (ParentSet) obj;
119 if (childCondition == null) {
120 if (other.childCondition != null)
121 return false;
122 } else if (!childCondition.equals(other.childCondition))
123 return false;
124 return true;
125 }
126 }
127
128 private static class ChildSet extends ContextProvider {
129 private final Match parentCondition;
130
131 ChildSet(Match parentCondition) {
132 this.parentCondition = parentCondition;
133 }
134
135 @Override
136 public boolean match(OsmPrimitive osm) {
137 throw new UnsupportedOperationException();
138 }
139
140 @Override
141 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
142 List<OsmPrimitive> parents;
143 if (parentCondition instanceof ContextProvider) {
144 parents = ((ContextProvider) parentCondition).getPrimitives(root);
145 } else if (parentCondition.match(root)) {
146 parents = Collections.singletonList(root);
147 } else {
148 parents = Collections.emptyList();
149 }
150 List<OsmPrimitive> result = new ArrayList<>();
151 for (OsmPrimitive p: parents) {
152 if (p instanceof Way) {
153 for (Node n: ((Way) p).getNodes()) {
154 if (condition != null && condition.match(n)) {
155 result.add(n);
156 }
157 result.add(n);
158 }
159 } else if (p instanceof Relation) {
160 for (RelationMember rm: ((Relation) p).getMembers()) {
161 if (condition != null && condition.match(rm.getMember())) {
162 result.add(rm.getMember());
163 }
164 }
165 }
166 }
167 return result;
168 }
169
170 @Override
171 public int hashCode() {
172 return 31 * super.hashCode() + ((parentCondition == null) ? 0 : parentCondition.hashCode());
173 }
174
175 @Override
176 public boolean equals(Object obj) {
177 if (this == obj)
178 return true;
179 if (!super.equals(obj) || getClass() != obj.getClass())
180 return false;
181 ChildSet other = (ChildSet) obj;
182 if (parentCondition == null) {
183 if (other.parentCondition != null)
184 return false;
185 } else if (!parentCondition.equals(other.parentCondition))
186 return false;
187 return true;
188 }
189 }
190
191 private static class OrSet extends ContextProvider {
192 private final ContextProvider lhs;
193 private final ContextProvider rhs;
194
195 OrSet(ContextProvider lhs, ContextProvider rhs) {
196 this.lhs = lhs;
197 this.rhs = rhs;
198 }
199
200 @Override
201 public boolean match(OsmPrimitive osm) {
202 throw new UnsupportedOperationException();
203 }
204
205 @Override
206 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
207 List<OsmPrimitive> result = new ArrayList<>();
208 for (OsmPrimitive o: lhs.getPrimitives(root)) {
209 if (condition == null || condition.match(o)) {
210 result.add(o);
211 }
212 }
213 for (OsmPrimitive o: rhs.getPrimitives(root)) {
214 if (condition == null || (condition.match(o) && !result.contains(o))) {
215 result.add(o);
216 }
217 }
218 return result;
219 }
220
221 @Override
222 public int hashCode() {
223 final int prime = 31;
224 int result = super.hashCode();
225 result = prime * result + ((lhs == null) ? 0 : lhs.hashCode());
226 result = prime * result + ((rhs == null) ? 0 : rhs.hashCode());
227 return result;
228 }
229
230 @Override
231 public boolean equals(Object obj) {
232 if (this == obj)
233 return true;
234 if (!super.equals(obj) || getClass() != obj.getClass())
235 return false;
236 OrSet other = (OrSet) obj;
237 if (lhs == null) {
238 if (other.lhs != null)
239 return false;
240 } else if (!lhs.equals(other.lhs))
241 return false;
242 if (rhs == null) {
243 if (other.rhs != null)
244 return false;
245 } else if (!rhs.equals(other.rhs))
246 return false;
247 return true;
248 }
249 }
250
251 private static class AndSet extends ContextProvider {
252 private final ContextProvider lhs;
253 private final ContextProvider rhs;
254
255 AndSet(ContextProvider lhs, ContextProvider rhs) {
256 this.lhs = lhs;
257 this.rhs = rhs;
258 }
259
260 @Override
261 public boolean match(OsmPrimitive osm) {
262 throw new UnsupportedOperationException();
263 }
264
265 @Override
266 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
267 List<OsmPrimitive> result = new ArrayList<>();
268 List<OsmPrimitive> lhsList = lhs.getPrimitives(root);
269 for (OsmPrimitive o: rhs.getPrimitives(root)) {
270 if (lhsList.contains(o) && (condition == null || condition.match(o))) {
271 result.add(o);
272 }
273 }
274 return result;
275 }
276
277 @Override
278 public int hashCode() {
279 final int prime = 31;
280 int result = super.hashCode();
281 result = prime * result + ((lhs == null) ? 0 : lhs.hashCode());
282 result = prime * result + ((rhs == null) ? 0 : rhs.hashCode());
283 return result;
284 }
285
286 @Override
287 public boolean equals(Object obj) {
288 if (this == obj)
289 return true;
290 if (!super.equals(obj) || getClass() != obj.getClass())
291 return false;
292 AndSet other = (AndSet) obj;
293 if (lhs == null) {
294 if (other.lhs != null)
295 return false;
296 } else if (!lhs.equals(other.lhs))
297 return false;
298 if (rhs == null) {
299 if (other.rhs != null)
300 return false;
301 } else if (!rhs.equals(other.rhs))
302 return false;
303 return true;
304 }
305 }
306
307 private final ContextProvider context;
308 private final TemplateEntry template;
309
310 private static Match transform(Match m, int searchExpressionPosition) throws ParseError {
311 if (m instanceof Parent) {
312 Match child = transform(((Parent) m).getOperand(), searchExpressionPosition);
313 return new ParentSet(child);
314 } else if (m instanceof Child) {
315 Match parent = transform(((Child) m).getOperand(), searchExpressionPosition);
316 return new ChildSet(parent);
317 } else if (m instanceof And) {
318 Match lhs = transform(((And) m).getLhs(), searchExpressionPosition);
319 Match rhs = transform(((And) m).getRhs(), searchExpressionPosition);
320
321 if (lhs instanceof ContextProvider && rhs instanceof ContextProvider)
322 return new AndSet((ContextProvider) lhs, (ContextProvider) rhs);
323 else if (lhs instanceof ContextProvider) {
324 ContextProvider cp = (ContextProvider) lhs;
325 if (cp.condition == null) {
326 cp.condition = rhs;
327 } else {
328 cp.condition = new And(cp.condition, rhs);
329 }
330 return cp;
331 } else if (rhs instanceof ContextProvider) {
332 ContextProvider cp = (ContextProvider) rhs;
333 if (cp.condition == null) {
334 cp.condition = lhs;
335 } else {
336 cp.condition = new And(lhs, cp.condition);
337 }
338 return cp;
339 } else
340 return m;
341 } else if (m instanceof Or) {
342 Match lhs = transform(((Or) m).getLhs(), searchExpressionPosition);
343 Match rhs = transform(((Or) m).getRhs(), searchExpressionPosition);
344
345 if (lhs instanceof ContextProvider && rhs instanceof ContextProvider)
346 return new OrSet((ContextProvider) lhs, (ContextProvider) rhs);
347 else if (lhs instanceof ContextProvider)
348 throw new ParseError(
349 tr("Error in search expression on position {0} - right side of or(|) expression must return set of primitives",
350 searchExpressionPosition));
351 else if (rhs instanceof ContextProvider)
352 throw new ParseError(
353 tr("Error in search expression on position {0} - left side of or(|) expression must return set of primitives",
354 searchExpressionPosition));
355 else
356 return m;
357 } else if (m instanceof Not) {
358 Match match = transform(((Not) m).getMatch(), searchExpressionPosition);
359 if (match instanceof ContextProvider)
360 throw new ParseError(
361 tr("Error in search expression on position {0} - not(-) cannot be used in this context",
362 searchExpressionPosition));
363 else
364 return m;
365 } else
366 return m;
367 }
368
369 /**
370 * Constructs a new {@code ContextSwitchTemplate}.
371 * @param match match
372 * @param template template
373 * @param searchExpressionPosition search expression position
374 * @throws ParseError if a parse error occurs, or if the match transformation returns the same primitive
375 */
376 public ContextSwitchTemplate(Match match, TemplateEntry template, int searchExpressionPosition) throws ParseError {
377 Match m = transform(match, searchExpressionPosition);
378 if (!(m instanceof ContextProvider))
379 throw new ParseError(
380 tr("Error in search expression on position {0} - expression must return different then current primitive",
381 searchExpressionPosition));
382 else {
383 context = (ContextProvider) m;
384 }
385 this.template = template;
386 }
387
388 @Override
389 public void appendText(StringBuilder result, TemplateEngineDataProvider dataProvider) {
390 if (dataProvider instanceof OsmPrimitive) {
391 List<OsmPrimitive> primitives = context.getPrimitives((OsmPrimitive) dataProvider);
392 if (primitives != null && !primitives.isEmpty()) {
393 template.appendText(result, primitives.get(0));
394 }
395 }
396 template.appendText(result, EMPTY_PROVIDER);
397 }
398
399 @Override
400 public boolean isValid(TemplateEngineDataProvider dataProvider) {
401 if (dataProvider instanceof OsmPrimitive) {
402 List<OsmPrimitive> primitives = context.getPrimitives((OsmPrimitive) dataProvider);
403 if (primitives != null && !primitives.isEmpty()) {
404 return template.isValid(primitives.get(0));
405 }
406 }
407 return false;
408 }
409
410 @Override
411 public int hashCode() {
412 final int prime = 31;
413 int result = 1;
414 result = prime * result + ((context == null) ? 0 : context.hashCode());
415 result = prime * result + ((template == null) ? 0 : template.hashCode());
416 return result;
417 }
418
419 @Override
420 public boolean equals(Object obj) {
421 if (this == obj)
422 return true;
423 if (obj == null || getClass() != obj.getClass())
424 return false;
425 ContextSwitchTemplate other = (ContextSwitchTemplate) obj;
426 if (context == null) {
427 if (other.context != null)
428 return false;
429 } else if (!context.equals(other.context))
430 return false;
431 if (template == null) {
432 if (other.template != null)
433 return false;
434 } else if (!template.equals(other.template))
435 return false;
436 return true;
437 }
438}
Note: See TracBrowser for help on using the repository browser.