source: josm/trunk/src/org/openstreetmap/josm/data/osm/OsmUtils.java@ 16260

Last change on this file since 16260 was 15951, checked in by simon04, 4 years ago

Simplify OsmUtils.isTrue/isFalse/isReversed (fix NPE)

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import java.util.Collection;
5import java.util.Locale;
6import java.util.Map;
7import java.util.regex.Pattern;
8import java.util.stream.Stream;
9
10import org.openstreetmap.josm.data.coor.LatLon;
11import org.openstreetmap.josm.tools.CheckParameterUtil;
12import org.openstreetmap.josm.tools.TextTagParser;
13
14/**
15 * Utility methods/constants that are useful for generic OSM tag handling.
16 */
17public final class OsmUtils {
18
19 /**
20 * A value that should be used to indicate true
21 * @since 12186
22 */
23 public static final String TRUE_VALUE = "yes";
24 /**
25 * A value that should be used to indicate false
26 * @since 12186
27 */
28 public static final String FALSE_VALUE = "no";
29 /**
30 * A value that should be used to indicate that a property applies reversed on the way
31 * @since 12186
32 */
33 public static final String REVERSE_VALUE = "-1";
34
35 /**
36 * Discouraged synonym for {@link #TRUE_VALUE}
37 */
38 public static final String trueval = TRUE_VALUE;
39 /**
40 * Discouraged synonym for {@link #FALSE_VALUE}
41 */
42 public static final String falseval = FALSE_VALUE;
43 /**
44 * Discouraged synonym for {@link #REVERSE_VALUE}
45 */
46 public static final String reverseval = REVERSE_VALUE;
47
48 private OsmUtils() {
49 // Hide default constructor for utils classes
50 }
51
52 /**
53 * Converts a string to a boolean value
54 * @param value The string to convert
55 * @return {@link Boolean#TRUE} if that string represents a true value,
56 * {@link Boolean#FALSE} if it represents a false value,
57 * <code>null</code> otherwise.
58 */
59 public static Boolean getOsmBoolean(String value) {
60 if (value == null) return null;
61 String lowerValue = value.toLowerCase(Locale.ENGLISH);
62 if (isTrue(lowerValue)) return Boolean.TRUE;
63 if (isFalse(lowerValue)) return Boolean.FALSE;
64 return null;
65 }
66
67 /**
68 * Normalizes the OSM boolean value
69 * @param value The tag value
70 * @return The best true/false value or the old value if the input cannot be converted.
71 * @see #TRUE_VALUE
72 * @see #FALSE_VALUE
73 */
74 public static String getNamedOsmBoolean(String value) {
75 Boolean res = getOsmBoolean(value);
76 return res == null ? value : (res ? trueval : falseval);
77 }
78
79 /**
80 * Check if the value is a value indicating that a property applies reversed.
81 * @param value The value to check
82 * @return true if it is reversed.
83 */
84 public static boolean isReversed(String value) {
85 if (value == null) {
86 return false;
87 }
88 switch (value) {
89 case "reverse":
90 case "-1":
91 return true;
92 default:
93 return false;
94 }
95 }
96
97 /**
98 * Check if a tag value represents a boolean true value
99 * @param value The value to check
100 * @return true if it is a true value.
101 */
102 public static boolean isTrue(String value) {
103 if (value == null) {
104 return false;
105 }
106 switch (value) {
107 case "true":
108 case "yes":
109 case "1":
110 case "on":
111 return true;
112 default:
113 return false;
114 }
115 }
116
117 /**
118 * Check if a tag value represents a boolean false value
119 * @param value The value to check
120 * @return true if it is a true value.
121 */
122 public static boolean isFalse(String value) {
123 if (value == null) {
124 return false;
125 }
126 switch (value) {
127 case "false":
128 case "no":
129 case "0":
130 case "off":
131 return true;
132 default:
133 return false;
134 }
135 }
136
137 /**
138 * Creates a new OSM primitive around (0,0) according to the given assertion. Originally written for unit tests,
139 * this can also be used in another places like validation of local MapCSS validator rules.
140 * Ways and relations created using this method are empty.
141 * @param assertion The assertion describing OSM primitive (ex: "way name=Foo railway=rail")
142 * @return a new OSM primitive according to the given assertion
143 * @throws IllegalArgumentException if assertion is null or if the primitive type cannot be deduced from it
144 * @since 7356
145 */
146 public static OsmPrimitive createPrimitive(String assertion) {
147 return createPrimitive(assertion, LatLon.ZERO, false);
148 }
149
150 /**
151 * Creates a new OSM primitive according to the given assertion. Originally written for unit tests,
152 * this can also be used in another places like validation of local MapCSS validator rules.
153 * @param assertion The assertion describing OSM primitive (ex: "way name=Foo railway=rail")
154 * @param around the coordinate at which the primitive will be located
155 * @param enforceLocation if {@code true}, ways and relations will not be empty to force a physical location
156 * @return a new OSM primitive according to the given assertion
157 * @throws IllegalArgumentException if assertion is null or if the primitive type cannot be deduced from it
158 * @since 14486
159 */
160 public static OsmPrimitive createPrimitive(String assertion, LatLon around, boolean enforceLocation) {
161 CheckParameterUtil.ensureParameterNotNull(assertion, "assertion");
162 final String[] x = assertion.split("\\s+", 2);
163 final OsmPrimitive p = "n".equals(x[0]) || "node".equals(x[0])
164 ? newNode(around)
165 : "w".equals(x[0]) || "way".equals(x[0]) || /*for MapCSS related usage*/ "area".equals(x[0])
166 ? newWay(around, enforceLocation)
167 : "r".equals(x[0]) || "relation".equals(x[0])
168 ? newRelation(around, enforceLocation)
169 : null;
170 if (p == null) {
171 throw new IllegalArgumentException("Expecting n/node/w/way/r/relation/area, but got '" + x[0] + '\'');
172 }
173 if (x.length > 1) {
174 for (final Map.Entry<String, String> i : TextTagParser.readTagsFromText(x[1]).entrySet()) {
175 p.put(i.getKey(), i.getValue());
176 }
177 }
178 return p;
179 }
180
181 private static Node newNode(LatLon around) {
182 return new Node(around);
183 }
184
185 private static Way newWay(LatLon around, boolean enforceLocation) {
186 Way w = new Way();
187 if (enforceLocation) {
188 w.addNode(newNode(new LatLon(around.lat()+0.1, around.lon())));
189 w.addNode(newNode(new LatLon(around.lat()-0.1, around.lon())));
190 }
191 return w;
192 }
193
194 private static Relation newRelation(LatLon around, boolean enforceLocation) {
195 Relation r = new Relation();
196 if (enforceLocation) {
197 r.addMember(new RelationMember(null, newNode(around)));
198 }
199 return r;
200 }
201
202 /**
203 * Returns the layer value of primitive (null for layer 0).
204 * @param w OSM primitive
205 * @return the value of "layer" key, or null if absent or set to 0 (default value)
206 * @since 12986
207 * @since 13637 (signature)
208 */
209 public static String getLayer(IPrimitive w) {
210 String layer1 = w.get("layer");
211 if ("0".equals(layer1)) {
212 layer1 = null; // 0 is default value for layer.
213 }
214 return layer1;
215 }
216
217 /**
218 * Determines if the given collection contains primitives, and that none of them belong to a locked layer.
219 * @param collection collection of OSM primitives
220 * @return {@code true} if the given collection is not empty and does not contain any primitive in a locked layer.
221 * @since 13611
222 * @since 13957 (signature)
223 */
224 public static boolean isOsmCollectionEditable(Collection<? extends IPrimitive> collection) {
225 if (collection == null || collection.isEmpty()) {
226 return false;
227 }
228 // see #16510: optimization: only consider the first primitive, as collection always refer to the same dataset
229 OsmData<?, ?, ?, ?> ds = collection.iterator().next().getDataSet();
230 return ds == null || !ds.isLocked();
231 }
232
233 /**
234 * Splits a tag value by <a href="https://wiki.openstreetmap.org/wiki/Semi-colon_value_separator">semi-colon value separator</a>.
235 * Spaces around the ; are ignored.
236 *
237 * @param value the value to separate
238 * @return the separated values as Stream
239 * @since 15671
240 */
241 public static Stream<String> splitMultipleValues(String value) {
242 return Pattern.compile("\\s*;\\s*").splitAsStream(value);
243 }
244}
Note: See TracBrowser for help on using the repository browser.