Changeset 15988 in josm
- Timestamp:
- 2020-03-01T23:36:07+01:00 (5 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/scripts/TagInfoExtract.java
r15985 r15988 342 342 private List<TagInfoTag> convertStyleSheet() { 343 343 return styleSource.rules.stream() 344 .flatMap(rule -> rule.selector.getConditions().stream()) 344 .flatMap(rule -> rule.selectors.stream()) 345 .flatMap(selector -> selector.getConditions().stream()) 345 346 .filter(ConditionFactory.SimpleKeyValueCondition.class::isInstance) 346 347 .map(ConditionFactory.SimpleKeyValueCondition.class::cast) -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
r15987 r15988 15 15 import java.util.HashSet; 16 16 import java.util.Iterator; 17 import java.util.LinkedHashMap;18 17 import java.util.LinkedList; 19 18 import java.util.List; … … 26 25 import java.util.regex.Matcher; 27 26 import java.util.regex.Pattern; 27 import java.util.stream.Stream; 28 28 29 29 import org.openstreetmap.josm.command.ChangePropertyCommand; … … 47 47 import org.openstreetmap.josm.gui.mappaint.MultiCascade; 48 48 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition; 49 import org.openstreetmap.josm.gui.mappaint.mapcss.Declaration;50 49 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression; 51 50 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction; 52 51 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule; 53 52 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource; 54 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource.MapCSSRuleIndex;55 53 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 56 54 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector; … … 76 74 public class MapCSSTagChecker extends Test.TagTest { 77 75 private MapCSSTagCheckerIndex indexData; 76 final Map<MapCSSRule, MapCSSTagCheckerAndRule> ruleToCheckMap = new HashMap<>(); 78 77 private final Set<OsmPrimitive> tested = new HashSet<>(); 79 78 private static final Map<IPrimitive, Area> mpAreaCache = new HashMap<>(); 80 81 /**82 * A grouped MapCSSRule with multiple selectors for a single declaration.83 * @see MapCSSRule84 */85 public static class GroupedMapCSSRule {86 /** MapCSS selectors **/87 public final List<Selector> selectors;88 /** MapCSS declaration **/89 public final Declaration declaration;90 /** MapCSS source **/91 public final String source;92 93 /**94 * Constructs a new {@code GroupedMapCSSRule} with empty source95 * @param selectors MapCSS selectors96 * @param declaration MapCSS declaration97 */98 public GroupedMapCSSRule(List<Selector> selectors, Declaration declaration) {99 this(selectors, declaration, "");100 }101 102 /**103 * Constructs a new {@code GroupedMapCSSRule}.104 * @param selectors MapCSS selectors105 * @param declaration MapCSS declaration106 * @param source the source of the rule107 */108 public GroupedMapCSSRule(List<Selector> selectors, Declaration declaration, String source) {109 this.selectors = selectors;110 this.declaration = declaration;111 this.source = source;112 }113 114 @Override115 public int hashCode() {116 return Objects.hash(selectors, declaration);117 }118 119 @Override120 public boolean equals(Object obj) {121 if (this == obj) return true;122 if (obj == null || getClass() != obj.getClass()) return false;123 GroupedMapCSSRule that = (GroupedMapCSSRule) obj;124 return Objects.equals(selectors, that.selectors) &&125 Objects.equals(declaration, that.declaration);126 }127 128 @Override129 public String toString() {130 return "GroupedMapCSSRule [selectors=" + selectors + ", declaration=" + declaration + ']';131 }132 }133 79 134 80 /** … … 281 227 public static class TagCheck implements Predicate<OsmPrimitive> { 282 228 /** The selector of this {@code TagCheck} */ 283 protected final GroupedMapCSSRule rule;229 protected final MapCSSRule rule; 284 230 /** Commands to apply in order to fix a matching primitive */ 285 231 protected final List<FixCommand> fixCommands; … … 296 242 protected String group; 297 243 298 TagCheck( GroupedMapCSSRule rule) {244 TagCheck(MapCSSRule rule) { 299 245 this.rule = rule; 300 246 this.fixCommands = new ArrayList<>(); … … 320 266 private static final String POSSIBLE_THROWS = "throwError/throwWarning/throwOther"; 321 267 322 static TagCheck ofMapCSSRule(final GroupedMapCSSRule rule, AssertionConsumer assertionConsumer) throws IllegalDataException {268 static TagCheck ofMapCSSRule(final MapCSSRule rule, AssertionConsumer assertionConsumer) throws IllegalDataException { 323 269 final TagCheck check = new TagCheck(rule); 324 270 final Map<String, Boolean> assertions = new HashMap<>(); … … 394 340 395 341 static ParseResult readMapCSS(Reader css) throws ParseException { 396 return readMapCSS(css, "",null);397 } 398 399 static ParseResult readMapCSS(Reader css, String url,AssertionConsumer assertionConsumer) throws ParseException {342 return readMapCSS(css, null); 343 } 344 345 static ParseResult readMapCSS(Reader css, AssertionConsumer assertionConsumer) throws ParseException { 400 346 CheckParameterUtil.ensureParameterNotNull(css, "css"); 401 347 … … 407 353 // Ignore "meta" rule(s) from external rules of JOSM wiki 408 354 source.removeMetaRules(); 409 // group rules with common declaration block 410 Map<Declaration, List<Selector>> g = new LinkedHashMap<>(); 355 List<TagCheck> parseChecks = new ArrayList<>(); 411 356 for (MapCSSRule rule : source.rules) { 412 if (!g.containsKey(rule.declaration)) {413 List<Selector> sels = new ArrayList<>();414 sels.add(rule.selector);415 g.put(rule.declaration, sels);416 } else {417 g.get(rule.declaration).add(rule.selector);418 }419 }420 List<TagCheck> parseChecks = new ArrayList<>();421 for (Map.Entry<Declaration, List<Selector>> map : g.entrySet()) {422 357 try { 423 parseChecks.add(TagCheck.ofMapCSSRule( 424 new GroupedMapCSSRule(map.getValue(), map.getKey(), url), assertionConsumer)); 358 parseChecks.add(TagCheck.ofMapCSSRule(rule, assertionConsumer)); 425 359 } catch (IllegalDataException e) { 426 360 Logging.error("Cannot add MapCss rule: "+e.getMessage()); … … 661 595 662 596 static class MapCSSTagCheckerAndRule extends MapCSSTagChecker { 663 public final GroupedMapCSSRule rule; 664 665 MapCSSTagCheckerAndRule(GroupedMapCSSRule rule) { 597 public final MapCSSRule rule; 598 private final TagCheck tagCheck; 599 private final String source; 600 601 MapCSSTagCheckerAndRule(MapCSSRule rule) { 666 602 this.rule = rule; 603 this.tagCheck = null; 604 this.source = ""; 605 } 606 607 MapCSSTagCheckerAndRule(TagCheck tagCheck, String source) { 608 this.rule = tagCheck.rule; 609 this.tagCheck = tagCheck; 610 this.source = source; 667 611 } 668 612 … … 674 618 @Override 675 619 public String getSource() { 676 return tr("URL / File: {0}", rule.source); 677 } 620 return tr("URL / File: {0}", source); 621 } 622 } 623 624 static MapCSSTagCheckerIndex createMapCSSTagCheckerIndex(MultiMap<String, TagCheck> checks, boolean includeOtherSeverity, boolean allTests) { 625 final MapCSSTagCheckerIndex index = new MapCSSTagCheckerIndex(); 626 final Stream<MapCSSRule> ruleStream = checks.values().stream() 627 .flatMap(Collection::stream) 628 // Ignore "information" level checks if not wanted, unless they also set a MapCSS class 629 .filter(c -> includeOtherSeverity || Severity.OTHER != c.getSeverity() || !c.setClassExpressions.isEmpty()) 630 .filter(c -> allTests || c.rule.selectors.stream().anyMatch(Selector.ChildOrParentSelector.class::isInstance)) 631 .map(c -> c.rule); 632 index.buildIndex(ruleStream); 633 return index; 678 634 } 679 635 … … 687 643 final List<TestError> res = new ArrayList<>(); 688 644 if (indexData == null) { 689 indexData = new MapCSSTagCheckerIndex(checks, includeOtherSeverity, MapCSSTagCheckerIndex.ALL_TESTS); 690 } 691 692 MapCSSRuleIndex matchingRuleIndex = indexData.get(p); 645 indexData = MapCSSTagCheckerIndex.createMapCSSTagCheckerIndex(checks, includeOtherSeverity, MapCSSTagCheckerIndex.ALL_TESTS); 646 } 693 647 694 648 Environment env = new Environment(p, new MultiCascade(), Environment.DEFAULT_LAYER, null); 695 649 env.mpAreaCache = mpAreaCache; 696 650 697 // the declaration indices are sorted, so it suffices to save the last used index 698 Declaration lastDeclUsed = null; 699 700 Iterator<MapCSSRule> candidates = matchingRuleIndex.getRuleCandidates(p); 651 Iterator<MapCSSRule> candidates = indexData.getRuleCandidates(p); 701 652 while (candidates.hasNext()) { 702 653 MapCSSRule r = candidates.next(); 703 env.clearSelectorMatchingInformation(); 704 if (r.matches(env)) { // as side effect env.parent will be set (if s is a child selector) 705 TagCheck check = indexData.getCheck(r); 654 for (Selector selector : r.selectors) { 655 env.clearSelectorMatchingInformation(); 656 if (!selector.matches(env)) { // as side effect env.parent will be set (if s is a child selector) 657 continue; 658 } 659 MapCSSTagCheckerAndRule test = ruleToCheckMap.computeIfAbsent(r, rule -> checks.entrySet().stream() 660 .map(e -> e.getValue().stream() 661 // rule.selectors might be different due to MapCSSStyleIndex, however, the declarations are the same object 662 .filter(c -> c.rule.declaration == rule.declaration) 663 .findFirst() 664 .map(c -> new MapCSSTagCheckerAndRule(c, e.getKey())) 665 .orElse(null)) 666 .filter(Objects::nonNull) 667 .findFirst() 668 .orElse(null)); 669 TagCheck check = test == null ? null : test.tagCheck; 706 670 if (check != null) { 707 if (r.declaration == lastDeclUsed)708 continue; // don't apply one declaration more than once709 lastDeclUsed = r.declaration;710 711 671 r.declaration.execute(env); 712 672 if (!check.errors.isEmpty()) { 713 for (TestError e: check.getErrorsForPrimitive(p, r.selector, env, new MapCSSTagCheckerAndRule(check.rule))) {673 for (TestError e: check.getErrorsForPrimitive(p, selector, env, test)) { 714 674 addIfNotSimilar(e, res); 715 675 } … … 831 791 if (zip != null) 832 792 I18n.addTexts(cache.getFile()); 833 result = TagCheck.readMapCSS(reader, url,assertionConsumer);793 result = TagCheck.readMapCSS(reader, assertionConsumer); 834 794 checks.remove(url); 835 795 checks.putAll(url, result.parseChecks); … … 890 850 super.setShowElements(true); 891 851 if (indexData == null) { 892 indexData = newMapCSSTagCheckerIndex(checks, includeOtherSeverityChecks(), MapCSSTagCheckerIndex.ALL_TESTS);852 indexData = MapCSSTagCheckerIndex.createMapCSSTagCheckerIndex(checks, includeOtherSeverityChecks(), MapCSSTagCheckerIndex.ALL_TESTS); 893 853 } 894 854 tested.clear(); … … 904 864 // rebuild index with a reduced set of rules (those that use ChildOrParentSelector) and thus may have left selectors 905 865 // matching the previously tested elements 906 indexData = newMapCSSTagCheckerIndex(checks, includeOtherSeverityChecks(), MapCSSTagCheckerIndex.ONLY_SELECTED_TESTS);866 indexData = MapCSSTagCheckerIndex.createMapCSSTagCheckerIndex(checks, includeOtherSeverityChecks(), MapCSSTagCheckerIndex.ONLY_SELECTED_TESTS); 907 867 908 868 Set<OsmPrimitive> surrounding = new HashSet<>(); -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerIndex.java
r15987 r15988 5 5 6 6 import java.text.MessageFormat; 7 import java.util. ArrayList;7 import java.util.Collection; 8 8 import java.util.HashMap; 9 import java.util. List;9 import java.util.Iterator; 10 10 import java.util.Map; 11 import java.util.Set; 11 import java.util.stream.Collectors; 12 import java.util.stream.Stream; 12 13 13 14 import org.openstreetmap.josm.data.osm.INode; 15 import org.openstreetmap.josm.data.osm.IPrimitive; 14 16 import org.openstreetmap.josm.data.osm.IRelation; 15 17 import org.openstreetmap.josm.data.osm.IWay; 16 import org.openstreetmap.josm.data.osm.OsmPrimitive;17 18 import org.openstreetmap.josm.data.osm.OsmUtils; 18 19 import org.openstreetmap.josm.data.validation.Severity; 19 20 import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker.TagCheck; 21 import org.openstreetmap.josm.gui.mappaint.mapcss.Declaration; 20 22 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule; 21 23 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource.MapCSSRuleIndex; 22 24 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 23 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;24 25 import org.openstreetmap.josm.tools.JosmRuntimeException; 25 26 import org.openstreetmap.josm.tools.Logging; … … 31 32 * 32 33 */ 33 final class MapCSSTagCheckerIndex {34 final Map< MapCSSRule, TagCheck> ruleToCheckMap = new HashMap<>();34 public final class MapCSSTagCheckerIndex { 35 final Map<Declaration, TagCheck> ruleToCheckMap = new HashMap<>(); 35 36 36 37 static final boolean ALL_TESTS = true; … … 57 58 */ 58 59 final MapCSSRuleIndex multipolygonRules = new MapCSSRuleIndex(); 59 60 MapCSSTagCheckerIndex(MultiMap<String, TagCheck> checks, boolean includeOtherSeverity, boolean allTests) { 61 buildIndex(checks, includeOtherSeverity, allTests); 62 } 63 64 private void buildIndex(MultiMap<String, TagCheck> checks, boolean includeOtherSeverity, boolean allTests) { 65 List<TagCheck> allChecks = new ArrayList<>(); 66 for (Set<TagCheck> cs : checks.values()) { 67 allChecks.addAll(cs); 68 } 69 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() { 70 84 ruleToCheckMap.clear(); 71 85 nodeRules.clear(); … … 74 88 relationRules.clear(); 75 89 multipolygonRules.clear(); 76 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(); 77 100 // optimization: filter rules for different primitive types 78 for (TagCheck c : allChecks) { 79 if (!includeOtherSeverity && Severity.OTHER == c.getSeverity() 80 && c.setClassExpressions.isEmpty()) { 81 // Ignore "information" level checks if not wanted, unless they also set a MapCSS class 82 continue; 83 } 84 85 for (Selector s : c.rule.selectors) { 86 boolean hasLeftRightSel = s instanceof Selector.ChildOrParentSelector; 87 if (!allTests && !hasLeftRightSel) { 88 continue; 89 } 90 91 MapCSSRule optRule = new MapCSSRule(s, c.rule.declaration); 92 93 ruleToCheckMap.put(optRule, c); 94 final String base = s.getBase(); 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) -> { 95 106 switch (base) { 96 107 case Selector.BASE_NODE: … … 117 128 break; 118 129 case Selector.BASE_CANVAS: 130 canvasRules.add(optRule); 131 break; 119 132 case Selector.BASE_META: 120 133 case Selector.BASE_SETTING: 134 case Selector.BASE_SETTINGS: 121 135 break; 122 136 default: … … 125 139 Logging.error(e); 126 140 } 127 } 128 } 141 }); 142 }); 143 initIndex(); 144 } 145 146 private void initIndex() { 129 147 nodeRules.initIndex(); 130 148 wayRules.initIndex(); … … 132 150 relationRules.initIndex(); 133 151 multipolygonRules.initIndex(); 152 canvasRules.initIndex(); 134 153 } 135 154 136 155 /** 137 156 * Get the index of rules for the given primitive. 138 * @param p the primit ve157 * @param p the primitive 139 158 * @return index of rules for the given primitive 140 159 */ 141 public MapCSSRuleIndex get( OsmPrimitive p) {160 public MapCSSRuleIndex get(IPrimitive p) { 142 161 if (p instanceof INode) { 143 162 return nodeRules; … … 151 170 if (((IRelation<?>) p).isMultipolygon()) { 152 171 return multipolygonRules; 172 } else if (p.hasKey("#canvas")) { 173 return canvasRules; 153 174 } else { 154 175 return relationRules; … … 160 181 161 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 /** 162 196 * return the TagCheck for which the given indexed rule was created. 163 197 * @param rule an indexed rule … … 165 199 */ 166 200 public TagCheck getCheck(MapCSSRule rule) { 167 return ruleToCheckMap.get(rule );201 return ruleToCheckMap.get(rule.declaration); 168 202 } 169 203 } -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
r15983 r15988 650 650 selectors=selectors() 651 651 decl=declaration() 652 { 653 for (Selector s : selectors) { 654 sheet.rules.add(new MapCSSRule(s, decl)); 655 } 652 { 653 sheet.rules.add(new MapCSSRule(selectors, decl)); 656 654 } 657 655 } -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java
r15984 r15988 2 2 package org.openstreetmap.josm.gui.mappaint.mapcss; 3 3 4 import java.util.List; 4 5 import java.util.stream.Collectors; 5 6 6 7 import org.openstreetmap.josm.gui.mappaint.Environment; 8 import org.openstreetmap.josm.tools.Utils; 7 9 8 10 /** … … 18 20 * The selector. If it matches, this rule should be applied 19 21 */ 20 public final Selector selector;22 public final List<Selector> selectors; 21 23 /** 22 24 * The instructions for this selector … … 26 28 /** 27 29 * Constructs a new {@code MapCSSRule}. 28 * @param selector The selector30 * @param selectors The selectors 29 31 * @param declaration The declaration 30 32 */ 31 public MapCSSRule( Selector selector, Declaration declaration) {32 this.selector = selector;33 public MapCSSRule(List<Selector> selectors, Declaration declaration) { 34 this.selectors = Utils.toUnmodifiableList(selectors); 33 35 this.declaration = declaration; 34 36 } … … 44 46 */ 45 47 public boolean matches(Environment env) { 46 return selector .matches(env);48 return selectors.stream().anyMatch(s -> s.matches(env)); 47 49 } 48 50 … … 64 66 @Override 65 67 public String toString() { 66 return selector + declaration.instructions.stream() 68 final String selectorsString = selectors.stream().map(String::valueOf) 69 .collect(Collectors.joining(",\n")); 70 final String declarationString = declaration.instructions.stream() 67 71 .map(String::valueOf) 68 72 .collect(Collectors.joining("\n ", " {\n ", "\n}")); 73 return selectorsString + declarationString; 69 74 } 70 75 } -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
r15987 r15988 14 14 import java.lang.reflect.Field; 15 15 import java.nio.charset.StandardCharsets; 16 import java.text.MessageFormat;17 16 import java.util.ArrayList; 18 17 import java.util.BitSet; 19 import java.util.Collection;20 18 import java.util.Collections; 21 19 import java.util.HashMap; … … 36 34 37 35 import org.openstreetmap.josm.data.Version; 38 import org.openstreetmap.josm.data.osm.INode;39 36 import org.openstreetmap.josm.data.osm.IPrimitive; 40 import org.openstreetmap.josm.data.osm.IRelation;41 import org.openstreetmap.josm.data.osm.IWay;42 37 import org.openstreetmap.josm.data.osm.KeyValueVisitor; 43 38 import org.openstreetmap.josm.data.osm.Node; 44 import org.openstreetmap.josm.data.osm.OsmUtils;45 39 import org.openstreetmap.josm.data.osm.Tagged; 46 40 import org.openstreetmap.josm.data.preferences.sources.SourceEntry; 41 import org.openstreetmap.josm.data.validation.tests.MapCSSTagCheckerIndex; 47 42 import org.openstreetmap.josm.gui.mappaint.Cascade; 48 43 import org.openstreetmap.josm.gui.mappaint.Environment; … … 89 84 public final List<MapCSSRule> rules = new ArrayList<>(); 90 85 /** 91 * Rules for nodes 92 */ 93 public final MapCSSRuleIndex nodeRules = new MapCSSRuleIndex(); 94 /** 95 * Rules for ways without tag area=no 96 */ 97 public final MapCSSRuleIndex wayRules = new MapCSSRuleIndex(); 98 /** 99 * Rules for ways with tag area=no 100 */ 101 public final MapCSSRuleIndex wayNoAreaRules = new MapCSSRuleIndex(); 102 /** 103 * Rules for relations that are not multipolygon relations 104 */ 105 public final MapCSSRuleIndex relationRules = new MapCSSRuleIndex(); 106 /** 107 * Rules for multipolygon relations 108 */ 109 public final MapCSSRuleIndex multipolygonRules = new MapCSSRuleIndex(); 110 /** 111 * rules to apply canvas properties 112 */ 113 public final MapCSSRuleIndex canvasRules = new MapCSSRuleIndex(); 86 * Index of rules in this style file 87 */ 88 private final MapCSSTagCheckerIndex ruleIndex = new MapCSSTagCheckerIndex(); 114 89 115 90 private Color backgroundColorOverride; … … 292 267 for (int ruleIndex = 0; ruleIndex < rules.size(); ruleIndex++) { 293 268 MapCSSRule r = rules.get(ruleIndex); 294 final List<Condition> conditions = r.selector.getConditions(); 295 if (conditions == null || conditions.isEmpty()) { 296 remaining.set(ruleIndex); 297 continue; 298 } 299 Optional<SimpleKeyValueCondition> lastCondition = Utils.filteredCollection(conditions, SimpleKeyValueCondition.class).stream() 300 .reduce((first, last) -> last); 301 if (lastCondition.isPresent()) { 302 getEntryInIndex(lastCondition.get().k).addForKeyAndValue(lastCondition.get().v, ruleIndex); 303 } else { 304 String key = findAnyRequiredKey(conditions); 305 if (key != null) { 306 getEntryInIndex(key).addForKey(ruleIndex); 269 for (Selector selector : r.selectors) { 270 final List<Condition> conditions = selector.getConditions(); 271 if (conditions == null || conditions.isEmpty()) { 272 remaining.set(ruleIndex); 273 continue; 274 } 275 Optional<SimpleKeyValueCondition> lastCondition = Utils.filteredCollection(conditions, SimpleKeyValueCondition.class) 276 .stream() 277 .reduce((first, last) -> last); 278 if (lastCondition.isPresent()) { 279 getEntryInIndex(lastCondition.get().k).addForKeyAndValue(lastCondition.get().v, ruleIndex); 307 280 } else { 308 remaining.set(ruleIndex); 281 String key = findAnyRequiredKey(conditions); 282 if (key != null) { 283 getEntryInIndex(key).addForKey(ruleIndex); 284 } else { 285 remaining.set(ruleIndex); 286 } 309 287 } 310 288 } … … 418 396 init(); 419 397 rules.clear(); 420 nodeRules.clear(); 421 wayRules.clear(); 422 wayNoAreaRules.clear(); 423 relationRules.clear(); 424 multipolygonRules.clear(); 425 canvasRules.clear(); 398 ruleIndex.clear(); 426 399 // remove "areaStyle" pseudo classes intended only for validator (causes StackOverflowError otherwise), see #16183 427 400 removeAreaStylePseudoClass = url == null || !url.contains("validator"); // resource://data/validator/ or xxx.validator.mapcss … … 461 434 } 462 435 // optimization: filter rules for different primitive types 463 for (MapCSSRule optRule: rules) { 464 final String base = optRule.selector.getBase(); 465 switch (base) { 466 case Selector.BASE_NODE: 467 nodeRules.add(optRule); 468 break; 469 case Selector.BASE_WAY: 470 wayNoAreaRules.add(optRule); 471 wayRules.add(optRule); 472 break; 473 case Selector.BASE_AREA: 474 wayRules.add(optRule); 475 multipolygonRules.add(optRule); 476 break; 477 case Selector.BASE_RELATION: 478 relationRules.add(optRule); 479 multipolygonRules.add(optRule); 480 break; 481 case Selector.BASE_ANY: 482 nodeRules.add(optRule); 483 wayRules.add(optRule); 484 wayNoAreaRules.add(optRule); 485 relationRules.add(optRule); 486 multipolygonRules.add(optRule); 487 break; 488 case Selector.BASE_CANVAS: 489 canvasRules.add(optRule); 490 break; 491 case Selector.BASE_META: 492 case Selector.BASE_SETTING: 493 case Selector.BASE_SETTINGS: 494 break; 495 default: 496 final RuntimeException e = new JosmRuntimeException(MessageFormat.format("Unknown MapCSS base selector {0}", base)); 497 Logging.warn(tr("Failed to parse Mappaint styles from ''{0}''. Error was: {1}", url, e.getMessage())); 498 Logging.error(e); 499 logError(e); 500 } 501 } 502 nodeRules.initIndex(); 503 wayRules.initIndex(); 504 wayNoAreaRules.initIndex(); 505 relationRules.initIndex(); 506 multipolygonRules.initIndex(); 507 canvasRules.initIndex(); 436 ruleIndex.buildIndex(rules.stream()); 508 437 loaded = true; 509 438 } finally { … … 588 517 // Parse rules 589 518 for (MapCSSRule r : rules) { 590 if (r.selector instanceof GeneralSelector) {591 GeneralSelector gs = (GeneralSelector) r.selector;519 final Selector gs = r.selectors.get(0); 520 if (gs instanceof GeneralSelector) { 592 521 if (Selector.BASE_SETTING.equals(gs.getBase())) { 593 loadSettings(r, gs, env);522 loadSettings(r, ((GeneralSelector) gs), env); 594 523 } else if (Selector.BASE_SETTINGS.equals(gs.getBase())) { 595 loadSettings(r, gs, envGroups);524 loadSettings(r, ((GeneralSelector) gs), envGroups); 596 525 } 597 526 } … … 639 568 640 569 for (MapCSSRule r : rules) { 641 if (r.selector instanceof GeneralSelector) { 642 GeneralSelector gs = (GeneralSelector) r.selector; 643 if (gs.getBase().equals(type)) { 644 if (!gs.matchesConditions(env)) { 645 continue; 646 } 647 r.execute(env); 648 } 570 final boolean matches = r.selectors.stream().anyMatch(gs -> gs instanceof GeneralSelector 571 && gs.getBase().equals(type) 572 && ((GeneralSelector) gs).matchesConditions(env)); 573 if (matches) { 574 r.execute(env); 649 575 } 650 576 } … … 659 585 @Override 660 586 public void apply(MultiCascade mc, IPrimitive osm, double scale, boolean pretendWayIsClosed) { 661 MapCSSRuleIndex matchingRuleIndex;662 if (osm instanceof INode) {663 matchingRuleIndex = nodeRules;664 } else if (osm instanceof IWay) {665 if (OsmUtils.isFalse(osm.get("area"))) {666 matchingRuleIndex = wayNoAreaRules;667 } else {668 matchingRuleIndex = wayRules;669 }670 } else if (osm instanceof IRelation) {671 if (((IRelation<?>) osm).isMultipolygon()) {672 matchingRuleIndex = multipolygonRules;673 } else if (osm.hasKey("#canvas")) {674 matchingRuleIndex = canvasRules;675 } else {676 matchingRuleIndex = relationRules;677 }678 } else {679 throw new IllegalArgumentException("Unsupported type: " + osm);680 }681 587 682 588 Environment env = new Environment(osm, mc, null, this); … … 684 590 int lastDeclUsed = -1; 685 591 686 Iterator<MapCSSRule> candidates = matchingRuleIndex.getRuleCandidates(osm);592 Iterator<MapCSSRule> candidates = ruleIndex.getRuleCandidates(osm); 687 593 while (candidates.hasNext()) { 688 594 MapCSSRule r = candidates.next(); 689 env.clearSelectorMatchingInformation(); 690 env.layer = r.selector.getSubpart().getId(env); 691 String sub = env.layer; 692 if (r.selector.matches(env)) { // as side effect env.parent will be set (if s is a child selector) 693 Selector s = r.selector; 595 for (Selector s : r.selectors) { 596 env.clearSelectorMatchingInformation(); 597 env.layer = s.getSubpart().getId(env); 598 String sub = env.layer; 599 if (!s.matches(env)) { // as side effect env.parent will be set (if s is a child selector) 600 continue; 601 } 694 602 if (s.getRange().contains(scale)) { 695 603 mc.range = Range.cut(mc.range, s.getRange()); … … 746 654 */ 747 655 public void removeMetaRules() { 748 rules.removeIf(x -> x.selector instanceof GeneralSelector && Selector.BASE_META.equals(x.selector.getBase()));656 rules.removeIf(x -> x.selectors.get(0) instanceof GeneralSelector && Selector.BASE_META.equals(x.selectors.get(0).getBase())); 749 657 } 750 658 -
trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java
r15981 r15988 67 67 final MapCSSTagChecker test = new MapCSSTagChecker(); 68 68 Set<String> errors = new HashSet<>(); 69 test.checks.putAll("test", TagCheck.readMapCSS(new StringReader(css), "",errors::add).parseChecks);69 test.checks.putAll("test", TagCheck.readMapCSS(new StringReader(css), errors::add).parseChecks); 70 70 assertTrue(errors.toString(), errors.isEmpty()); 71 71 return test; -
trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ChildOrParentSelectorTest.java
r15102 r15988 74 74 source.loadStyleSource(); 75 75 assertEquals(1, source.rules.size()); 76 return (ChildOrParentSelector) source.rules.get(0).selector ;76 return (ChildOrParentSelector) source.rules.get(0).selectors.get(0); 77 77 } 78 78
Note:
See TracChangeset
for help on using the changeset viewer.