Ignore:
Timestamp:
2018-12-02T02:32:13+01:00 (5 years ago)
Author:
Don-vip
Message:

fix #17058 - Cannot add assertMatch/assertNoMatch declarations with inside() selector

Location:
trunk/src/org/openstreetmap/josm/data
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/OsmUtils.java

    r14238 r14484  
    113113
    114114    /**
    115      * Creates a new OSM primitive according to the given assertion. Originally written for unit tests,
     115     * Creates a new OSM primitive around (0,0) according to the given assertion. Originally written for unit tests,
    116116     * this can also be used in another places like validation of local MapCSS validator rules.
    117117     * @param assertion The assertion describing OSM primitive (ex: "way name=Foo railway=rail")
     
    121121     */
    122122    public static OsmPrimitive createPrimitive(String assertion) {
     123        return createPrimitive(assertion, LatLon.ZERO);
     124    }
     125
     126    /**
     127     * Creates a new OSM primitive according to the given assertion. Originally written for unit tests,
     128     * this can also be used in another places like validation of local MapCSS validator rules.
     129     * @param assertion The assertion describing OSM primitive (ex: "way name=Foo railway=rail")
     130     * @param around the coordinate at which the primitive will be located
     131     * @return a new OSM primitive according to the given assertion
     132     * @throws IllegalArgumentException if assertion is null or if the primitive type cannot be deduced from it
     133     * @since 14484
     134     */
     135    public static OsmPrimitive createPrimitive(String assertion, LatLon around) {
    123136        CheckParameterUtil.ensureParameterNotNull(assertion, "assertion");
    124137        final String[] x = assertion.split("\\s+", 2);
    125138        final OsmPrimitive p = "n".equals(x[0]) || "node".equals(x[0])
    126                 ? new Node(LatLon.ZERO)
     139                ? new Node(around)
    127140                : "w".equals(x[0]) || "way".equals(x[0]) || /*for MapCSS related usage*/ "area".equals(x[0])
    128                 ? new Way()
     141                ? newWay(around)
    129142                : "r".equals(x[0]) || "relation".equals(x[0])
    130                 ? new Relation()
     143                ? newRelation(around)
    131144                : null;
    132145        if (p == null) {
     
    139152        }
    140153        return p;
     154    }
     155
     156    private static Node newNode(LatLon around) {
     157        return new Node(around);
     158    }
     159
     160    private static Way newWay(LatLon around) {
     161        Way w = new Way();
     162        w.addNode(newNode(new LatLon(around.lat()+0.1, around.lon())));
     163        w.addNode(newNode(new LatLon(around.lat()-0.1, around.lon())));
     164        return w;
     165    }
     166
     167    private static Relation newRelation(LatLon around) {
     168        Relation r = new Relation();
     169        r.addMember(new RelationMember(null, newNode(around)));
     170        return r;
    141171    }
    142172
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r14481 r14484  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.Rectangle;
    67import java.io.BufferedReader;
    78import java.io.IOException;
     
    910import java.io.Reader;
    1011import java.io.StringReader;
     12import java.lang.reflect.Method;
    1113import java.text.MessageFormat;
    1214import java.util.ArrayList;
     
    3537import org.openstreetmap.josm.command.DeleteCommand;
    3638import org.openstreetmap.josm.command.SequenceCommand;
     39import org.openstreetmap.josm.data.coor.LatLon;
    3740import org.openstreetmap.josm.data.osm.DataSet;
    3841import org.openstreetmap.josm.data.osm.INode;
     
    5356import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    5457import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition;
     58import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ExpressionCondition;
    5559import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
     60import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.Functions;
     61import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.ParameterFunction;
    5662import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     63import org.openstreetmap.josm.gui.mappaint.mapcss.LiteralExpression;
    5764import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
    5865import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule.Declaration;
     
    7380import org.openstreetmap.josm.spi.preferences.Config;
    7481import org.openstreetmap.josm.tools.CheckParameterUtil;
     82import org.openstreetmap.josm.tools.DefaultGeoProperty;
     83import org.openstreetmap.josm.tools.GeoProperty;
     84import org.openstreetmap.josm.tools.GeoPropertyIndex;
    7585import org.openstreetmap.josm.tools.I18n;
    7686import org.openstreetmap.josm.tools.JosmRuntimeException;
    7787import org.openstreetmap.josm.tools.Logging;
    7888import org.openstreetmap.josm.tools.MultiMap;
     89import org.openstreetmap.josm.tools.Territories;
    7990import org.openstreetmap.josm.tools.Utils;
    8091
     
    958969    }
    959970
     971    private static Method getFunctionMethod(String method) {
     972        try {
     973            return Functions.class.getDeclaredMethod(method, Environment.class, String.class);
     974        } catch (NoSuchMethodException | SecurityException e) {
     975            Logging.error(e);
     976            return null;
     977        }
     978    }
     979
     980    private static Optional<String> getFirstInsideCountry(TagCheck check, Method insideMethod) {
     981        return check.rule.selectors.stream()
     982                .filter(s -> s instanceof GeneralSelector)
     983                .flatMap(s -> ((GeneralSelector) s).getConditions().stream())
     984                .filter(c -> c instanceof ExpressionCondition)
     985                .map(c -> ((ExpressionCondition) c).getExpression())
     986                .filter(c -> c instanceof ParameterFunction)
     987                .map(c -> (ParameterFunction) c)
     988                .filter(c -> c.getMethod().equals(insideMethod))
     989                .flatMap(c -> c.getArgs().stream())
     990                .filter(e -> e instanceof LiteralExpression)
     991                .map(e -> ((LiteralExpression) e).getLiteral())
     992                .filter(l -> l instanceof String)
     993                .map(l -> (String) l)
     994                .findFirst();
     995    }
     996
     997    private static LatLon getLocation(TagCheck check, Method insideMethod) {
     998        Optional<String> inside = getFirstInsideCountry(check, insideMethod);
     999        if (inside.isPresent()) {
     1000            GeoPropertyIndex<Boolean> index = Territories.getGeoPropertyIndex(inside.get());
     1001            if (index != null) {
     1002                GeoProperty<Boolean> prop = index.getGeoProperty();
     1003                if (prop instanceof DefaultGeoProperty) {
     1004                    Rectangle bounds = ((DefaultGeoProperty) prop).getArea().getBounds();
     1005                    return new LatLon(bounds.getCenterY(), bounds.getCenterX());
     1006                }
     1007            }
     1008        }
     1009        return LatLon.ZERO;
     1010    }
     1011
    9601012    /**
    9611013     * Checks that rule assertions are met for the given set of TagChecks.
     
    9661018    public Set<String> checkAsserts(final Collection<TagCheck> schecks) {
    9671019        Set<String> assertionErrors = new LinkedHashSet<>();
     1020        final Method insideMethod = getFunctionMethod("inside");
    9681021        final DataSet ds = new DataSet();
    9691022        for (final TagCheck check : schecks) {
     
    9711024            for (final Map.Entry<String, Boolean> i : check.assertions.entrySet()) {
    9721025                Logging.debug("- Assertion: {0}", i);
    973                 final OsmPrimitive p = OsmUtils.createPrimitive(i.getKey());
     1026                final OsmPrimitive p = OsmUtils.createPrimitive(i.getKey(), getLocation(check, insideMethod));
    9741027                // Build minimal ordered list of checks to run to test the assertion
    9751028                List<Set<TagCheck>> checksToRun = new ArrayList<>();
Note: See TracChangeset for help on using the changeset viewer.