Changeset 15245 in josm
- Timestamp:
- 2019-07-13T18:41:24+02:00 (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
r15104 r15245 57 57 import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ExpressionCondition; 58 58 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression; 59 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.Functions;60 59 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.ParameterFunction; 60 import org.openstreetmap.josm.gui.mappaint.mapcss.Functions; 61 61 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction; 62 62 import org.openstreetmap.josm.gui.mappaint.mapcss.LiteralExpression; -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java
r15122 r15245 719 719 * @param e MapCSS environment 720 720 * @return {@code true} if there is right-hand traffic at the current location 721 * @see ExpressionFactory.Functions#is_right_hand_traffic(Environment)721 * @see Functions#is_right_hand_traffic(Environment) 722 722 */ 723 723 static boolean righthandtraffic(Environment e) { // NO_UCD (unused code) 724 return ExpressionFactory.Functions.is_right_hand_traffic(e);724 return Functions.is_right_hand_traffic(e); 725 725 } 726 726 … … 730 730 * @param e MapCSS environment 731 731 * @return {@code true} if the way clockwise 732 * @see ExpressionFactory.Functions#is_clockwise(Environment)732 * @see Functions#is_clockwise(Environment) 733 733 */ 734 734 static boolean clockwise(Environment e) { // NO_UCD (unused code) 735 return ExpressionFactory.Functions.is_clockwise(e);735 return Functions.is_clockwise(e); 736 736 } 737 737 … … 741 741 * @param e MapCSS environment 742 742 * @return {@code true} if the way clockwise 743 * @see ExpressionFactory.Functions#is_anticlockwise(Environment)743 * @see Functions#is_anticlockwise(Environment) 744 744 */ 745 745 static boolean anticlockwise(Environment e) { // NO_UCD (unused code) 746 return ExpressionFactory.Functions.is_anticlockwise(e);746 return Functions.is_anticlockwise(e); 747 747 } 748 748 -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
r15196 r15245 2 2 package org.openstreetmap.josm.gui.mappaint.mapcss; 3 3 4 import java.awt.Color;5 4 import java.lang.annotation.ElementType; 6 5 import java.lang.annotation.Retention; … … 10 9 import java.lang.reflect.InvocationTargetException; 11 10 import java.lang.reflect.Method; 12 import java.nio.charset.StandardCharsets;13 11 import java.util.ArrayList; 14 import java.util.Arrays;15 12 import java.util.Collection; 16 13 import java.util.Collections; 17 14 import java.util.List; 18 import java.util.Locale;19 15 import java.util.Objects; 20 import java.util.TreeSet;21 16 import java.util.function.Function; 22 import java.util.regex.Matcher; 23 import java.util.regex.Pattern; 24 import java.util.zip.CRC32; 25 26 import org.openstreetmap.josm.data.coor.LatLon; 27 import org.openstreetmap.josm.data.gpx.GpxDistance; 28 import org.openstreetmap.josm.data.osm.IPrimitive; 29 import org.openstreetmap.josm.data.osm.Node; 30 import org.openstreetmap.josm.data.osm.OsmPrimitive; 31 import org.openstreetmap.josm.data.osm.Relation; 32 import org.openstreetmap.josm.data.osm.RelationMember; 33 import org.openstreetmap.josm.data.osm.Way; 34 import org.openstreetmap.josm.data.osm.search.SearchCompiler; 35 import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match; 36 import org.openstreetmap.josm.data.osm.search.SearchParseError; 37 import org.openstreetmap.josm.gui.MainApplication; 17 38 18 import org.openstreetmap.josm.gui.mappaint.Cascade; 39 19 import org.openstreetmap.josm.gui.mappaint.Environment; 40 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;41 import org.openstreetmap.josm.io.XmlWriter;42 import org.openstreetmap.josm.tools.AlphanumComparator;43 import org.openstreetmap.josm.tools.ColorHelper;44 import org.openstreetmap.josm.tools.Geometry;45 20 import org.openstreetmap.josm.tools.JosmRuntimeException; 46 21 import org.openstreetmap.josm.tools.Logging; 47 import org.openstreetmap.josm.tools.RightAndLefthandTraffic;48 import org.openstreetmap.josm.tools.RotationAngle;49 22 import org.openstreetmap.josm.tools.SubclassFilteredCollection; 50 import org.openstreetmap.josm.tools.Territories;51 23 import org.openstreetmap.josm.tools.Utils; 52 24 … … 112 84 113 85 /** 114 * List of functions that can be used in MapCSS expressions.115 *116 * First parameter can be of type {@link Environment} (if needed). This is117 * automatically filled in by JOSM and the user only sees the remaining arguments.118 * When one of the user supplied arguments cannot be converted the119 * expected type or is null, the function is not called and it returns null120 * immediately. Add the annotation {@link NullableArguments} to allow null arguments.121 * Every method must be static.122 */123 @SuppressWarnings("UnusedDeclaration")124 public static final class Functions {125 126 private Functions() {127 // Hide implicit public constructor for utility classes128 }129 130 /**131 * Identity function for compatibility with MapCSS specification.132 * @param o any object133 * @return {@code o} unchanged134 */135 public static Object eval(Object o) { // NO_UCD (unused code)136 return o;137 }138 139 /**140 * Function associated to the numeric "+" operator.141 * @param args arguments142 * @return Sum of arguments143 */144 public static float plus(float... args) { // NO_UCD (unused code)145 float res = 0;146 for (float f : args) {147 res += f;148 }149 return res;150 }151 152 /**153 * Function associated to the numeric "-" operator.154 * @param args arguments155 * @return Substraction of arguments156 */157 public static Float minus(float... args) { // NO_UCD (unused code)158 if (args.length == 0) {159 return 0.0F;160 }161 if (args.length == 1) {162 return -args[0];163 }164 float res = args[0];165 for (int i = 1; i < args.length; ++i) {166 res -= args[i];167 }168 return res;169 }170 171 /**172 * Function associated to the numeric "*" operator.173 * @param args arguments174 * @return Multiplication of arguments175 */176 public static float times(float... args) { // NO_UCD (unused code)177 float res = 1;178 for (float f : args) {179 res *= f;180 }181 return res;182 }183 184 /**185 * Function associated to the numeric "/" operator.186 * @param args arguments187 * @return Division of arguments188 */189 public static Float divided_by(float... args) { // NO_UCD (unused code)190 if (args.length == 0) {191 return 1.0F;192 }193 float res = args[0];194 for (int i = 1; i < args.length; ++i) {195 if (args[i] == 0) {196 return null;197 }198 res /= args[i];199 }200 return res;201 }202 203 /**204 * Creates a list of values, e.g., for the {@code dashes} property.205 * @param args The values to put in a list206 * @return list of values207 * @see Arrays#asList(Object[])208 */209 public static List<Object> list(Object... args) { // NO_UCD (unused code)210 return Arrays.asList(args);211 }212 213 /**214 * Returns the number of elements in a list.215 * @param lst the list216 * @return length of the list217 */218 public static Integer count(List<?> lst) { // NO_UCD (unused code)219 return lst.size();220 }221 222 /**223 * Returns the first non-null object.224 * The name originates from <a href="http://wiki.openstreetmap.org/wiki/MapCSS/0.2/eval">MapCSS standard</a>.225 * @param args arguments226 * @return the first non-null object227 * @see Utils#firstNonNull(Object[])228 */229 @NullableArguments230 public static Object any(Object... args) { // NO_UCD (unused code)231 return Utils.firstNonNull(args);232 }233 234 /**235 * Get the {@code n}th element of the list {@code lst} (counting starts at 0).236 * @param lst list237 * @param n index238 * @return {@code n}th element of the list, or {@code null} if index out of range239 * @since 5699240 */241 public static Object get(List<?> lst, float n) { // NO_UCD (unused code)242 int idx = Math.round(n);243 if (idx >= 0 && idx < lst.size()) {244 return lst.get(idx);245 }246 return null;247 }248 249 /**250 * Splits string {@code toSplit} at occurrences of the separator string {@code sep} and returns a list of matches.251 * @param sep separator string252 * @param toSplit string to split253 * @return list of matches254 * @see String#split(String)255 * @since 5699256 */257 public static List<String> split(String sep, String toSplit) { // NO_UCD (unused code)258 return Arrays.asList(toSplit.split(Pattern.quote(sep), -1));259 }260 261 /**262 * Creates a color value with the specified amounts of {@code r}ed, {@code g}reen, {@code b}lue (arguments from 0.0 to 1.0)263 * @param r the red component264 * @param g the green component265 * @param b the blue component266 * @return color matching the given components267 * @see Color#Color(float, float, float)268 */269 public static Color rgb(float r, float g, float b) { // NO_UCD (unused code)270 try {271 return new Color(r, g, b);272 } catch (IllegalArgumentException e) {273 Logging.trace(e);274 return null;275 }276 }277 278 /**279 * Creates a color value with the specified amounts of {@code r}ed, {@code g}reen, {@code b}lue, {@code alpha}280 * (arguments from 0.0 to 1.0)281 * @param r the red component282 * @param g the green component283 * @param b the blue component284 * @param alpha the alpha component285 * @return color matching the given components286 * @see Color#Color(float, float, float, float)287 */288 public static Color rgba(float r, float g, float b, float alpha) { // NO_UCD (unused code)289 try {290 return new Color(r, g, b, alpha);291 } catch (IllegalArgumentException e) {292 Logging.trace(e);293 return null;294 }295 }296 297 /**298 * Create color from hsb color model. (arguments form 0.0 to 1.0)299 * @param h hue300 * @param s saturation301 * @param b brightness302 * @return the corresponding color303 */304 public static Color hsb_color(float h, float s, float b) { // NO_UCD (unused code)305 try {306 return Color.getHSBColor(h, s, b);307 } catch (IllegalArgumentException e) {308 Logging.trace(e);309 return null;310 }311 }312 313 /**314 * Creates a color value from an HTML notation, i.e., {@code #rrggbb}.315 * @param html HTML notation316 * @return color matching the given notation317 */318 public static Color html2color(String html) { // NO_UCD (unused code)319 return ColorHelper.html2color(html);320 }321 322 /**323 * Computes the HTML notation ({@code #rrggbb}) for a color value).324 * @param c color325 * @return HTML notation matching the given color326 */327 public static String color2html(Color c) { // NO_UCD (unused code)328 return ColorHelper.color2html(c);329 }330 331 /**332 * Get the value of the red color channel in the rgb color model333 * @param c color334 * @return the red color channel in the range [0;1]335 * @see java.awt.Color#getRed()336 */337 public static float red(Color c) { // NO_UCD (unused code)338 return Utils.colorInt2float(c.getRed());339 }340 341 /**342 * Get the value of the green color channel in the rgb color model343 * @param c color344 * @return the green color channel in the range [0;1]345 * @see java.awt.Color#getGreen()346 */347 public static float green(Color c) { // NO_UCD (unused code)348 return Utils.colorInt2float(c.getGreen());349 }350 351 /**352 * Get the value of the blue color channel in the rgb color model353 * @param c color354 * @return the blue color channel in the range [0;1]355 * @see java.awt.Color#getBlue()356 */357 public static float blue(Color c) { // NO_UCD (unused code)358 return Utils.colorInt2float(c.getBlue());359 }360 361 /**362 * Get the value of the alpha channel in the rgba color model363 * @param c color364 * @return the alpha channel in the range [0;1]365 * @see java.awt.Color#getAlpha()366 */367 public static float alpha(Color c) { // NO_UCD (unused code)368 return Utils.colorInt2float(c.getAlpha());369 }370 371 /**372 * Assembles the strings to one.373 * @param args arguments374 * @return assembled string375 * @see Utils#join376 */377 @NullableArguments378 public static String concat(Object... args) { // NO_UCD (unused code)379 return Utils.join("", Arrays.asList(args));380 }381 382 /**383 * Assembles the strings to one, where the first entry is used as separator.384 * @param args arguments. First one is used as separator385 * @return assembled string386 * @see Utils#join387 */388 @NullableArguments389 public static String join(String... args) { // NO_UCD (unused code)390 return Utils.join(args[0], Arrays.asList(args).subList(1, args.length));391 }392 393 /**394 * Joins a list of {@code values} into a single string with fields separated by {@code separator}.395 * @param separator the separator396 * @param values collection of objects397 * @return assembled string398 * @see Utils#join399 */400 public static String join_list(final String separator, final List<String> values) { // NO_UCD (unused code)401 return Utils.join(separator, values);402 }403 404 /**405 * Returns the value of the property {@code key}, e.g., {@code prop("width")}.406 * @param env the environment407 * @param key the property key408 * @return the property value409 */410 public static Object prop(final Environment env, String key) { // NO_UCD (unused code)411 return prop(env, key, null);412 }413 414 /**415 * Returns the value of the property {@code key} from layer {@code layer}.416 * @param env the environment417 * @param key the property key418 * @param layer layer419 * @return the property value420 */421 public static Object prop(final Environment env, String key, String layer) {422 return env.getCascade(layer).get(key);423 }424 425 /**426 * Determines whether property {@code key} is set.427 * @param env the environment428 * @param key the property key429 * @return {@code true} if the property is set, {@code false} otherwise430 */431 public static Boolean is_prop_set(final Environment env, String key) { // NO_UCD (unused code)432 return is_prop_set(env, key, null);433 }434 435 /**436 * Determines whether property {@code key} is set on layer {@code layer}.437 * @param env the environment438 * @param key the property key439 * @param layer layer440 * @return {@code true} if the property is set, {@code false} otherwise441 */442 public static Boolean is_prop_set(final Environment env, String key, String layer) {443 return env.getCascade(layer).containsKey(key);444 }445 446 /**447 * Gets the value of the key {@code key} from the object in question.448 * @param env the environment449 * @param key the OSM key450 * @return the value for given key451 */452 public static String tag(final Environment env, String key) { // NO_UCD (unused code)453 return env.osm == null ? null : env.osm.get(key);454 }455 456 /**457 * Gets the first non-null value of the key {@code key} from the object's parent(s).458 * @param env the environment459 * @param key the OSM key460 * @return first non-null value of the key {@code key} from the object's parent(s)461 */462 public static String parent_tag(final Environment env, String key) { // NO_UCD (unused code)463 if (env.parent == null) {464 if (env.osm != null) {465 // we don't have a matched parent, so just search all referrers466 for (IPrimitive parent : env.osm.getReferrers()) {467 String value = parent.get(key);468 if (value != null) {469 return value;470 }471 }472 }473 return null;474 }475 return env.parent.get(key);476 }477 478 /**479 * Gets a list of all non-null values of the key {@code key} from the object's parent(s).480 *481 * The values are sorted according to {@link AlphanumComparator}.482 * @param env the environment483 * @param key the OSM key484 * @return a list of non-null values of the key {@code key} from the object's parent(s)485 */486 public static List<String> parent_tags(final Environment env, String key) { // NO_UCD (unused code)487 if (env.parent == null) {488 if (env.osm != null) {489 final Collection<String> tags = new TreeSet<>(AlphanumComparator.getInstance());490 // we don't have a matched parent, so just search all referrers491 for (IPrimitive parent : env.osm.getReferrers()) {492 String value = parent.get(key);493 if (value != null) {494 tags.add(value);495 }496 }497 return new ArrayList<>(tags);498 }499 return Collections.emptyList();500 }501 return Collections.singletonList(env.parent.get(key));502 }503 504 /**505 * Gets the value of the key {@code key} from the object's child.506 * @param env the environment507 * @param key the OSM key508 * @return the value of the key {@code key} from the object's child, or {@code null} if there is no child509 */510 public static String child_tag(final Environment env, String key) { // NO_UCD (unused code)511 return env.child == null ? null : env.child.get(key);512 }513 514 /**515 * Returns the OSM id of the object's parent.516 * <p>517 * Parent must be matched by child selector.518 * @param env the environment519 * @return the OSM id of the object's parent, if available, or {@code null}520 * @see IPrimitive#getUniqueId()521 */522 public static Long parent_osm_id(final Environment env) { // NO_UCD (unused code)523 return env.parent == null ? null : env.parent.getUniqueId();524 }525 526 /**527 * Returns the lowest distance between the OSM object and a GPX point528 * <p>529 * @param env the environment530 * @return the distance between the object and the closest gpx point or {@code Double.MAX_VALUE}531 * @since 14802532 */533 public static double gpx_distance(final Environment env) { // NO_UCD (unused code)534 if (env.osm instanceof OsmPrimitive) {535 return MainApplication.getLayerManager().getAllGpxData().stream()536 .mapToDouble(gpx -> GpxDistance.getLowestDistance((OsmPrimitive) env.osm, gpx))537 .min().orElse(Double.MAX_VALUE);538 }539 return Double.MAX_VALUE;540 }541 542 /**543 * Determines whether the object has a tag with the given key.544 * @param env the environment545 * @param key the OSM key546 * @return {@code true} if the object has a tag with the given key, {@code false} otherwise547 */548 public static boolean has_tag_key(final Environment env, String key) { // NO_UCD (unused code)549 return env.osm.hasKey(key);550 }551 552 /**553 * Returns the index of node in parent way or member in parent relation.554 * @param env the environment555 * @return the index as float. Starts at 1556 */557 public static Float index(final Environment env) { // NO_UCD (unused code)558 if (env.index == null) {559 return null;560 }561 return Float.valueOf(env.index + 1f);562 }563 564 /**565 * Returns the role of current object in parent relation, or role of child if current object is a relation.566 * @param env the environment567 * @return role of current object in parent relation, or role of child if current object is a relation568 * @see Environment#getRole()569 */570 public static String role(final Environment env) { // NO_UCD (unused code)571 return env.getRole();572 }573 574 /**575 * Returns true if role is in relation. Returns false if not a relation or it does not have the role.576 * @param env the environment577 * @param roles The roles to count in the relation578 * @return The number of relation members with the specified role579 * @since 15196580 */581 public static int count_roles(final Environment env, String... roles) { // NO_UCD (unused code)582 int rValue = 0;583 if (env.osm instanceof Relation) {584 List<String> roleList = Arrays.asList(roles);585 Relation rel = (Relation) env.osm;586 for (RelationMember member : rel.getMembers()) {587 if (roleList.contains(member.getRole())) rValue++;588 }589 }590 return rValue;591 }592 593 /**594 * Returns the area of a closed way or multipolygon in square meters or {@code null}.595 * @param env the environment596 * @return the area of a closed way or multipolygon in square meters or {@code null}597 * @see Geometry#computeArea(IPrimitive)598 */599 public static Float areasize(final Environment env) { // NO_UCD (unused code)600 final Double area = Geometry.computeArea(env.osm);601 return area == null ? null : area.floatValue();602 }603 604 /**605 * Returns the length of the way in metres or {@code null}.606 * @param env the environment607 * @return the length of the way in metres or {@code null}.608 * @see Way#getLength()609 */610 public static Float waylength(final Environment env) { // NO_UCD (unused code)611 if (env.osm instanceof Way) {612 return (float) ((Way) env.osm).getLength();613 } else {614 return null;615 }616 }617 618 /**619 * Function associated to the logical "!" operator.620 * @param b boolean value621 * @return {@code true} if {@code !b}622 */623 public static boolean not(boolean b) { // NO_UCD (unused code)624 return !b;625 }626 627 /**628 * Function associated to the logical ">=" operator.629 * @param a first value630 * @param b second value631 * @return {@code true} if {@code a >= b}632 */633 public static boolean greater_equal(float a, float b) { // NO_UCD (unused code)634 return a >= b;635 }636 637 /**638 * Function associated to the logical "<=" operator.639 * @param a first value640 * @param b second value641 * @return {@code true} if {@code a <= b}642 */643 public static boolean less_equal(float a, float b) { // NO_UCD (unused code)644 return a <= b;645 }646 647 /**648 * Function associated to the logical ">" operator.649 * @param a first value650 * @param b second value651 * @return {@code true} if {@code a > b}652 */653 public static boolean greater(float a, float b) { // NO_UCD (unused code)654 return a > b;655 }656 657 /**658 * Function associated to the logical "<" operator.659 * @param a first value660 * @param b second value661 * @return {@code true} if {@code a < b}662 */663 public static boolean less(float a, float b) { // NO_UCD (unused code)664 return a < b;665 }666 667 /**668 * Converts an angle in degrees to radians.669 * @param degree the angle in degrees670 * @return the angle in radians671 * @see Math#toRadians(double)672 */673 public static double degree_to_radians(double degree) { // NO_UCD (unused code)674 return Utils.toRadians(degree);675 }676 677 /**678 * Converts an angle diven in cardinal directions to radians.679 * The following values are supported: {@code n}, {@code north}, {@code ne}, {@code northeast},680 * {@code e}, {@code east}, {@code se}, {@code southeast}, {@code s}, {@code south},681 * {@code sw}, {@code southwest}, {@code w}, {@code west}, {@code nw}, {@code northwest}.682 * @param cardinal the angle in cardinal directions.683 * @return the angle in radians684 * @see RotationAngle#parseCardinalRotation(String)685 */686 public static Double cardinal_to_radians(String cardinal) { // NO_UCD (unused code)687 try {688 return RotationAngle.parseCardinalRotation(cardinal);689 } catch (IllegalArgumentException ignore) {690 Logging.trace(ignore);691 return null;692 }693 }694 695 /**696 * Determines if the objects {@code a} and {@code b} are equal.697 * @param a First object698 * @param b Second object699 * @return {@code true} if objects are equal, {@code false} otherwise700 * @see Object#equals(Object)701 */702 public static boolean equal(Object a, Object b) {703 if (a.getClass() == b.getClass()) return a.equals(b);704 if (a.equals(Cascade.convertTo(b, a.getClass()))) return true;705 return b.equals(Cascade.convertTo(a, b.getClass()));706 }707 708 /**709 * Determines if the objects {@code a} and {@code b} are not equal.710 * @param a First object711 * @param b Second object712 * @return {@code false} if objects are equal, {@code true} otherwise713 * @see Object#equals(Object)714 */715 public static boolean not_equal(Object a, Object b) { // NO_UCD (unused code)716 return !equal(a, b);717 }718 719 /**720 * Determines whether the JOSM search with {@code searchStr} applies to the object.721 * @param env the environment722 * @param searchStr the search string723 * @return {@code true} if the JOSM search with {@code searchStr} applies to the object724 * @see SearchCompiler725 */726 public static Boolean JOSM_search(final Environment env, String searchStr) { // NO_UCD (unused code)727 Match m;728 try {729 m = SearchCompiler.compile(searchStr);730 } catch (SearchParseError ex) {731 Logging.trace(ex);732 return null;733 }734 return m.match(env.osm);735 }736 737 /**738 * Obtains the JOSM'key {@link org.openstreetmap.josm.data.Preferences} string for key {@code key},739 * and defaults to {@code def} if that is null.740 * @param env the environment741 * @param key Key in JOSM preference742 * @param def Default value743 * @return value for key, or default value if not found744 */745 public static String JOSM_pref(Environment env, String key, String def) { // NO_UCD (unused code)746 return MapPaintStyles.getStyles().getPreferenceCached(key, def);747 }748 749 /**750 * Tests if string {@code target} matches pattern {@code pattern}751 * @param pattern The regex expression752 * @param target The character sequence to be matched753 * @return {@code true} if, and only if, the entire region sequence matches the pattern754 * @see Pattern#matches(String, CharSequence)755 * @since 5699756 */757 public static boolean regexp_test(String pattern, String target) { // NO_UCD (unused code)758 return Pattern.matches(pattern, target);759 }760 761 /**762 * Tests if string {@code target} matches pattern {@code pattern}763 * @param pattern The regex expression764 * @param target The character sequence to be matched765 * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")766 * @return {@code true} if, and only if, the entire region sequence matches the pattern767 * @see Pattern#CASE_INSENSITIVE768 * @see Pattern#DOTALL769 * @see Pattern#MULTILINE770 * @since 5699771 */772 public static boolean regexp_test(String pattern, String target, String flags) { // NO_UCD (unused code)773 int f = 0;774 if (flags.contains("i")) {775 f |= Pattern.CASE_INSENSITIVE;776 }777 if (flags.contains("s")) {778 f |= Pattern.DOTALL;779 }780 if (flags.contains("m")) {781 f |= Pattern.MULTILINE;782 }783 return Pattern.compile(pattern, f).matcher(target).matches();784 }785 786 /**787 * Tries to match string against pattern regexp and returns a list of capture groups in case of success.788 * The first element (index 0) is the complete match (i.e. string).789 * Further elements correspond to the bracketed parts of the regular expression.790 * @param pattern The regex expression791 * @param target The character sequence to be matched792 * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")793 * @return a list of capture groups if {@link Matcher#matches()}, or {@code null}.794 * @see Pattern#CASE_INSENSITIVE795 * @see Pattern#DOTALL796 * @see Pattern#MULTILINE797 * @since 5701798 */799 public static List<String> regexp_match(String pattern, String target, String flags) { // NO_UCD (unused code)800 int f = 0;801 if (flags.contains("i")) {802 f |= Pattern.CASE_INSENSITIVE;803 }804 if (flags.contains("s")) {805 f |= Pattern.DOTALL;806 }807 if (flags.contains("m")) {808 f |= Pattern.MULTILINE;809 }810 return Utils.getMatches(Pattern.compile(pattern, f).matcher(target));811 }812 813 /**814 * Tries to match string against pattern regexp and returns a list of capture groups in case of success.815 * The first element (index 0) is the complete match (i.e. string).816 * Further elements correspond to the bracketed parts of the regular expression.817 * @param pattern The regex expression818 * @param target The character sequence to be matched819 * @return a list of capture groups if {@link Matcher#matches()}, or {@code null}.820 * @since 5701821 */822 public static List<String> regexp_match(String pattern, String target) { // NO_UCD (unused code)823 return Utils.getMatches(Pattern.compile(pattern).matcher(target));824 }825 826 /**827 * Returns the OSM id of the current object.828 * @param env the environment829 * @return the OSM id of the current object830 * @see IPrimitive#getUniqueId()831 */832 public static long osm_id(final Environment env) { // NO_UCD (unused code)833 return env.osm.getUniqueId();834 }835 836 /**837 * Translates some text for the current locale. The first argument is the text to translate,838 * and the subsequent arguments are parameters for the string indicated by <code>{0}</code>, <code>{1}</code>, …839 * @param args arguments840 * @return the translated string841 */842 @NullableArguments843 public static String tr(String... args) { // NO_UCD (unused code)844 final String text = args[0];845 System.arraycopy(args, 1, args, 0, args.length - 1);846 return org.openstreetmap.josm.tools.I18n.tr(text, (Object[]) args);847 }848 849 /**850 * Returns the substring of {@code s} starting at index {@code begin} (inclusive, 0-indexed).851 * @param s The base string852 * @param begin The start index853 * @return the substring854 * @see String#substring(int)855 */856 public static String substring(String s, /* due to missing Cascade.convertTo for int*/ float begin) { // NO_UCD (unused code)857 return s == null ? null : s.substring((int) begin);858 }859 860 /**861 * Returns the substring of {@code s} starting at index {@code begin} (inclusive)862 * and ending at index {@code end}, (exclusive, 0-indexed).863 * @param s The base string864 * @param begin The start index865 * @param end The end index866 * @return the substring867 * @see String#substring(int, int)868 */869 public static String substring(String s, float begin, float end) { // NO_UCD (unused code)870 return s == null ? null : s.substring((int) begin, (int) end);871 }872 873 /**874 * Replaces in {@code s} every {@code} target} substring by {@code replacement}.875 * @param s The source string876 * @param target The sequence of char values to be replaced877 * @param replacement The replacement sequence of char values878 * @return The resulting string879 * @see String#replace(CharSequence, CharSequence)880 */881 public static String replace(String s, String target, String replacement) { // NO_UCD (unused code)882 return s == null ? null : s.replace(target, replacement);883 }884 885 /**886 * Converts string {@code s} to uppercase.887 * @param s The source string888 * @return The resulting string889 * @see String#toUpperCase(Locale)890 * @since 11756891 */892 public static String upper(String s) {893 return s == null ? null : s.toUpperCase(Locale.ENGLISH);894 }895 896 /**897 * Converts string {@code s} to lowercase.898 * @param s The source string899 * @return The resulting string900 * @see String#toLowerCase(Locale)901 * @since 11756902 */903 public static String lower(String s) {904 return s == null ? null : s.toLowerCase(Locale.ENGLISH);905 }906 907 /**908 * Trim whitespaces from the string {@code s}.909 * @param s The source string910 * @return The resulting string911 * @see Utils#strip912 * @since 11756913 */914 public static String trim(String s) {915 return Utils.strip(s);916 }917 918 /**919 * Check if two strings are similar, but not identical, i.e., have a Levenshtein distance of 1 or 2.920 * @param string1 first string to compare921 * @param string2 second string to compare922 * @return true if the normalized strings are different but only a "little bit"923 * @see Utils#isSimilar924 * @since 14371925 */926 public static boolean is_similar(String string1, String string2) {927 return Utils.isSimilar(string1, string2);928 }929 930 /**931 * Percent-decode a string. (See https://en.wikipedia.org/wiki/Percent-encoding)932 * This is especially useful for wikipedia titles933 * @param s url-encoded string934 * @return the decoded string, or original in case of an error935 * @since 11756936 */937 public static String URL_decode(String s) {938 if (s == null) return null;939 try {940 return Utils.decodeUrl(s);941 } catch (IllegalStateException e) {942 Logging.debug(e);943 return s;944 }945 }946 947 /**948 * Percent-encode a string. (See https://en.wikipedia.org/wiki/Percent-encoding)949 * This is especially useful for data urls, e.g.950 * <code>concat("data:image/svg+xml,", URL_encode("<svg>...</svg>"));</code>951 * @param s arbitrary string952 * @return the encoded string953 */954 public static String URL_encode(String s) { // NO_UCD (unused code)955 return s == null ? null : Utils.encodeUrl(s);956 }957 958 /**959 * XML-encode a string.960 *961 * Escapes special characters in xml. Alternative to using <![CDATA[ ... ]]> blocks.962 * @param s arbitrary string963 * @return the encoded string964 */965 public static String XML_encode(String s) { // NO_UCD (unused code)966 return s == null ? null : XmlWriter.encode(s);967 }968 969 /**970 * Calculates the CRC32 checksum from a string (based on RFC 1952).971 * @param s the string972 * @return long value from 0 to 2^32-1973 */974 public static long CRC32_checksum(String s) { // NO_UCD (unused code)975 CRC32 cs = new CRC32();976 cs.update(s.getBytes(StandardCharsets.UTF_8));977 return cs.getValue();978 }979 980 /**981 * check if there is right-hand traffic at the current location982 * @param env the environment983 * @return true if there is right-hand traffic984 * @since 7193985 */986 public static boolean is_right_hand_traffic(Environment env) {987 return RightAndLefthandTraffic.isRightHandTraffic(center(env));988 }989 990 /**991 * Determines whether the way is {@link Geometry#isClockwise closed and oriented clockwise},992 * or non-closed and the {@link Geometry#angleIsClockwise 1st, 2nd and last node are in clockwise order}.993 *994 * @param env the environment995 * @return true if the way is closed and oriented clockwise996 */997 public static boolean is_clockwise(Environment env) {998 if (!(env.osm instanceof Way)) {999 return false;1000 }1001 final Way way = (Way) env.osm;1002 return (way.isClosed() && Geometry.isClockwise(way))1003 || (!way.isClosed() && way.getNodesCount() > 2 && Geometry.angleIsClockwise(way.getNode(0), way.getNode(1), way.lastNode()));1004 }1005 1006 /**1007 * Determines whether the way is {@link Geometry#isClockwise closed and oriented anticlockwise},1008 * or non-closed and the {@link Geometry#angleIsClockwise 1st, 2nd and last node are in anticlockwise order}.1009 *1010 * @param env the environment1011 * @return true if the way is closed and oriented clockwise1012 */1013 public static boolean is_anticlockwise(Environment env) {1014 if (!(env.osm instanceof Way)) {1015 return false;1016 }1017 final Way way = (Way) env.osm;1018 return (way.isClosed() && !Geometry.isClockwise(way))1019 || (!way.isClosed() && way.getNodesCount() > 2 && !Geometry.angleIsClockwise(way.getNode(0), way.getNode(1), way.lastNode()));1020 }1021 1022 /**1023 * Prints the object to the command line (for debugging purpose).1024 * @param o the object1025 * @return the same object, unchanged1026 */1027 @NullableArguments1028 public static Object print(Object o) { // NO_UCD (unused code)1029 System.out.print(o == null ? "none" : o.toString());1030 return o;1031 }1032 1033 /**1034 * Prints the object to the command line, with new line at the end1035 * (for debugging purpose).1036 * @param o the object1037 * @return the same object, unchanged1038 */1039 @NullableArguments1040 public static Object println(Object o) { // NO_UCD (unused code)1041 System.out.println(o == null ? "none" : o.toString());1042 return o;1043 }1044 1045 /**1046 * Get the number of tags for the current primitive.1047 * @param env the environment1048 * @return number of tags1049 */1050 public static int number_of_tags(Environment env) { // NO_UCD (unused code)1051 return env.osm.getNumKeys();1052 }1053 1054 /**1055 * Get value of a setting.1056 * @param env the environment1057 * @param key setting key (given as layer identifier, e.g. setting::mykey {...})1058 * @return the value of the setting (calculated when the style is loaded)1059 */1060 public static Object setting(Environment env, String key) { // NO_UCD (unused code)1061 return env.source.settingValues.get(key);1062 }1063 1064 /**1065 * Returns the center of the environment OSM primitive.1066 * @param env the environment1067 * @return the center of the environment OSM primitive1068 * @since 112471069 */1070 public static LatLon center(Environment env) { // NO_UCD (unused code)1071 return env.osm instanceof Node ? ((Node) env.osm).getCoor() : env.osm.getBBox().getCenter();1072 }1073 1074 /**1075 * Determines if the object is inside territories matching given ISO3166 codes.1076 * @param env the environment1077 * @param codes comma-separated list of ISO3166-1-alpha2 or ISO3166-2 country/subdivision codes1078 * @return {@code true} if the object is inside territory matching given ISO3166 codes1079 * @since 112471080 */1081 public static boolean inside(Environment env, String codes) { // NO_UCD (unused code)1082 for (String code : codes.toUpperCase(Locale.ENGLISH).split(",")) {1083 if (Territories.isIso3166Code(code.trim(), center(env))) {1084 return true;1085 }1086 }1087 return false;1088 }1089 1090 /**1091 * Determines if the object is outside territories matching given ISO3166 codes.1092 * @param env the environment1093 * @param codes comma-separated list of ISO3166-1-alpha2 or ISO3166-2 country/subdivision codes1094 * @return {@code true} if the object is outside territory matching given ISO3166 codes1095 * @since 112471096 */1097 public static boolean outside(Environment env, String codes) { // NO_UCD (unused code)1098 return !inside(env, codes);1099 }1100 1101 /**1102 * Determines if the object centroid lies at given lat/lon coordinates.1103 * @param env the environment1104 * @param lat latitude, i.e., the north-south position in degrees1105 * @param lon longitude, i.e., the east-west position in degrees1106 * @return {@code true} if the object centroid lies at given lat/lon coordinates1107 * @since 125141108 */1109 public static boolean at(Environment env, double lat, double lon) { // NO_UCD (unused code)1110 return new LatLon(lat, lon).equalsEpsilon(center(env));1111 }1112 }1113 1114 /**1115 86 * Main method to create an function-like expression. 1116 87 * -
trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactoryTest.java
r11921 r15245 4 4 import org.junit.Rule; 5 5 import org.junit.Test; 6 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory.Functions;7 6 import org.openstreetmap.josm.testutils.JOSMTestRules; 8 7 -
trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java
r15196 r15245 422 422 /* Check with empty role and one object */ 423 423 Environment e = new Environment(rel1, new MultiCascade(), Environment.DEFAULT_LAYER, null); 424 assertEquals(1, ExpressionFactory.Functions.count_roles(e, ""));424 assertEquals(1, Functions.count_roles(e, "")); 425 425 426 426 /* Check with non-empty role and one object */ 427 427 e = new Environment(rel1, new MultiCascade(), Environment.DEFAULT_LAYER, null); 428 assertEquals(0, ExpressionFactory.Functions.count_roles(e, "from"));428 assertEquals(0, Functions.count_roles(e, "from")); 429 429 430 430 /* Check with empty role and two objects */ … … 433 433 rel1.addMember(new RelationMember("", way2)); 434 434 e = new Environment(rel1, new MultiCascade(), Environment.DEFAULT_LAYER, null); 435 assertEquals(2, ExpressionFactory.Functions.count_roles(e, ""));435 assertEquals(2, Functions.count_roles(e, "")); 436 436 437 437 /* Check with non-empty role and two objects */ 438 438 rel1.setMember(0, new RelationMember("from", way1)); 439 439 e = new Environment(rel1, new MultiCascade(), Environment.DEFAULT_LAYER, null); 440 assertEquals(1, ExpressionFactory.Functions.count_roles(e, "from"));440 assertEquals(1, Functions.count_roles(e, "from")); 441 441 442 442 /* Check with multiple roles */ 443 assertEquals(1, ExpressionFactory.Functions.count_roles(e, "from", "to"));443 assertEquals(1, Functions.count_roles(e, "from", "to")); 444 444 445 445 /* Check with non-relation */ 446 446 e = new Environment(way1, new MultiCascade(), Environment.DEFAULT_LAYER, null); 447 assertEquals(0, ExpressionFactory.Functions.count_roles(e, "from", "to"));447 assertEquals(0, Functions.count_roles(e, "from", "to")); 448 448 } 449 449
Note:
See TracChangeset
for help on using the changeset viewer.