Changeset 10837 in josm


Ignore:
Timestamp:
2016-08-18T03:39:22+02:00 (8 years ago)
Author:
Don-vip
Message:

see #11924 - extract MapCSS conditions to new class ConditionFactory (on the same model than ExpressionFactory) - should workaround Groovy bug with Java 9 (https://issues.apache.org/jira/browse/GROOVY-7879 ?)

Location:
trunk
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/scripts/TagInfoExtract.groovy

    r10769 r10837  
    3232import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference
    3333import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource
    34 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition
     34import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition
    3535import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector
    3636import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r10729 r10837  
    4848import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    4949import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    50 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ClassCondition;
     50import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition;
    5151import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    5252import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java

    r10717 r10837  
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
    4 import java.lang.reflect.InvocationTargetException;
    5 import java.lang.reflect.Method;
    6 import java.text.MessageFormat;
    7 import java.util.Arrays;
    8 import java.util.EnumSet;
    9 import java.util.Map;
    10 import java.util.Objects;
    11 import java.util.Set;
    12 import java.util.function.BiFunction;
    13 import java.util.function.IntFunction;
    14 import java.util.function.Predicate;
    15 import java.util.regex.Pattern;
    16 
    17 import org.openstreetmap.josm.Main;
    18 import org.openstreetmap.josm.actions.search.SearchCompiler.InDataSourceArea;
    19 import org.openstreetmap.josm.data.osm.Node;
    204import org.openstreetmap.josm.data.osm.OsmPrimitive;
    21 import org.openstreetmap.josm.data.osm.OsmUtils;
    22 import org.openstreetmap.josm.data.osm.Relation;
    235import org.openstreetmap.josm.data.osm.Tag;
    24 import org.openstreetmap.josm.data.osm.Way;
    25 import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
    26 import org.openstreetmap.josm.gui.mappaint.Cascade;
    27 import org.openstreetmap.josm.gui.mappaint.ElemStyles;
    286import org.openstreetmap.josm.gui.mappaint.Environment;
    29 import org.openstreetmap.josm.tools.CheckParameterUtil;
    30 import org.openstreetmap.josm.tools.Utils;
    317
    328/**
     
    4218     */
    4319    boolean applies(Environment e);
    44 
    45     /**
    46      * Create a new condition that checks the key and the value of the object.
    47      * @param k The key.
    48      * @param v The reference value
    49      * @param op The operation to use when comparing the value
    50      * @param context The type of context to use.
    51      * @param considerValAsKey whether to consider {@code v} as another key and compare the values of key {@code k} and key {@code v}.
    52      * @return The new condition.
    53      */
    54     static Condition createKeyValueCondition(String k, String v, Op op, Context context, boolean considerValAsKey) {
    55         switch (context) {
    56         case PRIMITIVE:
    57             if (KeyValueRegexpCondition.SUPPORTED_OPS.contains(op) && !considerValAsKey)
    58                 return new KeyValueRegexpCondition(k, v, op, false);
    59             if (!considerValAsKey && op.equals(Op.EQ))
    60                 return new SimpleKeyValueCondition(k, v);
    61             return new KeyValueCondition(k, v, op, considerValAsKey);
    62         case LINK:
    63             if (considerValAsKey)
    64                 throw new MapCSSException("''considerValAsKey'' not supported in LINK context");
    65             if ("role".equalsIgnoreCase(k))
    66                 return new RoleCondition(v, op);
    67             else if ("index".equalsIgnoreCase(k))
    68                 return new IndexCondition(v, op);
    69             else
    70                 throw new MapCSSException(
    71                         MessageFormat.format("Expected key ''role'' or ''index'' in link context. Got ''{0}''.", k));
    72 
    73         default: throw new AssertionError();
    74         }
    75     }
    76 
    77     /**
    78      * Create a condition in which the key and the value need to match a given regexp
    79      * @param k The key regexp
    80      * @param v The value regexp
    81      * @param op The operation to use when comparing the key and the value.
    82      * @return The new condition.
    83      */
    84     static Condition createRegexpKeyRegexpValueCondition(String k, String v, Op op) {
    85         return new RegexpKeyValueRegexpCondition(k, v, op);
    86     }
    87 
    88     /**
    89      * Creates a condition that checks the given key.
    90      * @param k The key to test for
    91      * @param not <code>true</code> to invert the match
    92      * @param matchType The match type to check for.
    93      * @param context The context this rule is found in.
    94      * @return the new condition.
    95      */
    96     static Condition createKeyCondition(String k, boolean not, KeyMatchType matchType, Context context) {
    97         switch (context) {
    98         case PRIMITIVE:
    99             return new KeyCondition(k, not, matchType);
    100         case LINK:
    101             if (matchType != null)
    102                 throw new MapCSSException("Question mark operator ''?'' and regexp match not supported in LINK context");
    103             if (not)
    104                 return new RoleCondition(k, Op.NEQ);
    105             else
    106                 return new RoleCondition(k, Op.EQ);
    107 
    108         default: throw new AssertionError();
    109         }
    110     }
    111 
    112     /**
    113      * Create a new pseudo class condition
    114      * @param id The id of the pseudo class
    115      * @param not <code>true</code> to invert the condition
    116      * @param context The context the class is found in.
    117      * @return The new condition
    118      */
    119     static PseudoClassCondition createPseudoClassCondition(String id, boolean not, Context context) {
    120         return PseudoClassCondition.createPseudoClassCondition(id, not, context);
    121     }
    122 
    123     /**
    124      * Create a new class condition
    125      * @param id The id of the class to match
    126      * @param not <code>true</code> to invert the condition
    127      * @param context Ignored
    128      * @return The new condition
    129      */
    130     static ClassCondition createClassCondition(String id, boolean not, Context context) {
    131         return new ClassCondition(id, not);
    132     }
    133 
    134     /**
    135      * Create a new condition that a expression needs to be fulfilled
    136      * @param e the expression to check
    137      * @param context Ignored
    138      * @return The new condition
    139      */
    140     static ExpressionCondition createExpressionCondition(Expression e, Context context) {
    141         return new ExpressionCondition(e);
    142     }
    143 
    144     /**
    145      * This is the operation that {@link KeyValueCondition} uses to match.
    146      */
    147     enum Op {
    148         /** The value equals the given reference. */
    149         EQ(Objects::equals),
    150         /** The value does not equal the reference. */
    151         NEQ(EQ),
    152         /** The value is greater than or equal to the given reference value (as float). */
    153         GREATER_OR_EQUAL(comparisonResult -> comparisonResult >= 0),
    154         /** The value is greater than the given reference value (as float). */
    155         GREATER(comparisonResult -> comparisonResult > 0),
    156         /** The value is less than or equal to the given reference value (as float). */
    157         LESS_OR_EQUAL(comparisonResult -> comparisonResult <= 0),
    158         /** The value is less than the given reference value (as float). */
    159         LESS(comparisonResult -> comparisonResult < 0),
    160         /** The reference is treated as regular expression and the value needs to match it. */
    161         REGEX((test, prototype) -> Pattern.compile(prototype).matcher(test).find()),
    162         /** The reference is treated as regular expression and the value needs to not match it. */
    163         NREGEX(REGEX),
    164         /** The reference is treated as a list separated by ';'. Spaces around the ; are ignored.
    165          *  The value needs to be equal one of the list elements. */
    166         ONE_OF((test, prototype) -> Arrays.asList(test.split("\\s*;\\s*")).contains(prototype)),
    167         /** The value needs to begin with the reference string. */
    168         BEGINS_WITH(String::startsWith),
    169         /** The value needs to end with the reference string. */
    170         ENDS_WITH(String::endsWith),
    171         /** The value needs to contain the reference string. */
    172         CONTAINS(String::contains);
    173 
    174         static final Set<Op> NEGATED_OPS = EnumSet.of(NEQ, NREGEX);
    175 
    176         private final BiFunction<String, String, Boolean> function;
    177 
    178         private final boolean negated;
    179 
    180         /**
    181          * Create a new string operation.
    182          * @param func The function to apply during {@link #eval(String, String)}.
    183          */
    184         Op(BiFunction<String, String, Boolean> func) {
    185             this.function = func;
    186             negated = false;
    187         }
    188 
    189         /**
    190          * Create a new float operation that compares two float values
    191          * @param comparatorResult A function to mapt the result of the comparison
    192          */
    193         Op(IntFunction<Boolean> comparatorResult) {
    194             this.function = (test, prototype) -> {
    195                 float testFloat;
    196                 try {
    197                     testFloat = Float.parseFloat(test);
    198                 } catch (NumberFormatException e) {
    199                     return false;
    200                 }
    201                 float prototypeFloat = Float.parseFloat(prototype);
    202 
    203                 int res = Float.compare(testFloat, prototypeFloat);
    204                 return comparatorResult.apply(res);
    205             };
    206             negated = false;
    207         }
    208 
    209         /**
    210          * Create a new Op by negating an other op.
    211          * @param negate inverse operation
    212          */
    213         Op(Op negate) {
    214             this.function = (a, b) -> !negate.function.apply(a, b);
    215             negated = true;
    216         }
    217 
    218         /**
    219          * Evaluates a value against a reference string.
    220          * @param testString The value. May be <code>null</code>
    221          * @param prototypeString The reference string-
    222          * @return <code>true</code> if and only if this operation matches for the given value/reference pair.
    223          */
    224         public boolean eval(String testString, String prototypeString) {
    225             if (testString == null)
    226                 return negated;
    227             else
    228                 return function.apply(testString, prototypeString);
    229         }
    230     }
    23120
    23221    /**
     
    24635
    24736    /**
    248      * Most common case of a KeyValueCondition, this is the basic key=value case.
    249      *
    250      * Extra class for performance reasons.
    251      */
    252     class SimpleKeyValueCondition implements Condition, ToTagConvertable {
    253         /**
    254          * The key to search for.
    255          */
    256         public final String k;
    257         /**
    258          * The value to search for.
    259          */
    260         public final String v;
    261 
    262         /**
    263          * Create a new SimpleKeyValueCondition.
    264          * @param k The key
    265          * @param v The value.
    266          */
    267         public SimpleKeyValueCondition(String k, String v) {
    268             this.k = k;
    269             this.v = v;
    270         }
    271 
    272         @Override
    273         public boolean applies(Environment e) {
    274             return v.equals(e.osm.get(k));
    275         }
    276 
    277         @Override
    278         public Tag asTag(OsmPrimitive primitive) {
    279             return new Tag(k, v);
    280         }
    281 
    282         @Override
    283         public String toString() {
    284             return '[' + k + '=' + v + ']';
    285         }
    286 
    287     }
    288 
    289     /**
    290      * <p>Represents a key/value condition which is either applied to a primitive.</p>
    291      *
    292      */
    293     class KeyValueCondition implements Condition, ToTagConvertable {
    294         /**
    295          * The key to search for.
    296          */
    297         public final String k;
    298         /**
    299          * The value to search for.
    300          */
    301         public final String v;
    302         /**
    303          * The key/value match operation.
    304          */
    305         public final Op op;
    306         /**
    307          * If this flag is set, {@link #v} is treated as a key and the value is the value set for that key.
    308          */
    309         public final boolean considerValAsKey;
    310 
    311         /**
    312          * <p>Creates a key/value-condition.</p>
    313          *
    314          * @param k the key
    315          * @param v the value
    316          * @param op the operation
    317          * @param considerValAsKey whether to consider {@code v} as another key and compare the values of key {@code k} and key {@code v}.
    318          */
    319         public KeyValueCondition(String k, String v, Op op, boolean considerValAsKey) {
    320             this.k = k;
    321             this.v = v;
    322             this.op = op;
    323             this.considerValAsKey = considerValAsKey;
    324         }
    325 
    326         @Override
    327         public boolean applies(Environment env) {
    328             return op.eval(env.osm.get(k), considerValAsKey ? env.osm.get(v) : v);
    329         }
    330 
    331         @Override
    332         public Tag asTag(OsmPrimitive primitive) {
    333             return new Tag(k, v);
    334         }
    335 
    336         @Override
    337         public String toString() {
    338             return '[' + k + '\'' + op + '\'' + v + ']';
    339         }
    340     }
    341 
    342     /**
    343      * This condition requires a fixed key to match a given regexp
    344      */
    345     class KeyValueRegexpCondition extends KeyValueCondition {
    346         protected static final Set<Op> SUPPORTED_OPS = EnumSet.of(Op.REGEX, Op.NREGEX);
    347 
    348         final Pattern pattern;
    349 
    350         public KeyValueRegexpCondition(String k, String v, Op op, boolean considerValAsKey) {
    351             super(k, v, op, considerValAsKey);
    352             CheckParameterUtil.ensureThat(!considerValAsKey, "considerValAsKey is not supported");
    353             CheckParameterUtil.ensureThat(SUPPORTED_OPS.contains(op), "Op must be REGEX or NREGEX");
    354             this.pattern = Pattern.compile(v);
    355         }
    356 
    357         protected boolean matches(Environment env) {
    358             final String value = env.osm.get(k);
    359             return value != null && pattern.matcher(value).find();
    360         }
    361 
    362         @Override
    363         public boolean applies(Environment env) {
    364             if (Op.REGEX.equals(op)) {
    365                 return matches(env);
    366             } else if (Op.NREGEX.equals(op)) {
    367                 return !matches(env);
    368             } else {
    369                 throw new IllegalStateException();
    370             }
    371         }
    372     }
    373 
    374     /**
    375      * A condition that checks that a key with the matching pattern has a value with the matching pattern.
    376      */
    377     class RegexpKeyValueRegexpCondition extends KeyValueRegexpCondition {
    378 
    379         public final Pattern keyPattern;
    380 
    381         /**
    382          * Create a condition in which the key and the value need to match a given regexp
    383          * @param k The key regexp
    384          * @param v The value regexp
    385          * @param op The operation to use when comparing the key and the value.
    386          */
    387         public RegexpKeyValueRegexpCondition(String k, String v, Op op) {
    388             super(k, v, op, false);
    389             this.keyPattern = Pattern.compile(k);
    390         }
    391 
    392         @Override
    393         protected boolean matches(Environment env) {
    394             for (Map.Entry<String, String> kv: env.osm.getKeys().entrySet()) {
    395                 if (keyPattern.matcher(kv.getKey()).find() && pattern.matcher(kv.getValue()).find()) {
    396                     return true;
    397                 }
    398             }
    399             return false;
    400         }
    401     }
    402 
    403     class RoleCondition implements Condition {
    404         public final String role;
    405         public final Op op;
    406 
    407         public RoleCondition(String role, Op op) {
    408             this.role = role;
    409             this.op = op;
    410         }
    411 
    412         @Override
    413         public boolean applies(Environment env) {
    414             String testRole = env.getRole();
    415             if (testRole == null) return false;
    416             return op.eval(testRole, role);
    417         }
    418     }
    419 
    420     class IndexCondition implements Condition {
    421         public final String index;
    422         public final Op op;
    423 
    424         public IndexCondition(String index, Op op) {
    425             this.index = index;
    426             this.op = op;
    427         }
    428 
    429         @Override
    430         public boolean applies(Environment env) {
    431             if (env.index == null) return false;
    432             if (index.startsWith("-")) {
    433                 return env.count != null && op.eval(Integer.toString(env.index - env.count), index);
    434             } else {
    435                 return op.eval(Integer.toString(env.index + 1), index);
    436             }
    437         }
    438     }
    439 
    440     /**
    441      * This defines how {@link KeyCondition} matches a given key.
    442      */
    443     enum KeyMatchType {
    444         /**
    445          * The key needs to be equal to the given label.
    446          */
    447         EQ,
    448         /**
    449          * The key needs to have a true value (yes, ...)
    450          * @see OsmUtils#isTrue(String)
    451          */
    452         TRUE,
    453         /**
    454          * The key needs to have a false value (no, ...)
    455          * @see OsmUtils#isFalse(String)
    456          */
    457         FALSE,
    458         /**
    459          * The key needs to match the given regular expression.
    460          */
    461         REGEX
    462     }
    463 
    464     /**
    465      * <p>KeyCondition represent one of the following conditions in either the link or the
    466      * primitive context:</p>
    467      * <pre>
    468      *     ["a label"]  PRIMITIVE:   the primitive has a tag "a label"
    469      *                  LINK:        the parent is a relation and it has at least one member with the role
    470      *                               "a label" referring to the child
    471      *
    472      *     [!"a label"]  PRIMITIVE:  the primitive doesn't have a tag "a label"
    473      *                   LINK:       the parent is a relation but doesn't have a member with the role
    474      *                               "a label" referring to the child
    475      *
    476      *     ["a label"?]  PRIMITIVE:  the primitive has a tag "a label" whose value evaluates to a true-value
    477      *                   LINK:       not supported
    478      *
    479      *     ["a label"?!] PRIMITIVE:  the primitive has a tag "a label" whose value evaluates to a false-value
    480      *                   LINK:       not supported
    481      * </pre>
    482      */
    483     class KeyCondition implements Condition, ToTagConvertable {
    484 
    485         /**
    486          * The key name.
    487          */
    488         public final String label;
    489         /**
    490          * If we should negate the result of the match.
    491          */
    492         public final boolean negateResult;
    493         /**
    494          * Describes how to match the label against the key.
    495          * @see KeyMatchType
    496          */
    497         public final KeyMatchType matchType;
    498         /**
    499          * A predicate used to match a the regexp against the key. Only used if the match type is regexp.
    500          */
    501         public final Predicate<String> containsPattern;
    502 
    503         /**
    504          * Creates a new KeyCondition
    505          * @param label The key name (or regexp) to use.
    506          * @param negateResult If we should negate the result.,
    507          * @param matchType The match type.
    508          */
    509         public KeyCondition(String label, boolean negateResult, KeyMatchType matchType) {
    510             this.label = label;
    511             this.negateResult = negateResult;
    512             this.matchType = matchType == null ? KeyMatchType.EQ : matchType;
    513             this.containsPattern = KeyMatchType.REGEX.equals(matchType)
    514                     ? Pattern.compile(label).asPredicate()
    515                     : null;
    516         }
    517 
    518         @Override
    519         public boolean applies(Environment e) {
    520             switch(e.getContext()) {
    521             case PRIMITIVE:
    522                 switch (matchType) {
    523                 case TRUE:
    524                     return e.osm.isKeyTrue(label) ^ negateResult;
    525                 case FALSE:
    526                     return e.osm.isKeyFalse(label) ^ negateResult;
    527                 case REGEX:
    528                     return e.osm.keySet().stream().anyMatch(containsPattern) ^ negateResult;
    529                 default:
    530                     return e.osm.hasKey(label) ^ negateResult;
    531                 }
    532             case LINK:
    533                 Utils.ensure(false, "Illegal state: KeyCondition not supported in LINK context");
    534                 return false;
    535             default: throw new AssertionError();
    536             }
    537         }
    538 
    539         /**
    540          * Get the matched key and the corresponding value.
    541          * <p>
    542          * WARNING: This ignores {@link #negateResult}.
    543          * <p>
    544          * WARNING: For regexp, the regular expression is returned instead of a key if the match failed.
    545          * @param p The primitive to get the value from.
    546          * @return The tag.
    547          */
    548         @Override
    549         public Tag asTag(OsmPrimitive p) {
    550             String key = label;
    551             if (KeyMatchType.REGEX.equals(matchType)) {
    552                 key = p.keySet().stream().filter(containsPattern).findAny().orElse(key);
    553             }
    554             return new Tag(key, p.get(key));
    555         }
    556 
    557         @Override
    558         public String toString() {
    559             return '[' + (negateResult ? "!" : "") + label + ']';
    560         }
    561     }
    562 
    563     class ClassCondition implements Condition {
    564 
    565         public final String id;
    566         public final boolean not;
    567 
    568         public ClassCondition(String id, boolean not) {
    569             this.id = id;
    570             this.not = not;
    571         }
    572 
    573         @Override
    574         public boolean applies(Environment env) {
    575             Cascade cascade = env.getCascade(env.layer);
    576             return cascade != null && (not ^ cascade.containsKey(id));
    577         }
    578 
    579         @Override
    580         public String toString() {
    581             return (not ? "!" : "") + '.' + id;
    582         }
    583     }
    584 
    585     /**
    586      * Like <a href="http://www.w3.org/TR/css3-selectors/#pseudo-classes">CSS pseudo classes</a>, MapCSS pseudo classes
    587      * are written in lower case with dashes between words.
    588      */
    589     final class PseudoClasses {
    590 
    591         private PseudoClasses() {
    592             // Hide default constructor for utilities classes
    593         }
    594 
    595         /**
    596          * {@code closed} tests whether the way is closed or the relation is a closed multipolygon
    597          * @param e MapCSS environment
    598          * @return {@code true} if the way is closed or the relation is a closed multipolygon
    599          */
    600         static boolean closed(Environment e) { // NO_UCD (unused code)
    601             if (e.osm instanceof Way && ((Way) e.osm).isClosed())
    602                 return true;
    603             if (e.osm instanceof Relation && ((Relation) e.osm).isMultipolygon())
    604                 return true;
    605             return false;
    606         }
    607 
    608         /**
    609          * {@code :modified} tests whether the object has been modified.
    610          * @param e MapCSS environment
    611          * @return {@code true} if the object has been modified
    612          * @see OsmPrimitive#isModified()
    613          */
    614         static boolean modified(Environment e) { // NO_UCD (unused code)
    615             return e.osm.isModified() || e.osm.isNewOrUndeleted();
    616         }
    617 
    618         /**
    619          * {@code ;new} tests whether the object is new.
    620          * @param e MapCSS environment
    621          * @return {@code true} if the object is new
    622          * @see OsmPrimitive#isNew()
    623          */
    624         static boolean _new(Environment e) { // NO_UCD (unused code)
    625             return e.osm.isNew();
    626         }
    627 
    628         /**
    629          * {@code :connection} tests whether the object is a connection node.
    630          * @param e MapCSS environment
    631          * @return {@code true} if the object is a connection node
    632          * @see Node#isConnectionNode()
    633          */
    634         static boolean connection(Environment e) { // NO_UCD (unused code)
    635             return e.osm instanceof Node && e.osm.getDataSet() != null && ((Node) e.osm).isConnectionNode();
    636         }
    637 
    638         /**
    639          * {@code :tagged} tests whether the object is tagged.
    640          * @param e MapCSS environment
    641          * @return {@code true} if the object is tagged
    642          * @see OsmPrimitive#isTagged()
    643          */
    644         static boolean tagged(Environment e) { // NO_UCD (unused code)
    645             return e.osm.isTagged();
    646         }
    647 
    648         /**
    649          * {@code :same-tags} tests whether the object has the same tags as its child/parent.
    650          * @param e MapCSS environment
    651          * @return {@code true} if the object has the same tags as its child/parent
    652          * @see OsmPrimitive#hasSameInterestingTags(OsmPrimitive)
    653          */
    654         static boolean sameTags(Environment e) { // NO_UCD (unused code)
    655             return e.osm.hasSameInterestingTags(Utils.firstNonNull(e.child, e.parent));
    656         }
    657 
    658         /**
    659          * {@code :area-style} tests whether the object has an area style. This is useful for validators.
    660          * @param e MapCSS environment
    661          * @return {@code true} if the object has an area style
    662          * @see ElemStyles#hasAreaElemStyle(OsmPrimitive, boolean)
    663          */
    664         static boolean areaStyle(Environment e) { // NO_UCD (unused code)
    665             // only for validator
    666             return ElemStyles.hasAreaElemStyle(e.osm, false);
    667         }
    668 
    669         /**
    670          * {@code unconnected}: tests whether the object is a unconnected node.
    671          * @param e MapCSS environment
    672          * @return {@code true} if the object is a unconnected node
    673          */
    674         static boolean unconnected(Environment e) { // NO_UCD (unused code)
    675             return e.osm instanceof Node && OsmPrimitive.getFilteredList(e.osm.getReferrers(), Way.class).isEmpty();
    676         }
    677 
    678         /**
    679          * {@code righthandtraffic} checks if there is right-hand traffic at the current location.
    680          * @param e MapCSS environment
    681          * @return {@code true} if there is right-hand traffic at the current location
    682          * @see ExpressionFactory.Functions#is_right_hand_traffic(Environment)
    683          */
    684         static boolean righthandtraffic(Environment e) { // NO_UCD (unused code)
    685             return ExpressionFactory.Functions.is_right_hand_traffic(e);
    686         }
    687 
    688         /**
    689          * {@code clockwise} whether the way is closed and oriented clockwise,
    690          * or non-closed and the 1st, 2nd and last node are in clockwise order.
    691          * @param e MapCSS environment
    692          * @return {@code true} if the way clockwise
    693          * @see ExpressionFactory.Functions#is_clockwise(Environment)
    694          */
    695         static boolean clockwise(Environment e) { // NO_UCD (unused code)
    696             return ExpressionFactory.Functions.is_clockwise(e);
    697         }
    698 
    699         /**
    700          * {@code anticlockwise} whether the way is closed and oriented anticlockwise,
    701          * or non-closed and the 1st, 2nd and last node are in anticlockwise order.
    702          * @param e MapCSS environment
    703          * @return {@code true} if the way clockwise
    704          * @see ExpressionFactory.Functions#is_anticlockwise(Environment)
    705          */
    706         static boolean anticlockwise(Environment e) { // NO_UCD (unused code)
    707             return ExpressionFactory.Functions.is_anticlockwise(e);
    708         }
    709 
    710         /**
    711          * {@code unclosed-multipolygon} tests whether the object is an unclosed multipolygon.
    712          * @param e MapCSS environment
    713          * @return {@code true} if the object is an unclosed multipolygon
    714          */
    715         static boolean unclosed_multipolygon(Environment e) { // NO_UCD (unused code)
    716             return e.osm instanceof Relation && ((Relation) e.osm).isMultipolygon() &&
    717                     !e.osm.isIncomplete() && !((Relation) e.osm).hasIncompleteMembers() &&
    718                     !MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) e.osm).getOpenEnds().isEmpty();
    719         }
    720 
    721         private static final Predicate<OsmPrimitive> IN_DOWNLOADED_AREA = new InDataSourceArea(false);
    722 
    723         /**
    724          * {@code in-downloaded-area} tests whether the object is within source area ("downloaded area").
    725          * @param e MapCSS environment
    726          * @return {@code true} if the object is within source area ("downloaded area")
    727          * @see InDataSourceArea
    728          */
    729         static boolean inDownloadedArea(Environment e) { // NO_UCD (unused code)
    730             return IN_DOWNLOADED_AREA.test(e.osm);
    731         }
    732 
    733         static boolean completely_downloaded(Environment e) { // NO_UCD (unused code)
    734             if (e.osm instanceof Relation) {
    735                 return !((Relation) e.osm).hasIncompleteMembers();
    736             } else {
    737                 return true;
    738             }
    739         }
    740 
    741         static boolean closed2(Environment e) { // NO_UCD (unused code)
    742             if (e.osm instanceof Way && ((Way) e.osm).isClosed())
    743                 return true;
    744             if (e.osm instanceof Relation && ((Relation) e.osm).isMultipolygon())
    745                 return MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) e.osm).getOpenEnds().isEmpty();
    746             return false;
    747         }
    748 
    749         static boolean selected(Environment e) { // NO_UCD (unused code)
    750             Cascade c = e.mc.getCascade(e.layer);
    751             c.setDefaultSelectedHandling(false);
    752             return e.osm.isSelected();
    753         }
    754     }
    755 
    756     class PseudoClassCondition implements Condition {
    757 
    758         public final Method method;
    759         public final boolean not;
    760 
    761         protected PseudoClassCondition(Method method, boolean not) {
    762             this.method = method;
    763             this.not = not;
    764         }
    765 
    766         /**
    767          * Create a new pseudo class condition
    768          * @param id The id of the pseudo class
    769          * @param not <code>true</code> to invert the condition
    770          * @param context The context the class is found in.
    771          * @return The new condition
    772          */
    773         public static PseudoClassCondition createPseudoClassCondition(String id, boolean not, Context context) {
    774             CheckParameterUtil.ensureThat(!"sameTags".equals(id) || Context.LINK.equals(context), "sameTags only supported in LINK context");
    775             if ("open_end".equals(id)) {
    776                 return new OpenEndPseudoClassCondition(not);
    777             }
    778             final Method method = getMethod(id);
    779             if (method != null) {
    780                 return new PseudoClassCondition(method, not);
    781             }
    782             throw new MapCSSException("Invalid pseudo class specified: " + id);
    783         }
    784 
    785         protected static Method getMethod(String id) {
    786             id = id.replaceAll("-|_", "");
    787             for (Method method : PseudoClasses.class.getDeclaredMethods()) {
    788                 // for backwards compatibility, consider :sameTags == :same-tags == :same_tags (#11150)
    789                 final String methodName = method.getName().replaceAll("-|_", "");
    790                 if (methodName.equalsIgnoreCase(id)) {
    791                     return method;
    792                 }
    793             }
    794             return null;
    795         }
    796 
    797         @Override
    798         public boolean applies(Environment e) {
    799             try {
    800                 return not ^ (Boolean) method.invoke(null, e);
    801             } catch (IllegalAccessException | InvocationTargetException ex) {
    802                 throw new RuntimeException(ex);
    803             }
    804         }
    805 
    806         @Override
    807         public String toString() {
    808             return (not ? "!" : "") + ':' + method.getName();
    809         }
    810     }
    811 
    812     class OpenEndPseudoClassCondition extends PseudoClassCondition {
    813         public OpenEndPseudoClassCondition(boolean not) {
    814             super(null, not);
    815         }
    816 
    817         @Override
    818         public boolean applies(Environment e) {
    819             return true;
    820         }
    821     }
    822 
    823     /**
    824      * A condition that is fulfilled whenever the expression is evaluated to be true.
    825      */
    826     class ExpressionCondition implements Condition {
    827 
    828         private final Expression e;
    829 
    830         /**
    831          * Constructs a new {@code ExpressionFactory}
    832          * @param e expression
    833          */
    834         public ExpressionCondition(Expression e) {
    835             this.e = e;
    836         }
    837 
    838         @Override
    839         public boolean applies(Environment env) {
    840             Boolean b = Cascade.convertTo(e.evaluate(env), Boolean.class);
    841             return b != null && b;
    842         }
    843 
    844         @Override
    845         public String toString() {
    846             return '[' + e.toString() + ']';
    847         }
    848     }
    849 
    850     /**
    85137     * This is a condition that can be converted to a tag
    85238     * @author Michael Zangl
    85339     * @since 10674
    85440     */
     41    @FunctionalInterface
    85542    public interface ToTagConvertable {
    85643        /**
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java

    r10748 r10837  
    4343
    4444/**
    45  * Factory to generate Expressions.
    46  *
     45 * Factory to generate {@link Expression}s.
     46 * <p>
    4747 * See {@link #createFunctionExpression}.
    4848 */
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj

    r9958 r10837  
    2222import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    2323import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
     24import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory;
     25import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyMatchType;
     26import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op;
    2427import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    2528import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory;
     
    744747            c=simple_key_value_condition(context) s() <RSQUARE> { return c; }
    745748        |
    746             e=expression() <RSQUARE> { return Condition.createExpressionCondition(e, context); }
     749            e=expression() <RSQUARE> { return ConditionFactory.createExpressionCondition(e, context); }
    747750    )
    748751}
     
    762765{
    763766    boolean not = false;
    764     Condition.KeyMatchType matchType = null;;
     767    KeyMatchType matchType = null;;
    765768    String key;
    766769}
     
    768771    ( <EXCLAMATION> { not = true; } )?
    769772    (
    770         { matchType = Condition.KeyMatchType.REGEX; } key = regex()
     773        { matchType = KeyMatchType.REGEX; } key = regex()
    771774    |
    772775        key = tag_key()
    773776    )
    774     ( LOOKAHEAD(2) <QUESTION> <EXCLAMATION> { matchType = Condition.KeyMatchType.FALSE; } )?
    775     (              <QUESTION>               { matchType = Condition.KeyMatchType.TRUE;  } )?
    776     { return Condition.createKeyCondition(key, not, matchType, context); }
     777    ( LOOKAHEAD(2) <QUESTION> <EXCLAMATION> { matchType = KeyMatchType.FALSE; } )?
     778    (              <QUESTION>               { matchType = KeyMatchType.TRUE;  } )?
     779    { return ConditionFactory.createKeyCondition(key, not, matchType, context); }
    777780}
    778781
     
    783786    float f;
    784787    int i;
    785     Condition.KeyMatchType matchType = null;;
    786     Condition.Op op;
     788    KeyMatchType matchType = null;;
     789    Op op;
    787790    boolean considerValAsKey = false;
    788791}
    789792{
    790793    (
    791         key = regex() s() { matchType = Condition.KeyMatchType.REGEX; }
     794        key = regex() s() { matchType = KeyMatchType.REGEX; }
    792795    |
    793796        key=tag_key() s()
     
    796799        LOOKAHEAD(3)
    797800            (
    798                     <EQUAL> <TILDE> { op=Condition.Op.REGEX; }
     801                    <EQUAL> <TILDE> { op=Op.REGEX; }
    799802                |
    800                     <EXCLAMATION> <TILDE> { op=Condition.Op.NREGEX; }
     803                    <EXCLAMATION> <TILDE> { op=Op.NREGEX; }
    801804            )
    802805            s()
     
    805808        |
    806809            (
    807                     <EXCLAMATION> <EQUAL> { op=Condition.Op.NEQ; }
     810                    <EXCLAMATION> <EQUAL> { op=Op.NEQ; }
    808811                |
    809                     <EQUAL> { op=Condition.Op.EQ; }
     812                    <EQUAL> { op=Op.EQ; }
    810813                |
    811                     <TILDE> <EQUAL> { op=Condition.Op.ONE_OF; }
     814                    <TILDE> <EQUAL> { op=Op.ONE_OF; }
    812815                |
    813                     <CARET> <EQUAL> { op=Condition.Op.BEGINS_WITH; }
     816                    <CARET> <EQUAL> { op=Op.BEGINS_WITH; }
    814817                |
    815                     <DOLLAR> <EQUAL> { op=Condition.Op.ENDS_WITH; }
     818                    <DOLLAR> <EQUAL> { op=Op.ENDS_WITH; }
    816819                |
    817                     <STAR> <EQUAL> { op=Condition.Op.CONTAINS; }
     820                    <STAR> <EQUAL> { op=Op.CONTAINS; }
    818821            )
    819822            s()
     
    829832        |
    830833            (
    831                     <GREATER_EQUAL> { op=Condition.Op.GREATER_OR_EQUAL; }
     834                    <GREATER_EQUAL> { op=Op.GREATER_OR_EQUAL; }
    832835                |
    833                     <GREATER> { op=Condition.Op.GREATER; }
     836                    <GREATER> { op=Op.GREATER; }
    834837                |
    835                     <LESS_EQUAL> { op=Condition.Op.LESS_OR_EQUAL; }
     838                    <LESS_EQUAL> { op=Op.LESS_OR_EQUAL; }
    836839                |
    837                     <LESS> { op=Condition.Op.LESS; }
     840                    <LESS> { op=Op.LESS; }
    838841            )
    839842            s()
    840843            f=float_() { val=Float.toString(f); }
    841844    )
    842     { return Condition.KeyMatchType.REGEX == matchType
    843             ? Condition.createRegexpKeyRegexpValueCondition(key, val, op)
    844             : Condition.createKeyValueCondition(key, val, op, context, considerValAsKey); }
     845    { return KeyMatchType.REGEX == matchType
     846            ? ConditionFactory.createRegexpKeyRegexpValueCondition(key, val, op)
     847            : ConditionFactory.createKeyValueCondition(key, val, op, context, considerValAsKey); }
    845848}
    846849
     
    860863    s=ident()
    861864    { return pseudo
    862         ? Condition.createPseudoClassCondition(s, not, context)
    863         : Condition.createClassCondition(s, not, context); }
     865        ? ConditionFactory.createPseudoClassCondition(s, not, context)
     866        : ConditionFactory.createClassCondition(s, not, context); }
    864867}
    865868
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r10268 r10837  
    4545import org.openstreetmap.josm.gui.mappaint.StyleSetting.BooleanStyleSetting;
    4646import org.openstreetmap.josm.gui.mappaint.StyleSource;
    47 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.KeyCondition;
    48 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.KeyMatchType;
    49 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.KeyValueCondition;
    50 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op;
    51 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition;
     47import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyCondition;
     48import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyMatchType;
     49import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyValueCondition;
     50import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op;
     51import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition;
    5252import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    5353import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

    r10715 r10837  
    2121import org.openstreetmap.josm.gui.mappaint.Environment;
    2222import org.openstreetmap.josm.gui.mappaint.Range;
     23import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.OpenEndPseudoClassCondition;
    2324import org.openstreetmap.josm.tools.CheckParameterUtil;
    2425import org.openstreetmap.josm.tools.Geometry;
     
    377378            } else if (ChildOrParentSelectorType.CHILD.equals(type)
    378379                    && link.conds != null && !link.conds.isEmpty()
    379                     && link.conds.get(0) instanceof Condition.OpenEndPseudoClassCondition) {
     380                    && link.conds.get(0) instanceof OpenEndPseudoClassCondition) {
    380381                if (e.osm instanceof Node) {
    381382                    e.osm.visitReferrers(new MultipolygonOpenEndFinder(e));
  • trunk/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSConditionPerformanceTest.java

    r10674 r10837  
    66import org.junit.Test;
    77import org.openstreetmap.josm.PerformanceTestUtils;
    8 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op;
     8import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op;
    99
    1010/**
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java

    r10674 r10837  
    1313import org.openstreetmap.josm.gui.mappaint.Environment;
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    15 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op;
    16 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition;
    1715import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable;
     16import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op;
     17import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition;
    1818import org.openstreetmap.josm.testutils.JOSMTestRules;
    1919
     
    5454    @Test
    5555    public void testKeyValueEq() {
    56         Condition op = Condition.createKeyValueCondition("k1", "v1", Op.EQ, Context.PRIMITIVE, false);
     56        Condition op = ConditionFactory.createKeyValueCondition("k1", "v1", Op.EQ, Context.PRIMITIVE, false);
    5757        assertFalse(op.applies(genEnv(node0)));
    5858        assertTrue(op.applies(genEnv(node1)));
     
    7272    @Test
    7373    public void testKeyValueEqAsKey() {
    74         Condition op = Condition.createKeyValueCondition("k1", "k2", Op.EQ, Context.PRIMITIVE, true);
     74        Condition op = ConditionFactory.createKeyValueCondition("k1", "k2", Op.EQ, Context.PRIMITIVE, true);
    7575        assertFalse(op.applies(genEnv(node0)));
    7676        assertTrue(op.applies(genEnv(node1)));
     
    8888    @Test
    8989    public void testKeyValueNeq() {
    90         Condition op = Condition.createKeyValueCondition("k1", "v1", Op.NEQ, Context.PRIMITIVE, false);
     90        Condition op = ConditionFactory.createKeyValueCondition("k1", "v1", Op.NEQ, Context.PRIMITIVE, false);
    9191        assertTrue(op.applies(genEnv(node0)));
    9292        assertFalse(op.applies(genEnv(node1)));
     
    101101    @Test
    102102    public void testKeyValueGreatherEq() {
    103         Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.GREATER_OR_EQUAL, Context.PRIMITIVE, false);
     103        Condition op = ConditionFactory.createKeyValueCondition("f1", "0.2", Op.GREATER_OR_EQUAL, Context.PRIMITIVE, false);
    104104        assertFalse(op.applies(genEnv(node0)));
    105105        assertTrue(op.applies(genEnv(node1)));
     
    114114    @Test
    115115    public void testKeyValueGreather() {
    116         Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.GREATER, Context.PRIMITIVE, false);
     116        Condition op = ConditionFactory.createKeyValueCondition("f1", "0.2", Op.GREATER, Context.PRIMITIVE, false);
    117117        assertFalse(op.applies(genEnv(node0)));
    118118        assertFalse(op.applies(genEnv(node1)));
     
    127127    @Test
    128128    public void testKeyValueLessEq() {
    129         Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.LESS_OR_EQUAL, Context.PRIMITIVE, false);
     129        Condition op = ConditionFactory.createKeyValueCondition("f1", "0.2", Op.LESS_OR_EQUAL, Context.PRIMITIVE, false);
    130130        assertFalse(op.applies(genEnv(node0)));
    131131        assertTrue(op.applies(genEnv(node1)));
     
    140140    @Test
    141141    public void testKeyValueLess() {
    142         Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.LESS, Context.PRIMITIVE, false);
     142        Condition op = ConditionFactory.createKeyValueCondition("f1", "0.2", Op.LESS, Context.PRIMITIVE, false);
    143143        assertFalse(op.applies(genEnv(node0)));
    144144        assertFalse(op.applies(genEnv(node1)));
     
    153153    @Test
    154154    public void testKeyValueRegex() {
    155         Condition op = Condition.createKeyValueCondition("r1", "(ab){2}", Op.REGEX, Context.PRIMITIVE, false);
     155        Condition op = ConditionFactory.createKeyValueCondition("r1", "(ab){2}", Op.REGEX, Context.PRIMITIVE, false);
    156156        assertFalse(op.applies(genEnv(node0)));
    157157        assertTrue(op.applies(genEnv(node1)));
     
    166166    @Test
    167167    public void testKeyValueNregex() {
    168         Condition op = Condition.createKeyValueCondition("r1", "(ab){2}", Op.NREGEX, Context.PRIMITIVE, false);
     168        Condition op = ConditionFactory.createKeyValueCondition("r1", "(ab){2}", Op.NREGEX, Context.PRIMITIVE, false);
    169169        assertTrue(op.applies(genEnv(node0)));
    170170        assertFalse(op.applies(genEnv(node1)));
     
    179179    @Test
    180180    public void testKeyValueOneOf() {
    181         Condition op = Condition.createKeyValueCondition("one", "a", Op.ONE_OF, Context.PRIMITIVE, false);
     181        Condition op = ConditionFactory.createKeyValueCondition("one", "a", Op.ONE_OF, Context.PRIMITIVE, false);
    182182        assertFalse(op.applies(genEnv(node0)));
    183183        assertTrue(op.applies(genEnv(node1)));
     
    192192    @Test
    193193    public void testKeyValueBeginsWith() {
    194         Condition op = Condition.createKeyValueCondition("c1", "xy", Op.BEGINS_WITH, Context.PRIMITIVE, false);
     194        Condition op = ConditionFactory.createKeyValueCondition("c1", "xy", Op.BEGINS_WITH, Context.PRIMITIVE, false);
    195195        assertFalse(op.applies(genEnv(node0)));
    196196        assertTrue(op.applies(genEnv(node1)));
     
    205205    @Test
    206206    public void testKeyValueEndsWith() {
    207         Condition op = Condition.createKeyValueCondition("c1", "xy", Op.ENDS_WITH, Context.PRIMITIVE, false);
     207        Condition op = ConditionFactory.createKeyValueCondition("c1", "xy", Op.ENDS_WITH, Context.PRIMITIVE, false);
    208208        assertFalse(op.applies(genEnv(node0)));
    209209        assertFalse(op.applies(genEnv(node1)));
     
    218218    @Test
    219219    public void testKeyValueContains() {
    220         Condition op = Condition.createKeyValueCondition("c1", "xy", Op.CONTAINS, Context.PRIMITIVE, false);
    221         assertFalse(op.applies(genEnv(node0)));
    222         assertTrue(op.applies(genEnv(node1)));
    223         assertTrue(op.applies(genEnv(node2)));
    224         assertTrue(op.applies(genEnv(node3)));
    225         assertTrue(op.applies(genEnv(node4)));
    226     }
    227 
    228     /**
    229      * Test of {@link Condition#createRegexpKeyRegexpValueCondition(String, String, Op)}
     220        Condition op = ConditionFactory.createKeyValueCondition("c1", "xy", Op.CONTAINS, Context.PRIMITIVE, false);
     221        assertFalse(op.applies(genEnv(node0)));
     222        assertTrue(op.applies(genEnv(node1)));
     223        assertTrue(op.applies(genEnv(node2)));
     224        assertTrue(op.applies(genEnv(node3)));
     225        assertTrue(op.applies(genEnv(node4)));
     226    }
     227
     228    /**
     229     * Test of {@link ConditionFactory#createRegexpKeyRegexpValueCondition(String, String, Op)}
    230230     */
    231231    @Test
    232232    public void testRegexpKeyValueRegexpCondition() {
    233         Condition op = Condition.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.REGEX);
    234         assertFalse(op.applies(genEnv(node0)));
    235         assertFalse(op.applies(genEnv(node1)));
    236         assertTrue(op.applies(genEnv(node2)));
    237         assertFalse(op.applies(genEnv(node3)));
    238         assertTrue(op.applies(genEnv(node4)));
    239 
    240         Condition notOp = Condition.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.NREGEX);
     233        Condition op = ConditionFactory.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.REGEX);
     234        assertFalse(op.applies(genEnv(node0)));
     235        assertFalse(op.applies(genEnv(node1)));
     236        assertTrue(op.applies(genEnv(node2)));
     237        assertFalse(op.applies(genEnv(node3)));
     238        assertTrue(op.applies(genEnv(node4)));
     239
     240        Condition notOp = ConditionFactory.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.NREGEX);
    241241        assertTrue(notOp.applies(genEnv(node0)));
    242242        assertTrue(notOp.applies(genEnv(node1)));
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyConditionTest.groovy

    r9214 r10837  
    1313import org.openstreetmap.josm.gui.mappaint.Environment
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context
     15import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyMatchType
    1516
    1617class KeyConditionTest {
     
    4748
    4849        // ["a label"]
    49         Condition c = Condition.createKeyCondition("a key", false, Condition.KeyMatchType.FALSE, Context.PRIMITIVE)
     50        Condition c = ConditionFactory.createKeyCondition("a key", false, KeyMatchType.FALSE, Context.PRIMITIVE)
    5051        // ["a label"?]
    51         c = Condition.createKeyCondition("a key", false, Condition.KeyMatchType.TRUE, Context.PRIMITIVE)
     52        c = ConditionFactory.createKeyCondition("a key", false, KeyMatchType.TRUE, Context.PRIMITIVE)
    5253        // [!"a label"]
    53         c = Condition.createKeyCondition("a key", true, Condition.KeyMatchType.FALSE, Context.PRIMITIVE)
     54        c = ConditionFactory.createKeyCondition("a key", true, KeyMatchType.FALSE, Context.PRIMITIVE)
    5455        // [!"a label"?]
    55         c = Condition.createKeyCondition("a key", true, Condition.KeyMatchType.TRUE, Context.PRIMITIVE)
     56        c = ConditionFactory.createKeyCondition("a key", true, KeyMatchType.TRUE, Context.PRIMITIVE)
    5657
    5758        // ["a label"]
    58         c = Condition.createKeyCondition("a key", false, null, Context.LINK)
     59        c = ConditionFactory.createKeyCondition("a key", false, null, Context.LINK)
    5960        // [!"a label"]
    60         c = Condition.createKeyCondition("a key", true, null, Context.LINK)
     61        c = ConditionFactory.createKeyCondition("a key", true, null, Context.LINK)
    6162
    6263        shouldFail(MapCSSException) {
    6364            // ["a label"?]
    64            c = Condition.createKeyCondition("a key", false, Condition.KeyMatchType.TRUE, Context.LINK)
     65           c = ConditionFactory.createKeyCondition("a key", false, KeyMatchType.TRUE, Context.LINK)
    6566        }
    6667
    6768        shouldFail(MapCSSException) {
    6869            // [!"a label"?]
    69             c = Condition.createKeyCondition("a key", true, Condition.KeyMatchType.TRUE, Context.LINK)
     70            c = ConditionFactory.createKeyCondition("a key", true, KeyMatchType.TRUE, Context.LINK)
    7071        }
    7172    }
     
    7980        Environment e = new Environment(n).withParent(r).withIndex(0, r.membersCount).withLinkContext()
    8081
    81         Condition cond = Condition.createKeyCondition("my_role", false, null, Context.LINK)
     82        Condition cond = ConditionFactory.createKeyCondition("my_role", false, null, Context.LINK)
    8283        assert cond.applies(e)
    8384
    84         cond = Condition.createKeyCondition("my_role", true, null, Context.LINK)
     85        cond = ConditionFactory.createKeyCondition("my_role", true, null, Context.LINK)
    8586        assert !cond.applies(e)
    8687    }
     
    9495        Environment e = new Environment(n).withParent(r).withIndex(0, r.membersCount).withLinkContext()
    9596
    96         Condition cond = Condition.createKeyCondition("another_role", false, null, Context.LINK)
     97        Condition cond = ConditionFactory.createKeyCondition("another_role", false, null, Context.LINK)
    9798        assert !cond.applies(e)
    9899
    99         cond = Condition.createKeyCondition("another_role", true, null, Context.LINK)
     100        cond = ConditionFactory.createKeyCondition("another_role", true, null, Context.LINK)
    100101        assert cond.applies(e)
    101102    }
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy

    r9247 r10837  
    1212import org.openstreetmap.josm.gui.mappaint.Environment
    1313import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context
    14 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op
     14import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op
    1515import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
    1616
     
    4747    @Test
    4848    public void create() {
    49         Condition c = Condition.createKeyValueCondition("a key", "a value", Op.EQ, Context.PRIMITIVE, false)
     49        Condition c = ConditionFactory.createKeyValueCondition("a key", "a value", Op.EQ, Context.PRIMITIVE, false)
    5050
    51         c = Condition.createKeyValueCondition("role", "a role", Op.EQ, Context.LINK, false)
    52         c = Condition.createKeyValueCondition("RoLe", "a role", Op.EQ, Context.LINK, false)
     51        c = ConditionFactory.createKeyValueCondition("role", "a role", Op.EQ, Context.LINK, false)
     52        c = ConditionFactory.createKeyValueCondition("RoLe", "a role", Op.EQ, Context.LINK, false)
    5353
    5454        shouldFail(MapCSSException) {
    55             c = Condition.createKeyValueCondition("an arbitry tag", "a role", Op.EQ, Context.LINK, false)
     55            c = ConditionFactory.createKeyValueCondition("an arbitry tag", "a role", Op.EQ, Context.LINK, false)
    5656        }
    5757    }
     
    6565        Environment e = new Environment(n).withParent(r).withLinkContext().withIndex(0, r.membersCount)
    6666
    67         Condition cond = new Condition.RoleCondition("my_role", Op.EQ)
     67        Condition cond = new ConditionFactory.RoleCondition("my_role", Op.EQ)
    6868        assert cond.applies(e)
    6969
    70         cond = new Condition.RoleCondition("another_role", Op.EQ)
     70        cond = new ConditionFactory.RoleCondition("another_role", Op.EQ)
    7171        assert !cond.applies(e)
    7272    }
     
    8080        Environment e = new Environment(n).withParent(r).withIndex(0, r.membersCount).withLinkContext()
    8181
    82         Condition cond = Condition.createKeyValueCondition("role", "my_role", Op.NEQ, Context.LINK, false)
     82        Condition cond = ConditionFactory.createKeyValueCondition("role", "my_role", Op.NEQ, Context.LINK, false)
    8383        assert !cond.applies(e)
    8484
    85         cond = Condition.createKeyValueCondition("role", "another_role", Op.NEQ, Context.LINK, false)
     85        cond = ConditionFactory.createKeyValueCondition("role", "another_role", Op.NEQ, Context.LINK, false)
    8686        assert cond.applies(e)
    8787    }
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.groovy

    r10193 r10837  
    1414import org.openstreetmap.josm.gui.mappaint.Environment
    1515import org.openstreetmap.josm.gui.mappaint.MultiCascade
     16import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition
     17import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyCondition
     18import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyMatchType
     19import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.KeyValueCondition
     20import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op
     21import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.PseudoClassCondition
     22import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition
    1623import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
    1724import org.openstreetmap.josm.tools.ColorHelper
     
    5057    public void testClassCondition() throws Exception {
    5158        def conditions = ((Selector.GeneralSelector) getParser("way[name=X].highway:closed").selector()).conds
    52         assert conditions.get(0) instanceof Condition.SimpleKeyValueCondition
     59        assert conditions.get(0) instanceof SimpleKeyValueCondition
    5360        assert conditions.get(0).applies(getEnvironment("name", "X"))
    54         assert conditions.get(1) instanceof Condition.ClassCondition
    55         assert conditions.get(2) instanceof Condition.PseudoClassCondition
     61        assert conditions.get(1) instanceof ClassCondition
     62        assert conditions.get(2) instanceof PseudoClassCondition
    5663        assert !conditions.get(2).applies(getEnvironment("name", "X"))
    5764    }
     
    93100    @Test
    94101    public void testEqualCondition() throws Exception {
    95         def condition = (Condition.SimpleKeyValueCondition) getParser("[surface=paved]").condition(Condition.Context.PRIMITIVE)
    96         assert condition instanceof Condition.SimpleKeyValueCondition
     102        def condition = (SimpleKeyValueCondition) getParser("[surface=paved]").condition(Condition.Context.PRIMITIVE)
     103        assert condition instanceof SimpleKeyValueCondition
    97104        assert "surface".equals(condition.k)
    98105        assert "paved".equals(condition.v)
     
    103110    @Test
    104111    public void testNotEqualCondition() throws Exception {
    105         def condition = (Condition.KeyValueCondition) getParser("[surface!=paved]").condition(Condition.Context.PRIMITIVE)
    106         assert Condition.Op.NEQ.equals(condition.op)
     112        def condition = (KeyValueCondition) getParser("[surface!=paved]").condition(Condition.Context.PRIMITIVE)
     113        assert Op.NEQ.equals(condition.op)
    107114        assert !condition.applies(getEnvironment("surface", "paved"))
    108115        assert condition.applies(getEnvironment("surface", "unpaved"))
     
    111118    @Test
    112119    public void testRegexCondition() throws Exception {
    113         def condition = (Condition.KeyValueCondition) getParser("[surface=~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
    114         assert Condition.Op.REGEX.equals(condition.op)
     120        def condition = (KeyValueCondition) getParser("[surface=~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
     121        assert Op.REGEX.equals(condition.op)
    115122        assert condition.applies(getEnvironment("surface", "unpaved"))
    116123        assert !condition.applies(getEnvironment("surface", "grass"))
     
    119126    @Test
    120127    public void testRegexConditionParenthesis() throws Exception {
    121         def condition = (Condition.KeyValueCondition) getParser("[name =~ /^\\(foo\\)/]").condition(Condition.Context.PRIMITIVE)
     128        def condition = (KeyValueCondition) getParser("[name =~ /^\\(foo\\)/]").condition(Condition.Context.PRIMITIVE)
    122129        assert condition.applies(getEnvironment("name", "(foo)"))
    123130        assert !condition.applies(getEnvironment("name", "foo"))
     
    127134    @Test
    128135    public void testNegatedRegexCondition() throws Exception {
    129         def condition = (Condition.KeyValueCondition) getParser("[surface!~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
    130         assert Condition.Op.NREGEX.equals(condition.op)
     136        def condition = (KeyValueCondition) getParser("[surface!~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
     137        assert Op.NREGEX.equals(condition.op)
    131138        assert !condition.applies(getEnvironment("surface", "unpaved"))
    132139        assert condition.applies(getEnvironment("surface", "grass"))
     
    135142    @Test
    136143    public void testBeginsEndsWithCondition() throws Exception {
    137         def condition = (Condition.KeyValueCondition) getParser('[foo ^= bar]').condition(Condition.Context.PRIMITIVE)
    138         assert Condition.Op.BEGINS_WITH.equals(condition.op)
     144        def condition = (KeyValueCondition) getParser('[foo ^= bar]').condition(Condition.Context.PRIMITIVE)
     145        assert Op.BEGINS_WITH.equals(condition.op)
    139146        assert condition.applies(getEnvironment("foo", "bar123"))
    140147        assert !condition.applies(getEnvironment("foo", "123bar"))
    141148        assert !condition.applies(getEnvironment("foo", "123bar123"))
    142         condition = (Condition.KeyValueCondition) getParser('[foo $= bar]').condition(Condition.Context.PRIMITIVE)
    143         assert Condition.Op.ENDS_WITH.equals(condition.op)
     149        condition = (KeyValueCondition) getParser('[foo $= bar]').condition(Condition.Context.PRIMITIVE)
     150        assert Op.ENDS_WITH.equals(condition.op)
    144151        assert !condition.applies(getEnvironment("foo", "bar123"))
    145152        assert condition.applies(getEnvironment("foo", "123bar"))
     
    158165    @Test
    159166    public void testStandardKeyCondition() throws Exception {
    160         def c1 = (Condition.KeyCondition) getParser("[ highway ]").condition(Condition.Context.PRIMITIVE)
    161         assert Condition.KeyMatchType.EQ.equals(c1.matchType)
     167        def c1 = (KeyCondition) getParser("[ highway ]").condition(Condition.Context.PRIMITIVE)
     168        assert KeyMatchType.EQ.equals(c1.matchType)
    162169        assert c1.applies(getEnvironment("highway", "unclassified"))
    163170        assert !c1.applies(getEnvironment("railway", "rail"))
    164         def c2 = (Condition.KeyCondition) getParser("[\"/slash/\"]").condition(Condition.Context.PRIMITIVE)
    165         assert Condition.KeyMatchType.EQ.equals(c2.matchType)
     171        def c2 = (KeyCondition) getParser("[\"/slash/\"]").condition(Condition.Context.PRIMITIVE)
     172        assert KeyMatchType.EQ.equals(c2.matchType)
    166173        assert c2.applies(getEnvironment("/slash/", "yes"))
    167174        assert !c2.applies(getEnvironment("\"slash\"", "no"))
     
    170177    @Test
    171178    public void testYesNoKeyCondition() throws Exception {
    172         def c1 = (Condition.KeyCondition) getParser("[oneway?]").condition(Condition.Context.PRIMITIVE)
    173         def c2 = (Condition.KeyCondition) getParser("[oneway?!]").condition(Condition.Context.PRIMITIVE)
    174         def c3 = (Condition.KeyCondition) getParser("[!oneway?]").condition(Condition.Context.PRIMITIVE)
    175         def c4 = (Condition.KeyCondition) getParser("[!oneway?!]").condition(Condition.Context.PRIMITIVE)
     179        def c1 = (KeyCondition) getParser("[oneway?]").condition(Condition.Context.PRIMITIVE)
     180        def c2 = (KeyCondition) getParser("[oneway?!]").condition(Condition.Context.PRIMITIVE)
     181        def c3 = (KeyCondition) getParser("[!oneway?]").condition(Condition.Context.PRIMITIVE)
     182        def c4 = (KeyCondition) getParser("[!oneway?!]").condition(Condition.Context.PRIMITIVE)
    176183        def yes = getEnvironment("oneway", "yes")
    177184        def no = getEnvironment("oneway", "no")
     
    193200    @Test
    194201    public void testRegexKeyCondition() throws Exception {
    195         def c1 = (Condition.KeyCondition) getParser("[/.*:(backward|forward)\$/]").condition(Condition.Context.PRIMITIVE)
    196         assert Condition.KeyMatchType.REGEX.equals(c1.matchType)
     202        def c1 = (KeyCondition) getParser("[/.*:(backward|forward)\$/]").condition(Condition.Context.PRIMITIVE)
     203        assert KeyMatchType.REGEX.equals(c1.matchType)
    197204        assert !c1.applies(getEnvironment("lanes", "3"))
    198205        assert c1.applies(getEnvironment("lanes:forward", "3"))
     
    214221    @Test
    215222    public void testKeyKeyCondition() throws Exception {
    216         def c1 = (Condition.KeyValueCondition) getParser("[foo = *bar]").condition(Condition.Context.PRIMITIVE)
     223        def c1 = (KeyValueCondition) getParser("[foo = *bar]").condition(Condition.Context.PRIMITIVE)
    217224        def w1 = new Way()
    218225        w1.put("foo", "123")
     
    221228        w1.put("bar", "123")
    222229        assert c1.applies(new Environment(w1))
    223         def c2 = (Condition.KeyValueCondition) getParser("[foo =~ */bar/]").condition(Condition.Context.PRIMITIVE)
     230        def c2 = (KeyValueCondition) getParser("[foo =~ */bar/]").condition(Condition.Context.PRIMITIVE)
    224231        def w2 = new Way(w1)
    225232        w2.put("bar", "[0-9]{3}")
Note: See TracChangeset for help on using the changeset viewer.