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

Last change on this file since 4724 was 4724, checked in by jttt, 12 years ago

Fix some of errors found by FindBugs

File size: 10.1 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.actions.search.SearchCompiler.And;
12import org.openstreetmap.josm.actions.search.SearchCompiler.Child;
13import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
14import org.openstreetmap.josm.actions.search.SearchCompiler.Not;
15import org.openstreetmap.josm.actions.search.SearchCompiler.Or;
16import org.openstreetmap.josm.actions.search.SearchCompiler.Parent;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Relation;
20import org.openstreetmap.josm.data.osm.RelationMember;
21import org.openstreetmap.josm.data.osm.Way;
22
23public class ContextSwitchTemplate implements TemplateEntry {
24
25 private static final TemplateEngineDataProvider EMTPY_PROVIDER = new TemplateEngineDataProvider() {
26 @Override
27 public Object getTemplateValue(String name, boolean special) {
28 return null;
29 }
30
31 @Override
32 public Collection<String> getTemplateKeys() {
33 return Collections.emptyList();
34 }
35
36 @Override
37 public boolean evaluateCondition(Match condition) {
38 return false;
39 }
40 };
41
42 private abstract class ContextProvider extends Match {
43 Match condition;
44 abstract List<OsmPrimitive> getPrimitives(OsmPrimitive root);
45 }
46
47 private class ParentSet extends ContextProvider {
48 private final Match childCondition;
49
50 ParentSet(Match child) {
51 this.childCondition = child;
52 }
53 @Override
54 public boolean match(OsmPrimitive osm) {
55 throw new UnsupportedOperationException();
56 }
57 @Override
58 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
59 List<OsmPrimitive> children;
60 if (childCondition instanceof ContextProvider) {
61 children = ((ContextProvider) childCondition).getPrimitives(root);
62 } else if (childCondition.match(root)) {
63 children = Collections.singletonList(root);
64 } else {
65 children = Collections.emptyList();
66 }
67
68 List<OsmPrimitive> result = new ArrayList<OsmPrimitive>();
69 for (OsmPrimitive child: children) {
70 for (OsmPrimitive parent: child.getReferrers()) {
71 if (condition == null || condition.match(parent)) {
72 result.add(parent);
73 }
74 }
75 }
76 return result;
77 }
78 }
79
80 private class ChildSet extends ContextProvider {
81 private final Match parentCondition;
82
83 ChildSet(Match parentCondition) {
84 this.parentCondition = parentCondition;
85 }
86
87 @Override
88 public boolean match(OsmPrimitive osm) {
89 throw new UnsupportedOperationException();
90 }
91
92 @Override
93 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
94 List<OsmPrimitive> parents;
95 if (parentCondition instanceof ContextProvider) {
96 parents = ((ContextProvider) parentCondition).getPrimitives(root);
97 } else if (parentCondition.match(root)) {
98 parents = Collections.singletonList(root);
99 } else {
100 parents = Collections.emptyList();
101 }
102 List<OsmPrimitive> result = new ArrayList<OsmPrimitive>();
103 for (OsmPrimitive p: parents) {
104 if (p instanceof Way) {
105 for (Node n: ((Way) p).getNodes()) {
106 if (condition != null && condition.match(n)) {
107 result.add(n);
108 }
109 result.add(n);
110 }
111 } else if (p instanceof Relation) {
112 for (RelationMember rm: ((Relation) p).getMembers()) {
113 if (condition != null && condition.match(rm.getMember())) {
114 result.add(rm.getMember());
115 }
116 }
117 }
118 }
119 return result;
120 }
121 }
122
123 private class OrSet extends ContextProvider {
124 private final ContextProvider lhs;
125 private final ContextProvider rhs;
126
127 OrSet(ContextProvider lhs, ContextProvider rhs) {
128 this.lhs = lhs;
129 this.rhs = rhs;
130 }
131
132 @Override
133 public boolean match(OsmPrimitive osm) {
134 throw new UnsupportedOperationException();
135 }
136
137 @Override
138 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
139 List<OsmPrimitive> result = new ArrayList<OsmPrimitive>();
140 for (OsmPrimitive o: lhs.getPrimitives(root)) {
141 if (condition == null || condition.match(o)) {
142 result.add(o);
143 }
144 }
145 for (OsmPrimitive o: rhs.getPrimitives(root)) {
146 if (condition == null || condition.match(o) && !result.contains(o)) {
147 result.add(o);
148 }
149 }
150 return result;
151 }
152 }
153
154 private class AndSet extends ContextProvider {
155 private final ContextProvider lhs;
156 private final ContextProvider rhs;
157
158 AndSet(ContextProvider lhs, ContextProvider rhs) {
159 this.lhs = lhs;
160 this.rhs = rhs;
161 }
162
163 @Override
164 public boolean match(OsmPrimitive osm) {
165 throw new UnsupportedOperationException();
166 }
167
168 @Override
169 List<OsmPrimitive> getPrimitives(OsmPrimitive root) {
170 List<OsmPrimitive> result = new ArrayList<OsmPrimitive>();
171 List<OsmPrimitive> lhsList = lhs.getPrimitives(root);
172 for (OsmPrimitive o: rhs.getPrimitives(root)) {
173 if (lhsList.contains(o) && (condition == null || condition.match(o))) {
174 result.add(o);
175 }
176 }
177 return result;
178 }
179 }
180
181 private final ContextProvider context;
182 private final TemplateEntry template;
183
184 private Match transform(Match m, int searchExpressionPosition) throws ParseError {
185 if (m instanceof Parent) {
186 Match child = transform(((Parent) m).getChild(), searchExpressionPosition);
187 return new ParentSet(child);
188 } else if (m instanceof Child) {
189 Match parent = transform(((Child) m).getParent(), searchExpressionPosition);
190 return new ChildSet(parent);
191 } else if (m instanceof And) {
192 Match lhs = transform(((And) m).getLhs(), searchExpressionPosition);
193 Match rhs = transform(((And) m).getRhs(), searchExpressionPosition);
194
195 if (lhs instanceof ContextProvider && rhs instanceof ContextProvider)
196 return new AndSet((ContextProvider)lhs, (ContextProvider)rhs);
197 else if (lhs instanceof ContextProvider) {
198 ContextProvider cp = (ContextProvider) lhs;
199 if (cp.condition == null) {
200 cp.condition = rhs;
201 } else {
202 cp.condition = new And(cp.condition, rhs);
203 }
204 return cp;
205 } else if (rhs instanceof ContextProvider) {
206 ContextProvider cp = (ContextProvider) rhs;
207 if (cp.condition == null) {
208 cp.condition = lhs;
209 } else {
210 cp.condition = new And(lhs, cp.condition);
211 }
212 return cp;
213 } else
214 return m;
215 } else if (m instanceof Or) {
216 Match lhs = transform(((Or) m).getLhs(), searchExpressionPosition);
217 Match rhs = transform(((Or) m).getRhs(), searchExpressionPosition);
218
219 if (lhs instanceof ContextProvider && rhs instanceof ContextProvider)
220 return new OrSet((ContextProvider)lhs, (ContextProvider)rhs);
221 else if (lhs instanceof ContextProvider)
222 throw new ParseError(tr("Error in search expression on position {0} - right side of or(|) expression must return set of primitives", searchExpressionPosition));
223 else if (rhs instanceof ContextProvider)
224 throw new ParseError(tr("Error in search expression on position {0} - left side of or(|) expression must return set of primitives", searchExpressionPosition));
225 else
226 return m;
227 } else if (m instanceof Not) {
228 Match match = transform(((Not) m).getMatch(), searchExpressionPosition);
229 if (match instanceof ContextProvider)
230 throw new ParseError(tr("Error in search expression on position {0} - not(-) cannot be used in this context", searchExpressionPosition));
231 else
232 return m;
233 } else
234 return m;
235 }
236
237 public ContextSwitchTemplate(Match match, TemplateEntry template, int searchExpressionPosition) throws ParseError {
238 Match m = transform(match, searchExpressionPosition);
239 if (!(m instanceof ContextProvider))
240 throw new ParseError(tr("Error in search expression on position {0} - expression must return different then current primitive", searchExpressionPosition));
241 else {
242 context = (ContextProvider) m;
243 }
244 this.template = template;
245 }
246
247 @Override
248 public void appendText(StringBuilder result, TemplateEngineDataProvider dataProvider) {
249 List<OsmPrimitive> primitives = context.getPrimitives((OsmPrimitive) dataProvider);
250 if (primitives != null && !primitives.isEmpty()) {
251 template.appendText(result, primitives.get(0));
252 } else {
253 template.appendText(result, EMTPY_PROVIDER);
254 }
255 }
256
257 @Override
258 public boolean isValid(TemplateEngineDataProvider dataProvider) {
259 List<OsmPrimitive> primitives = context.getPrimitives((OsmPrimitive) dataProvider);
260 if (primitives != null && !primitives.isEmpty())
261 return template.isValid(primitives.get(0));
262 else
263 return false;
264 }
265
266}
Note: See TracBrowser for help on using the repository browser.