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

Last change on this file since 18211 was 18211, checked in by Don-vip, 3 years ago

global use of !Utils.isEmpty/isBlank

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