Changeset 14484 in josm for trunk


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
Files:
9 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<>();
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java

    r14436 r14484  
    872872        }
    873873
     874        /**
     875         * Returns the expression.
     876         * @return the expression
     877         * @since 14484
     878         */
     879        public final Expression getExpression() {
     880            return e;
     881        }
     882
    874883        @Override
    875884        public boolean applies(Environment env) {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java

    r14371 r14484  
    13061306        }
    13071307
     1308        /**
     1309         * Returns the method.
     1310         * @return the method
     1311         * @since 14484
     1312         */
     1313        public final Method getMethod() {
     1314            return m;
     1315        }
     1316
     1317        /**
     1318         * Returns the arguments.
     1319         * @return the arguments
     1320         * @since 14484
     1321         */
     1322        public final List<Expression> getArgs() {
     1323            return args;
     1324        }
     1325
    13081326        @Override
    13091327        public Object evaluate(Environment env) {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/LiteralExpression.java

    r10300 r14484  
    2323    }
    2424
     25    /**
     26     * Returns the literal.
     27     * @return the literal
     28     * @since 14484
     29     */
     30    public final Object getLiteral() {
     31        return literal;
     32    }
     33
    2534    @Override
    2635    public Object evaluate(Environment env) {
  • trunk/src/org/openstreetmap/josm/tools/DefaultGeoProperty.java

    r11361 r14484  
    6060    }
    6161
     62    /**
     63     * Returns the area.
     64     * @return the area
     65     * @since 14484
     66     */
     67    public final Area getArea() {
     68        return area;
     69    }
    6270}
  • trunk/src/org/openstreetmap/josm/tools/GeoPropertyIndex.java

    r14008 r14484  
    4848    public T get(LatLon ll) {
    4949        return lastLevelUsed.get(ll);
     50    }
     51
     52    /**
     53     * Returns the geo property.
     54     * @return the geo property
     55     * @since 14484
     56     */
     57    public final GeoProperty<T> getGeoProperty() {
     58        return geoProp;
    5059    }
    5160
  • trunk/src/org/openstreetmap/josm/tools/Territories.java

    r14035 r14484  
    5151
    5252    /**
    53      * Determine, if a point is inside a territory with the given the ISO3166-1
     53     * Returns the {@link GeoPropertyIndex} for the given ISO3166-1 or ISO3166-2 code.
     54     * @param code the ISO3166-1 or ISO3166-2 code
     55     * @return the {@link GeoPropertyIndex} for the given {@code code}
     56     * @since 14484
     57     */
     58    public static GeoPropertyIndex<Boolean> getGeoPropertyIndex(String code) {
     59        return iso3166Cache.get(code);
     60    }
     61
     62    /**
     63     * Determine, if a point is inside a territory with the given ISO3166-1
    5464     * or ISO3166-2 code.
    5565     *
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java

    r14481 r14484  
    5252    @Rule
    5353    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    54     public JOSMTestRules test = new JOSMTestRules().projection();
     54    public JOSMTestRules test = new JOSMTestRules().projection().territories();
    5555
    5656    static MapCSSTagChecker buildTagChecker(String css) throws ParseException {
     
    191191
    192192    /**
     193     * Checks that assertions work for country-specific checks.
     194     * @throws ParseException if a parsing error occurs
     195     */
     196    @Test
     197    public void testAssertInsideCountry() throws ParseException {
     198        final MapCSSTagChecker test = buildTagChecker(
     199                "node[amenity=parking][inside(\"BR\")] {\n" +
     200                "  throwWarning: \"foo\";\n" +
     201                "  assertMatch: \"node amenity=parking\";\n" +
     202                "  assertNoMatch: \"node amenity=restaurant\";\n" +
     203                "}");
     204        Set<String> errors = test.checkAsserts(test.checks.get("test"));
     205        assertTrue(errors.toString(), errors.isEmpty());
     206    }
     207
     208    /**
    193209     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/13762">Bug #13762</a>.
    194210     * @throws ParseException if a parsing error occurs
Note: See TracChangeset for help on using the changeset viewer.