source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerIndex.java@ 15988

Last change on this file since 15988 was 15988, checked in by simon04, 4 years ago

see #18802 - MapCSSRule: support list of selectors

  • allows to drop MapCSSTagChecker.GroupedMapCSSRule
  • remove code duplication in MapCSSStyleSource/MapCSSTagCheckerIndex w.r.t. MapCSSRuleIndex
File size: 7.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7import java.util.Collection;
8import java.util.HashMap;
9import java.util.Iterator;
10import java.util.Map;
11import java.util.stream.Collectors;
12import java.util.stream.Stream;
13
14import org.openstreetmap.josm.data.osm.INode;
15import org.openstreetmap.josm.data.osm.IPrimitive;
16import org.openstreetmap.josm.data.osm.IRelation;
17import org.openstreetmap.josm.data.osm.IWay;
18import org.openstreetmap.josm.data.osm.OsmUtils;
19import org.openstreetmap.josm.data.validation.Severity;
20import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker.TagCheck;
21import org.openstreetmap.josm.gui.mappaint.mapcss.Declaration;
22import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
23import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource.MapCSSRuleIndex;
24import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
25import org.openstreetmap.josm.tools.JosmRuntimeException;
26import org.openstreetmap.josm.tools.Logging;
27import org.openstreetmap.josm.tools.MultiMap;
28
29/**
30 * Helper class for {@link MapCSSTagChecker} to store indexes of rules
31 * @author Gerd
32 *
33 */
34public final class MapCSSTagCheckerIndex {
35 final Map<Declaration, TagCheck> ruleToCheckMap = new HashMap<>();
36
37 static final boolean ALL_TESTS = true;
38 static final boolean ONLY_SELECTED_TESTS = false;
39
40 /**
41 * Rules for nodes
42 */
43 final MapCSSRuleIndex nodeRules = new MapCSSRuleIndex();
44 /**
45 * Rules for ways without tag area=no
46 */
47 final MapCSSRuleIndex wayRules = new MapCSSRuleIndex();
48 /**
49 * Rules for ways with tag area=no
50 */
51 final MapCSSRuleIndex wayNoAreaRules = new MapCSSRuleIndex();
52 /**
53 * Rules for relations that are not multipolygon relations
54 */
55 final MapCSSRuleIndex relationRules = new MapCSSRuleIndex();
56 /**
57 * Rules for multipolygon relations
58 */
59 final MapCSSRuleIndex multipolygonRules = new MapCSSRuleIndex();
60 /**
61 * rules to apply canvas properties
62 */
63 final MapCSSRuleIndex canvasRules = new MapCSSRuleIndex();
64
65 static MapCSSTagCheckerIndex createMapCSSTagCheckerIndex(MultiMap<String, TagCheck> checks, boolean includeOtherSeverity, boolean allTests) {
66 final MapCSSTagCheckerIndex index = new MapCSSTagCheckerIndex();
67 final Stream<MapCSSRule> ruleStream = checks.values().stream()
68 .flatMap(Collection::stream)
69 // Ignore "information" level checks if not wanted, unless they also set a MapCSS class
70 .filter(c -> includeOtherSeverity || Severity.OTHER != c.getSeverity() || !c.setClassExpressions.isEmpty())
71 .filter(c -> allTests || c.rule.selectors.stream().anyMatch(Selector.ChildOrParentSelector.class::isInstance))
72 .peek(c -> index.ruleToCheckMap.put(c.rule.declaration, c))
73 .map(c -> c.rule);
74 index.buildIndex(ruleStream);
75 return index;
76 }
77
78 /**
79 * Clear the index.
80 * <p>
81 * You must own the write lock STYLE_SOURCE_LOCK when calling this method.
82 */
83 public void clear() {
84 ruleToCheckMap.clear();
85 nodeRules.clear();
86 wayRules.clear();
87 wayNoAreaRules.clear();
88 relationRules.clear();
89 multipolygonRules.clear();
90 canvasRules.clear();
91 }
92
93 /**
94 * Builds and initializes the index.
95 * <p>
96 * You must own the write lock of STYLE_SOURCE_LOCK when calling this method.
97 */
98 public void buildIndex(Stream<MapCSSRule> ruleStream) {
99 clear();
100 // optimization: filter rules for different primitive types
101 ruleStream.forEach(rule -> {
102 final Map<String, MapCSSRule> selectorsByBase = rule.selectors.stream()
103 .collect(Collectors.groupingBy(Selector::getBase,
104 Collectors.collectingAndThen(Collectors.toList(), selectors -> new MapCSSRule(selectors, rule.declaration))));
105 selectorsByBase.forEach((base, optRule) -> {
106 switch (base) {
107 case Selector.BASE_NODE:
108 nodeRules.add(optRule);
109 break;
110 case Selector.BASE_WAY:
111 wayNoAreaRules.add(optRule);
112 wayRules.add(optRule);
113 break;
114 case Selector.BASE_AREA:
115 wayRules.add(optRule);
116 multipolygonRules.add(optRule);
117 break;
118 case Selector.BASE_RELATION:
119 relationRules.add(optRule);
120 multipolygonRules.add(optRule);
121 break;
122 case Selector.BASE_ANY:
123 nodeRules.add(optRule);
124 wayRules.add(optRule);
125 wayNoAreaRules.add(optRule);
126 relationRules.add(optRule);
127 multipolygonRules.add(optRule);
128 break;
129 case Selector.BASE_CANVAS:
130 canvasRules.add(optRule);
131 break;
132 case Selector.BASE_META:
133 case Selector.BASE_SETTING:
134 case Selector.BASE_SETTINGS:
135 break;
136 default:
137 final RuntimeException e = new JosmRuntimeException(MessageFormat.format("Unknown MapCSS base selector {0}", base));
138 Logging.warn(tr("Failed to index validator rules. Error was: {0}", e.getMessage()));
139 Logging.error(e);
140 }
141 });
142 });
143 initIndex();
144 }
145
146 private void initIndex() {
147 nodeRules.initIndex();
148 wayRules.initIndex();
149 wayNoAreaRules.initIndex();
150 relationRules.initIndex();
151 multipolygonRules.initIndex();
152 canvasRules.initIndex();
153 }
154
155 /**
156 * Get the index of rules for the given primitive.
157 * @param p the primitive
158 * @return index of rules for the given primitive
159 */
160 public MapCSSRuleIndex get(IPrimitive p) {
161 if (p instanceof INode) {
162 return nodeRules;
163 } else if (p instanceof IWay) {
164 if (OsmUtils.isFalse(p.get("area"))) {
165 return wayNoAreaRules;
166 } else {
167 return wayRules;
168 }
169 } else if (p instanceof IRelation) {
170 if (((IRelation<?>) p).isMultipolygon()) {
171 return multipolygonRules;
172 } else if (p.hasKey("#canvas")) {
173 return canvasRules;
174 } else {
175 return relationRules;
176 }
177 } else {
178 throw new IllegalArgumentException("Unsupported type: " + p);
179 }
180 }
181
182 /**
183 * Get a subset of all rules that might match the primitive. Rules not included in the result are guaranteed to
184 * not match this primitive.
185 * <p>
186 * You must have a read lock of STYLE_SOURCE_LOCK when calling this method.
187 *
188 * @param osm the primitive to match
189 * @return An iterator over possible rules in the right order.
190 */
191 public Iterator<MapCSSRule> getRuleCandidates(IPrimitive osm) {
192 return get(osm).getRuleCandidates(osm);
193 }
194
195 /**
196 * return the TagCheck for which the given indexed rule was created.
197 * @param rule an indexed rule
198 * @return the original TagCheck
199 */
200 public TagCheck getCheck(MapCSSRule rule) {
201 return ruleToCheckMap.get(rule.declaration);
202 }
203}
Note: See TracBrowser for help on using the repository browser.