commit ca1b0013680e30cc419f726fab6282f488084531
Author: Simon Legner <Simon.Legner@gmail.com>
Date: Fri Jan 11 17:43:05 2019 +0100
v1
diff --git a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
index 31d9438b8..9d70b60da 100644
|
a
|
b
|
|
| 41 | 41 | import org.openstreetmap.josm.data.osm.OsmUtils; |
| 42 | 42 | import org.openstreetmap.josm.data.osm.Relation; |
| 43 | 43 | import org.openstreetmap.josm.data.osm.Tag; |
| | 44 | import org.openstreetmap.josm.data.osm.Tagged; |
| 44 | 45 | import org.openstreetmap.josm.data.osm.Way; |
| 45 | 46 | import org.openstreetmap.josm.data.preferences.sources.SourceEntry; |
| 46 | 47 | import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper; |
| … |
… |
|
| 49 | 50 | import org.openstreetmap.josm.data.validation.Test; |
| 50 | 51 | import org.openstreetmap.josm.data.validation.TestError; |
| 51 | 52 | import org.openstreetmap.josm.gui.mappaint.Environment; |
| 52 | | import org.openstreetmap.josm.gui.mappaint.Keyword; |
| 53 | 53 | import org.openstreetmap.josm.gui.mappaint.MultiCascade; |
| 54 | 54 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition; |
| 55 | 55 | import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition; |
| … |
… |
public ParseResult(List<TagCheck> parseChecks, Collection<Throwable> parseErrors
|
| 286 | 286 | protected final GroupedMapCSSRule rule; |
| 287 | 287 | /** Commands to apply in order to fix a matching primitive */ |
| 288 | 288 | protected final List<FixCommand> fixCommands = new ArrayList<>(); |
| 289 | | /** Tags (or arbitraty strings) of alternatives to be presented to the user */ |
| | 289 | /** Tags (or arbitrary strings) of alternatives to be presented to the user */ |
| 290 | 290 | protected final List<String> alternatives = new ArrayList<>(); |
| 291 | 291 | /** An {@link org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.AssignmentInstruction}-{@link Severity} pair. |
| 292 | 292 | * Is evaluated on the matching primitive to give the error message. Map is checked to contain exactly one element. */ |
| … |
… |
static TagCheck ofMapCSSRule(final GroupedMapCSSRule rule) throws IllegalDataExc
|
| 329 | 329 | continue; |
| 330 | 330 | } |
| 331 | 331 | try { |
| 332 | | final String val = ai.val instanceof Expression |
| 333 | | ? Optional.ofNullable(((Expression) ai.val).evaluate(new Environment())).map(Object::toString).orElse(null) |
| 334 | | : ai.val instanceof String |
| 335 | | ? (String) ai.val |
| 336 | | : ai.val instanceof Keyword |
| 337 | | ? ((Keyword) ai.val).val |
| 338 | | : null; |
| | 332 | final String val = ai.getValAsString(); |
| 339 | 333 | if (ai.key.startsWith("throw")) { |
| 340 | 334 | try { |
| 341 | 335 | check.errors.put(ai, Severity.valueOf(ai.key.substring("throw".length()).toUpperCase(Locale.ENGLISH))); |
| … |
… |
Selector whichSelectorMatchesEnvironment(Environment env) {
|
| 445 | 439 | * @param matchingSelector matching selector |
| 446 | 440 | * @param index index |
| 447 | 441 | * @param type selector type ("key", "value" or "tag") |
| 448 | | * @param p OSM primitive |
| | 442 | * @param p a tagged object |
| 449 | 443 | * @return argument value, can be {@code null} |
| 450 | 444 | */ |
| 451 | | static String determineArgument(OptimizedGeneralSelector matchingSelector, int index, String type, OsmPrimitive p) { |
| | 445 | static String determineArgument(OptimizedGeneralSelector matchingSelector, int index, String type, Tagged p) { |
| 452 | 446 | try { |
| 453 | 447 | final Condition c = matchingSelector.getConditions().get(index); |
| 454 | | final Tag tag = c instanceof Condition.ToTagConvertable |
| 455 | | ? ((Condition.ToTagConvertable) c).asTag(p) |
| | 448 | final Tag tag = c instanceof Condition.TagCondition |
| | 449 | ? ((Condition.TagCondition) c).asTag(p) |
| 456 | 450 | : null; |
| 457 | 451 | if (tag == null) { |
| 458 | 452 | return null; |
| … |
… |
static String determineArgument(OptimizedGeneralSelector matchingSelector, int i
|
| 474 | 468 | * key/value/tag of the {@code index}-th {@link Condition} of {@code matchingSelector}. |
| 475 | 469 | * @param matchingSelector matching selector |
| 476 | 470 | * @param s any string |
| 477 | | * @param p OSM primitive |
| | 471 | * @param p a tagged object |
| 478 | 472 | * @return string with arguments inserted |
| 479 | 473 | */ |
| 480 | | static String insertArguments(Selector matchingSelector, String s, OsmPrimitive p) { |
| | 474 | static String insertArguments(Selector matchingSelector, String s, Tagged p) { |
| 481 | 475 | if (s != null && matchingSelector instanceof Selector.ChildOrParentSelector) { |
| 482 | 476 | return insertArguments(((Selector.ChildOrParentSelector) matchingSelector).right, s, p); |
| 483 | 477 | } else if (s == null || !(matchingSelector instanceof Selector.OptimizedGeneralSelector)) { |
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
index f0eab71e3..d10aa1be9 100644
|
a
|
b
|
|
| 3 | 3 | |
| 4 | 4 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| 5 | 5 | import org.openstreetmap.josm.data.osm.Tag; |
| | 6 | import org.openstreetmap.josm.data.osm.Tagged; |
| 6 | 7 | import org.openstreetmap.josm.gui.mappaint.Environment; |
| | 8 | import org.openstreetmap.josm.tools.Utils; |
| 7 | 9 | |
| 8 | 10 | /** |
| 9 | 11 | * This is a condition that needs to be fulfilled in order to apply a MapCSS style. |
| … |
… |
|
| 38 | 40 | * @author Michael Zangl |
| 39 | 41 | * @since 10674 |
| 40 | 42 | */ |
| 41 | | @FunctionalInterface |
| 42 | | interface ToTagConvertable { |
| | 43 | interface TagCondition extends Condition { |
| | 44 | |
| | 45 | @Override |
| | 46 | default boolean applies(Environment e) { |
| | 47 | return applies(e.osm); |
| | 48 | } |
| | 49 | |
| | 50 | /** |
| | 51 | * Checks if the condition applies in the given {@link Tagged} element. |
| | 52 | * @param tagged The tagged to check. |
| | 53 | * @return <code>true</code> if the condition applies. |
| | 54 | */ |
| | 55 | boolean applies(Tagged tagged); |
| | 56 | |
| 43 | 57 | /** |
| 44 | 58 | * Converts the current condition to a tag |
| 45 | | * @param primitive A primitive to use as context. May be ignored. |
| | 59 | * @param tagged A tagged object to use as context. May be ignored. |
| 46 | 60 | * @return A tag with the key/value of this condition. |
| 47 | 61 | */ |
| 48 | | Tag asTag(OsmPrimitive primitive); |
| | 62 | Tag asTag(Tagged tagged); |
| 49 | 63 | } |
| 50 | 64 | } |
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java
index e0cc01b46..29d6ce2a1 100644
|
a
|
b
|
|
| 23 | 23 | import org.openstreetmap.josm.data.osm.OsmUtils; |
| 24 | 24 | import org.openstreetmap.josm.data.osm.Relation; |
| 25 | 25 | import org.openstreetmap.josm.data.osm.Tag; |
| | 26 | import org.openstreetmap.josm.data.osm.Tagged; |
| 26 | 27 | import org.openstreetmap.josm.data.osm.search.SearchCompiler.InDataSourceArea; |
| 27 | 28 | import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; |
| 28 | 29 | import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache; |
| … |
… |
|
| 30 | 31 | import org.openstreetmap.josm.gui.mappaint.ElemStyles; |
| 31 | 32 | import org.openstreetmap.josm.gui.mappaint.Environment; |
| 32 | 33 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; |
| 33 | | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable; |
| | 34 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition; |
| 34 | 35 | import org.openstreetmap.josm.tools.CheckParameterUtil; |
| 35 | 36 | import org.openstreetmap.josm.tools.JosmRuntimeException; |
| 36 | 37 | import org.openstreetmap.josm.tools.Utils; |
| … |
… |
public boolean eval(String testString, String prototypeString) {
|
| 243 | 244 | * |
| 244 | 245 | * Extra class for performance reasons. |
| 245 | 246 | */ |
| 246 | | public static class SimpleKeyValueCondition implements Condition, ToTagConvertable { |
| | 247 | public static class SimpleKeyValueCondition implements TagCondition { |
| 247 | 248 | /** |
| 248 | 249 | * The key to search for. |
| 249 | 250 | */ |
| … |
… |
public SimpleKeyValueCondition(String k, String v) {
|
| 264 | 265 | } |
| 265 | 266 | |
| 266 | 267 | @Override |
| 267 | | public boolean applies(Environment e) { |
| 268 | | return v.equals(e.osm.get(k)); |
| | 268 | public boolean applies(Tagged tagged) { |
| | 269 | return v.equals(tagged.get(k)); |
| 269 | 270 | } |
| 270 | 271 | |
| 271 | 272 | @Override |
| 272 | | public Tag asTag(OsmPrimitive primitive) { |
| | 273 | public Tag asTag(Tagged tagged) { |
| 273 | 274 | return new Tag(k, v); |
| 274 | 275 | } |
| 275 | 276 | |
| … |
… |
public String toString() {
|
| 284 | 285 | * <p>Represents a key/value condition which is either applied to a primitive.</p> |
| 285 | 286 | * |
| 286 | 287 | */ |
| 287 | | public static class KeyValueCondition implements Condition, ToTagConvertable { |
| | 288 | public static class KeyValueCondition implements TagCondition { |
| 288 | 289 | /** |
| 289 | 290 | * The key to search for. |
| 290 | 291 | */ |
| … |
… |
public boolean requiresExactKeyMatch() {
|
| 327 | 328 | } |
| 328 | 329 | |
| 329 | 330 | @Override |
| 330 | | public boolean applies(Environment env) { |
| 331 | | return op.eval(env.osm.get(k), considerValAsKey ? env.osm.get(v) : v); |
| | 331 | public boolean applies(Tagged tagged) { |
| | 332 | return op.eval(tagged.get(k), considerValAsKey ? tagged.get(v) : v); |
| 332 | 333 | } |
| 333 | 334 | |
| 334 | 335 | @Override |
| 335 | | public Tag asTag(OsmPrimitive primitive) { |
| | 336 | public Tag asTag(Tagged tagged) { |
| 336 | 337 | return new Tag(k, v); |
| 337 | 338 | } |
| 338 | 339 | |
| … |
… |
public boolean applies(Environment env) {
|
| 512 | 513 | * LINK: not supported |
| 513 | 514 | * </pre> |
| 514 | 515 | */ |
| 515 | | public static class KeyCondition implements Condition, ToTagConvertable { |
| | 516 | public static class KeyCondition implements TagCondition { |
| 516 | 517 | |
| 517 | 518 | /** |
| 518 | 519 | * The key name. |
| … |
… |
public KeyCondition(String label, boolean negateResult, KeyMatchType matchType)
|
| 550 | 551 | @Override |
| 551 | 552 | public boolean applies(Environment e) { |
| 552 | 553 | switch(e.getContext()) { |
| 553 | | case PRIMITIVE: |
| 554 | | switch (matchType) { |
| | 554 | case PRIMITIVE: |
| | 555 | return applies(e.osm); |
| | 556 | case LINK: |
| | 557 | Utils.ensure(false, "Illegal state: {0} not supported in LINK context", getClass()); |
| | 558 | return false; |
| | 559 | default: throw new AssertionError(); |
| | 560 | } |
| | 561 | } |
| | 562 | |
| | 563 | @Override |
| | 564 | public boolean applies(Tagged tagged) { |
| | 565 | switch (matchType) { |
| 555 | 566 | case TRUE: |
| 556 | | return e.osm.isKeyTrue(label) ^ negateResult; |
| | 567 | return tagged.isKeyTrue(label) ^ negateResult; |
| 557 | 568 | case FALSE: |
| 558 | | return e.osm.isKeyFalse(label) ^ negateResult; |
| | 569 | return tagged.isKeyFalse(label) ^ negateResult; |
| 559 | 570 | case REGEX: |
| 560 | | return e.osm.keySet().stream().anyMatch(containsPattern) ^ negateResult; |
| | 571 | return tagged.keySet().stream().anyMatch(containsPattern) ^ negateResult; |
| 561 | 572 | default: |
| 562 | | return e.osm.hasKey(label) ^ negateResult; |
| 563 | | } |
| 564 | | case LINK: |
| 565 | | Utils.ensure(false, "Illegal state: KeyCondition not supported in LINK context"); |
| 566 | | return false; |
| 567 | | default: throw new AssertionError(); |
| | 573 | return tagged.hasKey(label) ^ negateResult; |
| 568 | 574 | } |
| 569 | 575 | } |
| 570 | 576 | |
| … |
… |
public boolean applies(Environment e) {
|
| 578 | 584 | * @return The tag. |
| 579 | 585 | */ |
| 580 | 586 | @Override |
| 581 | | public Tag asTag(OsmPrimitive p) { |
| | 587 | public Tag asTag(Tagged p) { |
| 582 | 588 | String key = label; |
| 583 | 589 | if (KeyMatchType.REGEX == matchType) { |
| 584 | 590 | key = p.keySet().stream().filter(containsPattern).findAny().orElse(key); |
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
index 793b85eaa..58b4082d8 100644
|
a
|
b
|
|
| 2 | 2 | package org.openstreetmap.josm.gui.mappaint.mapcss; |
| 3 | 3 | |
| 4 | 4 | import java.util.Arrays; |
| | 5 | import java.util.Optional; |
| 5 | 6 | |
| 6 | 7 | import org.openstreetmap.josm.gui.mappaint.Cascade; |
| 7 | 8 | import org.openstreetmap.josm.gui.mappaint.Environment; |
| … |
… |
public void execute(Environment env) {
|
| 102 | 103 | env.mc.getOrCreateCascade(env.layer).putOrClear(key, value); |
| 103 | 104 | } |
| 104 | 105 | |
| | 106 | public String getValAsString() { |
| | 107 | return this.val instanceof Expression |
| | 108 | ? Optional.ofNullable(((Expression) this.val).evaluate(new Environment())).map(Object::toString).orElse(null) |
| | 109 | : this.val instanceof String |
| | 110 | ? (String) this.val |
| | 111 | : this.val instanceof Keyword |
| | 112 | ? ((Keyword) this.val).val |
| | 113 | : null; |
| | 114 | } |
| | 115 | |
| 105 | 116 | @Override |
| 106 | 117 | public String toString() { |
| 107 | 118 | return key + ": " + (val instanceof float[] ? Arrays.toString((float[]) val) : |
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java
index fca2760f4..511fd351c 100644
|
a
|
b
|
|
| 43 | 43 | |
| 44 | 44 | /** |
| 45 | 45 | * Create a new {@link Declaration} |
| 46 | | * @param instructions The instructions for this dectlaration |
| | 46 | * @param instructions The instructions for this declaration |
| 47 | 47 | * @param idx The index in the {@link StyleSource} |
| 48 | 48 | */ |
| 49 | 49 | public Declaration(List<Instruction> instructions, int idx) { |
diff --git a/src/org/openstreetmap/josm/tools/Tag2Link.java b/src/org/openstreetmap/josm/tools/Tag2Link.java
new file mode 100644
index 000000000..e9490c14b
|
-
|
+
|
|
| | 1 | package org.openstreetmap.josm.tools; |
| | 2 | |
| | 3 | import java.net.URL; |
| | 4 | import java.util.ArrayList; |
| | 5 | import java.util.List; |
| | 6 | |
| | 7 | import org.openstreetmap.josm.data.osm.Tag; |
| | 8 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition; |
| | 9 | import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule; |
| | 10 | import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; |
| | 11 | |
| | 12 | public final class Tag2Link { |
| | 13 | |
| | 14 | final List<MapCSSRule> rules = new ArrayList<>(); |
| | 15 | |
| | 16 | private Tag2Link() { |
| | 17 | } |
| | 18 | |
| | 19 | public Iterable<URL> getLinksForTag(Tag tag) { |
| | 20 | for (MapCSSRule rule : rules) { |
| | 21 | for (Condition condition : ((Selector.AbstractSelector) rule.selector).getConditions()) { |
| | 22 | if (((Condition.TagCondition) condition).applies(tag)) { |
| | 23 | |
| | 24 | } |
| | 25 | } |
| | 26 | } |
| | 27 | } |
| | 28 | } |
diff --git a/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java b/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java
index 4fefb417e..890f311ba 100644
|
a
|
b
|
|
| 12 | 12 | import org.openstreetmap.josm.data.osm.OsmUtils; |
| 13 | 13 | import org.openstreetmap.josm.gui.mappaint.Environment; |
| 14 | 14 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; |
| 15 | | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable; |
| | 15 | import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition; |
| 16 | 16 | import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op; |
| 17 | 17 | import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition; |
| 18 | 18 | import org.openstreetmap.josm.testutils.JOSMTestRules; |
| … |
… |
public void testKeyValueEq() {
|
| 62 | 62 | |
| 63 | 63 | assertTrue(op instanceof SimpleKeyValueCondition); |
| 64 | 64 | assertEquals("[k1=v1]", op.toString()); |
| 65 | | assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey()); |
| 66 | | assertEquals("v1", ((ToTagConvertable) op).asTag(null).getValue()); |
| | 65 | assertEquals("k1", ((TagCondition) op).asTag(null).getKey()); |
| | 66 | assertEquals("v1", ((TagCondition) op).asTag(null).getValue()); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | /** |
| … |
… |
public void testKeyValueEqAsKey() {
|
| 78 | 78 | assertFalse(op.applies(genEnv(node3))); |
| 79 | 79 | assertFalse(op.applies(genEnv(node4))); |
| 80 | 80 | |
| 81 | | assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey()); |
| 82 | | assertEquals("k2", ((ToTagConvertable) op).asTag(null).getValue()); |
| | 81 | assertEquals("k1", ((TagCondition) op).asTag(null).getKey()); |
| | 82 | assertEquals("k2", ((TagCondition) op).asTag(null).getValue()); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | 85 | /** |