Changeset 15979 in josm


Ignore:
Timestamp:
2020-03-01T23:35:47+01:00 (3 months ago)
Author:
simon04
Message:

see #18802 - Extract MapCSSTagCheckerAsserts class

Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r15972 r15979  
    1010import java.io.Reader;
    1111import java.io.StringReader;
    12 import java.lang.reflect.Method;
    13 import java.text.MessageFormat;
    1412import java.util.ArrayList;
    1513import java.util.Collection;
    16 import java.util.Collections;
    1714import java.util.HashMap;
    1815import java.util.HashSet;
    1916import java.util.Iterator;
    2017import java.util.LinkedHashMap;
    21 import java.util.LinkedHashSet;
    2218import java.util.LinkedList;
    2319import java.util.List;
     
    3632import org.openstreetmap.josm.command.DeleteCommand;
    3733import org.openstreetmap.josm.command.SequenceCommand;
    38 import org.openstreetmap.josm.data.coor.LatLon;
    39 import org.openstreetmap.josm.data.osm.DataSet;
    4034import org.openstreetmap.josm.data.osm.IPrimitive;
    4135import org.openstreetmap.josm.data.osm.OsmPrimitive;
    42 import org.openstreetmap.josm.data.osm.OsmUtils;
    43 import org.openstreetmap.josm.data.osm.Relation;
    4436import org.openstreetmap.josm.data.osm.Tag;
    4537import org.openstreetmap.josm.data.osm.Way;
     
    5547import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    5648import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    57 import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition;
    58 import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ExpressionCondition;
    5949import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    60 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.ParameterFunction;
    61 import org.openstreetmap.josm.gui.mappaint.mapcss.Functions;
    6250import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
    63 import org.openstreetmap.josm.gui.mappaint.mapcss.LiteralExpression;
    6451import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
    6552import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule.Declaration;
     
    6754import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource.MapCSSRuleIndex;
    6855import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    69 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.AbstractSelector;
    70 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
    7156import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.OptimizedGeneralSelector;
    7257import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser;
     
    8065import org.openstreetmap.josm.spi.preferences.Config;
    8166import org.openstreetmap.josm.tools.CheckParameterUtil;
    82 import org.openstreetmap.josm.tools.DefaultGeoProperty;
    83 import org.openstreetmap.josm.tools.GeoProperty;
    84 import org.openstreetmap.josm.tools.GeoPropertyIndex;
    8567import org.openstreetmap.josm.tools.I18n;
    8668import org.openstreetmap.josm.tools.Logging;
    8769import org.openstreetmap.josm.tools.MultiMap;
    88 import org.openstreetmap.josm.tools.Territories;
    8970import org.openstreetmap.josm.tools.Utils;
    9071
     
    9677    private MapCSSTagCheckerIndex indexData;
    9778    private final Set<OsmPrimitive> tested = new HashSet<>();
    98     final Map<IPrimitive, Area> mpAreaCache = new HashMap<>();
     79    private static final Map<IPrimitive, Area> mpAreaCache = new HashMap<>();
    9980
    10081    /**
     
    668649        }
    669650
    670         /**
    671          * Returns the set of tagchecks on which this check depends on.
    672          * @param schecks the collection of tagcheks to search in
    673          * @return the set of tagchecks on which this check depends on
    674          * @since 7881
    675          */
    676         public Set<TagCheck> getTagCheckDependencies(Collection<TagCheck> schecks) {
    677             Set<TagCheck> result = new HashSet<>();
    678             Set<String> classes = getClassesIds();
    679             if (schecks != null && !classes.isEmpty()) {
    680                 for (TagCheck tc : schecks) {
    681                     if (this.equals(tc)) {
    682                         continue;
    683                     }
    684                     for (String id : tc.setClassExpressions) {
    685                         if (classes.contains(id)) {
    686                             result.add(tc);
    687                             break;
    688                         }
    689                     }
    690                 }
    691             }
    692             return result;
    693         }
    694 
    695         /**
    696          * Returns the list of ids of all MapCSS classes referenced in the rule selectors.
    697          * @return the list of ids of all MapCSS classes referenced in the rule selectors
    698          * @since 7881
    699          */
    700         public Set<String> getClassesIds() {
    701             Set<String> result = new HashSet<>();
    702             for (Selector s : rule.selectors) {
    703                 if (s instanceof AbstractSelector) {
    704                     for (Condition c : ((AbstractSelector) s).getConditions()) {
    705                         if (c instanceof ClassCondition) {
    706                             result.add(((ClassCondition) c).id);
    707                         }
    708                     }
    709                 }
    710             }
    711             return result;
    712         }
    713651    }
    714652
     
    814752    }
    815753
    816     private Collection<TestError> getErrorsForPrimitive(OsmPrimitive p, boolean includeOtherSeverity,
     754    static Collection<TestError> getErrorsForPrimitive(OsmPrimitive p, boolean includeOtherSeverity,
    817755            Collection<Set<TagCheck>> checksCol) {
    818756        // this variant is only used by the assertion tests
     
    877815            // Check assertions, useful for development of local files
    878816            if (Config.getPref().getBoolean("validator.check_assert_local_rules", false) && Utils.isLocalUrl(url)) {
    879                 for (String msg : checkAsserts(result.parseChecks)) {
     817                for (String msg : MapCSSTagCheckerAsserts.checkAsserts(result.parseChecks)) {
    880818                    Logging.warn(msg);
    881819                }
     
    912850            }
    913851        }
    914     }
    915 
    916     private static Method getFunctionMethod(String method) {
    917         try {
    918             return Functions.class.getDeclaredMethod(method, Environment.class, String.class);
    919         } catch (NoSuchMethodException | SecurityException e) {
    920             Logging.error(e);
    921             return null;
    922         }
    923     }
    924 
    925     private static Optional<String> getFirstInsideCountry(TagCheck check, Method insideMethod) {
    926         return check.rule.selectors.stream()
    927                 .filter(s -> s instanceof GeneralSelector)
    928                 .flatMap(s -> ((GeneralSelector) s).getConditions().stream())
    929                 .filter(c -> c instanceof ExpressionCondition)
    930                 .map(c -> ((ExpressionCondition) c).getExpression())
    931                 .filter(c -> c instanceof ParameterFunction)
    932                 .map(c -> (ParameterFunction) c)
    933                 .filter(c -> c.getMethod().equals(insideMethod))
    934                 .flatMap(c -> c.getArgs().stream())
    935                 .filter(e -> e instanceof LiteralExpression)
    936                 .map(e -> ((LiteralExpression) e).getLiteral())
    937                 .filter(l -> l instanceof String)
    938                 .map(l -> ((String) l).split(",")[0])
    939                 .findFirst();
    940     }
    941 
    942     private static LatLon getLocation(TagCheck check, Method insideMethod) {
    943         Optional<String> inside = getFirstInsideCountry(check, insideMethod);
    944         if (inside.isPresent()) {
    945             GeoPropertyIndex<Boolean> index = Territories.getGeoPropertyIndex(inside.get());
    946             if (index != null) {
    947                 GeoProperty<Boolean> prop = index.getGeoProperty();
    948                 if (prop instanceof DefaultGeoProperty) {
    949                     return ((DefaultGeoProperty) prop).getRandomLatLon();
    950                 }
    951             }
    952         }
    953         return LatLon.ZERO;
    954     }
    955 
    956     /**
    957      * Checks that rule assertions are met for the given set of TagChecks.
    958      * @param schecks The TagChecks for which assertions have to be checked
    959      * @return A set of error messages, empty if all assertions are met
    960      * @since 7356
    961      */
    962     public Set<String> checkAsserts(final Collection<TagCheck> schecks) {
    963         Set<String> assertionErrors = new LinkedHashSet<>();
    964         final Method insideMethod = getFunctionMethod("inside");
    965         final DataSet ds = new DataSet();
    966         for (final TagCheck check : schecks) {
    967             Logging.debug("Check: {0}", check);
    968             for (final Map.Entry<String, Boolean> i : check.assertions.entrySet()) {
    969                 Logging.debug("- Assertion: {0}", i);
    970                 final OsmPrimitive p = OsmUtils.createPrimitive(i.getKey(), getLocation(check, insideMethod), true);
    971                 // Build minimal ordered list of checks to run to test the assertion
    972                 List<Set<TagCheck>> checksToRun = new ArrayList<>();
    973                 Set<TagCheck> checkDependencies = check.getTagCheckDependencies(schecks);
    974                 if (!checkDependencies.isEmpty()) {
    975                     checksToRun.add(checkDependencies);
    976                 }
    977                 checksToRun.add(Collections.singleton(check));
    978                 // Add primitive to dataset to avoid DataIntegrityProblemException when evaluating selectors
    979                 addPrimitive(ds, p);
    980                 final Collection<TestError> pErrors = getErrorsForPrimitive(p, true, checksToRun);
    981                 Logging.debug("- Errors: {0}", pErrors);
    982                 final boolean isError = pErrors.stream().anyMatch(e -> e.getTester() instanceof MapCSSTagCheckerAndRule
    983                         && ((MapCSSTagCheckerAndRule) e.getTester()).rule.equals(check.rule));
    984                 if (isError != i.getValue()) {
    985                     assertionErrors.add(MessageFormat.format("Expecting test ''{0}'' (i.e., {1}) to {2} {3} (i.e., {4})",
    986                             check.getMessage(p), check.rule.selectors, i.getValue() ? "match" : "not match", i.getKey(), p.getKeys()));
    987                 }
    988                 if (isError) {
    989                     // Check that autofix works as expected
    990                     Command fix = check.fixPrimitive(p);
    991                     if (fix != null && fix.executeCommand() && !getErrorsForPrimitive(p, true, checksToRun).isEmpty()) {
    992                         assertionErrors.add(MessageFormat.format("Autofix does not work for test ''{0}'' (i.e., {1})",
    993                                 check.getMessage(p), check.rule.selectors));
    994                     }
    995                 }
    996                 ds.removePrimitive(p);
    997             }
    998         }
    999         return assertionErrors;
    1000     }
    1001 
    1002     private static void addPrimitive(DataSet ds, OsmPrimitive p) {
    1003         if (p instanceof Way) {
    1004             ((Way) p).getNodes().forEach(n -> addPrimitive(ds, n));
    1005         } else if (p instanceof Relation) {
    1006             ((Relation) p).getMembers().forEach(m -> addPrimitive(ds, m.getMember()));
    1007         }
    1008         ds.addPrimitive(p);
    1009852    }
    1010853
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java

    r15959 r15979  
    185185        Set<String> assertionErrors = new LinkedHashSet<>();
    186186        for (Set<TagCheck> schecks : c.checks.values()) {
    187             assertionErrors.addAll(c.checkAsserts(schecks));
     187            assertionErrors.addAll(MapCSSTagCheckerAsserts.checkAsserts(schecks));
    188188        }
    189189        for (String msg : assertionErrors) {
     
    205205                "  assertNoMatch: \"node amenity=restaurant\";\n" +
    206206                "}");
    207         Set<String> errors = test.checkAsserts(test.checks.get("test"));
     207        Set<String> errors = MapCSSTagCheckerAsserts.checkAsserts(test.checks.get("test"));
    208208        assertTrue(errors.toString(), errors.isEmpty());
    209209    }
     
    221221                "  assertNoMatch: \"way name=Hauptstrasse\";\n" +
    222222                "}");
    223         Set<String> errors = test.checkAsserts(test.checks.get("test"));
     223        Set<String> errors = MapCSSTagCheckerAsserts.checkAsserts(test.checks.get("test"));
    224224        assertTrue(errors.toString(), errors.isEmpty());
    225225    }
Note: See TracChangeset for help on using the changeset viewer.