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

Last change on this file since 10659 was 10659, checked in by Don-vip, 15 months ago

see #12472 - fix more warnings, increase maximum number of reported warnings from 100 to 1000

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