001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.Arrays; 005import java.util.HashSet; 006import java.util.Locale; 007import java.util.Map; 008import java.util.Set; 009 010import org.openstreetmap.josm.data.coor.LatLon; 011import org.openstreetmap.josm.tools.CheckParameterUtil; 012import org.openstreetmap.josm.tools.TextTagParser; 013 014/** 015 * Utility methods/constants that are useful for generic OSM tag handling. 016 */ 017public final class OsmUtils { 018 019 private static final Set<String> TRUE_VALUES = new HashSet<>(Arrays 020 .asList("true", "yes", "1", "on")); 021 private static final Set<String> FALSE_VALUES = new HashSet<>(Arrays 022 .asList("false", "no", "0", "off")); 023 private static final Set<String> REVERSE_VALUES = new HashSet<>(Arrays 024 .asList("reverse", "-1")); 025 026 /** 027 * A value that should be used to indicate true 028 * @since 12186 029 */ 030 public static final String TRUE_VALUE = "yes"; 031 /** 032 * A value that should be used to indicate false 033 * @since 12186 034 */ 035 public static final String FALSE_VALUE = "no"; 036 /** 037 * A value that should be used to indicate that a property applies reversed on the way 038 * @since 12186 039 */ 040 public static final String REVERSE_VALUE = "-1"; 041 042 /** 043 * Discouraged synonym for {@link #TRUE_VALUE} 044 */ 045 public static final String trueval = TRUE_VALUE; 046 /** 047 * Discouraged synonym for {@link #FALSE_VALUE} 048 */ 049 public static final String falseval = FALSE_VALUE; 050 /** 051 * Discouraged synonym for {@link #REVERSE_VALUE} 052 */ 053 public static final String reverseval = REVERSE_VALUE; 054 055 private OsmUtils() { 056 // Hide default constructor for utils classes 057 } 058 059 /** 060 * Converts a string to a boolean value 061 * @param value The string to convert 062 * @return {@link Boolean#TRUE} if that string represents a true value, 063 * {@link Boolean#FALSE} if it represents a false value, 064 * <code>null</code> otherwise. 065 */ 066 public static Boolean getOsmBoolean(String value) { 067 if (value == null) return null; 068 String lowerValue = value.toLowerCase(Locale.ENGLISH); 069 if (TRUE_VALUES.contains(lowerValue)) return Boolean.TRUE; 070 if (FALSE_VALUES.contains(lowerValue)) return Boolean.FALSE; 071 return null; 072 } 073 074 /** 075 * Normalizes the OSM boolean value 076 * @param value The tag value 077 * @return The best true/false value or the old value if the input cannot be converted. 078 * @see #TRUE_VALUE 079 * @see #FALSE_VALUE 080 */ 081 public static String getNamedOsmBoolean(String value) { 082 Boolean res = getOsmBoolean(value); 083 return res == null ? value : (res ? trueval : falseval); 084 } 085 086 /** 087 * Check if the value is a value indicating that a property applies reversed. 088 * @param value The value to check 089 * @return true if it is reversed. 090 */ 091 public static boolean isReversed(String value) { 092 return REVERSE_VALUES.contains(value); 093 } 094 095 /** 096 * Check if a tag value represents a boolean true value 097 * @param value The value to check 098 * @return true if it is a true value. 099 */ 100 public static boolean isTrue(String value) { 101 return TRUE_VALUES.contains(value); 102 } 103 104 /** 105 * Check if a tag value represents a boolean false value 106 * @param value The value to check 107 * @return true if it is a true value. 108 */ 109 public static boolean isFalse(String value) { 110 return FALSE_VALUES.contains(value); 111 } 112 113 /** 114 * Creates a new OSM primitive according to the given assertion. Originally written for unit tests, 115 * this can also be used in another places like validation of local MapCSS validator rules. 116 * @param assertion The assertion describing OSM primitive (ex: "way name=Foo railway=rail") 117 * @return a new OSM primitive according to the given assertion 118 * @throws IllegalArgumentException if assertion is null or if the primitive type cannot be deduced from it 119 * @since 7356 120 */ 121 public static OsmPrimitive createPrimitive(String assertion) { 122 CheckParameterUtil.ensureParameterNotNull(assertion, "assertion"); 123 final String[] x = assertion.split("\\s+", 2); 124 final OsmPrimitive p = "n".equals(x[0]) || "node".equals(x[0]) 125 ? new Node(LatLon.ZERO) 126 : "w".equals(x[0]) || "way".equals(x[0]) || /*for MapCSS related usage*/ "area".equals(x[0]) 127 ? new Way() 128 : "r".equals(x[0]) || "relation".equals(x[0]) 129 ? new Relation() 130 : null; 131 if (p == null) { 132 throw new IllegalArgumentException("Expecting n/node/w/way/r/relation/area, but got '" + x[0] + '\''); 133 } 134 if (x.length > 1) { 135 for (final Map.Entry<String, String> i : TextTagParser.readTagsFromText(x[1]).entrySet()) { 136 p.put(i.getKey(), i.getValue()); 137 } 138 } 139 return p; 140 } 141 142 /** 143 * Returns the layer value of primitive (null for layer 0). 144 * @param w OSM primitive 145 * @return the value of "layer" key, or null if absent or set to 0 (default value) 146 * @since 12986 147 */ 148 public static String getLayer(OsmPrimitive w) { 149 String layer1 = w.get("layer"); 150 if ("0".equals(layer1)) { 151 layer1 = null; // 0 is default value for layer. 152 } 153 return layer1; 154 } 155}