source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/UnclosedWays.java@ 14577

Last change on this file since 14577 was 14577, checked in by Klumbumbus, 5 years ago

fix #17130 - warn about area:highway on unclosed ways and nodes

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.util.Arrays;
8import java.util.Collections;
9import java.util.HashSet;
10import java.util.Set;
11
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.OsmUtils;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.Way;
16import org.openstreetmap.josm.data.validation.Severity;
17import org.openstreetmap.josm.data.validation.Test;
18import org.openstreetmap.josm.data.validation.TestError;
19
20/**
21 * Check area type ways for errors
22 *
23 * @author stoecker
24 * @since 3669
25 */
26public class UnclosedWays extends Test {
27
28 /**
29 * Constructs a new {@code UnclosedWays} test.
30 */
31 public UnclosedWays() {
32 super(tr("Unclosed Ways"), tr("This tests if ways which should be circular are closed."));
33 }
34
35 /**
36 * A check performed by UnclosedWays test.
37 * @since 6390
38 */
39 private static class UnclosedWaysCheck {
40 /** The unique numeric code for this check */
41 public final int code;
42 /** The OSM key checked */
43 public final String key;
44 /** The English message */
45 private final String engMessage;
46 /** The special values, to be ignored if ignore is set to true; to be considered only if ignore is set to false */
47 private final Set<String> specialValues;
48 /** The boolean indicating if special values must be ignored or considered only */
49 private final boolean ignore;
50
51 /**
52 * Constructs a new {@code UnclosedWaysCheck}.
53 * @param code The unique numeric code for this check
54 * @param key The OSM key checked
55 * @param engMessage The English message
56 */
57 UnclosedWaysCheck(int code, String key, String engMessage) {
58 this(code, key, engMessage, Collections.<String>emptySet());
59 }
60
61 /**
62 * Constructs a new {@code UnclosedWaysCheck}.
63 * @param code The unique numeric code for this check
64 * @param key The OSM key checked
65 * @param engMessage The English message
66 * @param ignoredValues The ignored values.
67 */
68 UnclosedWaysCheck(int code, String key, String engMessage, Set<String> ignoredValues) {
69 this(code, key, engMessage, ignoredValues, true);
70 }
71
72 /**
73 * Constructs a new {@code UnclosedWaysCheck}.
74 * @param code The unique numeric code for this check
75 * @param key The OSM key checked
76 * @param engMessage The English message
77 * @param specialValues The special values, to be ignored if ignore is set to true; to be considered only if ignore is set to false
78 * @param ignore indicates if special values must be ignored or considered only
79 */
80 UnclosedWaysCheck(int code, String key, String engMessage, Set<String> specialValues, boolean ignore) {
81 this.code = code;
82 this.key = key;
83 this.engMessage = engMessage;
84 this.specialValues = specialValues;
85 this.ignore = ignore;
86 }
87
88 /**
89 * Returns the test error of the given way, if any.
90 * @param w The way to check
91 * @param test parent test
92 * @return The test error if the way is erroneous, {@code null} otherwise
93 */
94 public final TestError getTestError(Way w, UnclosedWays test) {
95 String value = w.get(key);
96 if (isValueErroneous(value)) {
97 return TestError.builder(test, Severity.WARNING, code)
98 .message(tr("Unclosed way"), engMessage, engMessage.contains("{0}") ? new Object[]{value} : new Object[]{})
99 .primitives(w)
100 .highlight(Arrays.asList(w.firstNode(), w.lastNode()))
101 .build();
102 }
103 return null;
104 }
105
106 protected boolean isValueErroneous(String value) {
107 return value != null && ignore != specialValues.contains(value);
108 }
109 }
110
111 /**
112 * A check performed by UnclosedWays test where the key is treated as boolean.
113 * @since 6390
114 */
115 private static final class UnclosedWaysBooleanCheck extends UnclosedWaysCheck {
116
117 /**
118 * Constructs a new {@code UnclosedWaysBooleanCheck}.
119 * @param code The unique numeric code for this check
120 * @param key The OSM key checked
121 * @param engMessage The English message
122 */
123 UnclosedWaysBooleanCheck(int code, String key, String engMessage) {
124 super(code, key, engMessage);
125 }
126
127 @Override
128 protected boolean isValueErroneous(String value) {
129 Boolean btest = OsmUtils.getOsmBoolean(value);
130 // Not a strict boolean comparison to handle building=house like a building=yes
131 return (btest != null && btest) || (btest == null && value != null);
132 }
133 }
134
135 private static final UnclosedWaysCheck[] checks = {
136 // CHECKSTYLE.OFF: SingleSpaceSeparator
137 // list contains natural tag allowed on unclosed ways as well as those only allowed on nodes to avoid
138 // duplicate warnings
139 new UnclosedWaysCheck(1101, "natural", marktr("natural type {0}"),
140 new HashSet<>(Arrays.asList("arete", "cave", "cliff", "coastline", "gorge", "gully", "peak",
141 "ridge", "saddle", "tree", "tree_row", "valley", "volcano"))),
142
143 new UnclosedWaysCheck(1102, "landuse", marktr("landuse type {0}")),
144 new UnclosedWaysCheck(1103, "amenities", marktr("amenities type {0}")),
145 new UnclosedWaysCheck(1104, "sport", marktr("sport type {0}"),
146 new HashSet<>(Arrays.asList("water_slide", "climbing", "skiing"))),
147 new UnclosedWaysCheck(1105, "tourism", marktr("tourism type {0}"),
148 new HashSet<>(Arrays.asList("attraction", "artwork"))),
149 new UnclosedWaysCheck(1106, "shop", marktr("shop type {0}")),
150 new UnclosedWaysCheck(1107, "leisure", marktr("leisure type {0}"),
151 new HashSet<>(Arrays.asList("track", "slipway"))),
152 new UnclosedWaysCheck(1108, "waterway", marktr("waterway type {0}"),
153 new HashSet<>(Arrays.asList("riverbank")), false),
154 new UnclosedWaysCheck(1109, "boundary", marktr("boundary type {0}")),
155 new UnclosedWaysCheck(1110, "area:highway", marktr("area:highway type {0}")),
156 new UnclosedWaysBooleanCheck(1120, "building", marktr("building")),
157 new UnclosedWaysBooleanCheck(1130, "area", marktr("area")),
158 // CHECKSTYLE.ON: SingleSpaceSeparator
159 };
160
161 /**
162 * Returns the set of checked OSM keys.
163 * @return The set of checked OSM keys.
164 * @since 6390
165 */
166 public Set<String> getCheckedKeys() {
167 Set<String> keys = new HashSet<>();
168 for (UnclosedWaysCheck c : checks) {
169 keys.add(c.key);
170 }
171 return keys;
172 }
173
174 @Override
175 public void visit(Way w) {
176
177 if (!w.isUsable() || w.isArea())
178 return;
179
180 for (OsmPrimitive parent: w.getReferrers()) {
181 if (parent instanceof Relation && ((Relation) parent).isMultipolygon())
182 return;
183 }
184
185 for (UnclosedWaysCheck c : checks) {
186 TestError error = c.getTestError(w, this);
187 if (error != null) {
188 errors.add(error);
189 return;
190 }
191 }
192 }
193}
Note: See TracBrowser for help on using the repository browser.