- Timestamp:
- 2014-05-04T15:47:33+02:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java
r7022 r7061 11 11 import java.util.HashSet; 12 12 import java.util.LinkedList; 13 import java.util.List; 13 14 import java.util.Set; 14 15 … … 32 33 33 34 /** 34 * Check for wrong relations 35 * 35 * Check for wrong relations. 36 * @since 3669 36 37 */ 37 38 public class RelationChecker extends Test { … … 95 96 @Override 96 97 public void visit(Relation n) { 98 LinkedList<Role> allroles = buildAllRoles(n); 99 if (allroles.isEmpty() && n.hasTag("type", "route") 100 && n.hasTag("route", "train", "subway", "monorail", "tram", "bus", "trolleybus", "aerialway", "ferry")) { 101 errors.add(new TestError(this, Severity.WARNING, 102 tr("Route scheme (public_transport or legacy) is unspecified. Add {0}", "public_transport:version"), 103 RELATION_UNKNOWN, n)); 104 } else if (allroles.isEmpty()) { 105 errors.add(new TestError(this, Severity.WARNING, tr("Relation type is unknown"), RELATION_UNKNOWN, n)); 106 } else { 107 HashMap<String, RoleInfo> map = buildRoleInfoMap(n); 108 if (map.isEmpty()) { 109 errors.add(new TestError(this, Severity.ERROR, tr("Relation is empty"), RELATION_EMPTY, n)); 110 } else { 111 checkRoles(n, allroles, map); 112 } 113 } 114 } 115 116 private HashMap<String, RoleInfo> buildRoleInfoMap(Relation n) { 117 HashMap<String,RoleInfo> map = new HashMap<>(); 118 for (RelationMember m : n.getMembers()) { 119 String role = m.getRole(); 120 RoleInfo ri = map.get(role); 121 if (ri == null) { 122 ri = new RoleInfo(); 123 } 124 ri.total++; 125 if (m.isRelation()) { 126 ri.relations.add(m.getRelation()); 127 } else if(m.isWay()) { 128 ri.ways.add(m.getWay()); 129 if (!m.getWay().isClosed()) { 130 ri.openways.add(m.getWay()); 131 } 132 } 133 else if (m.isNode()) { 134 ri.nodes.add(m.getNode()); 135 } 136 map.put(role, ri); 137 } 138 return map; 139 } 140 141 private LinkedList<Role> buildAllRoles(Relation n) { 97 142 LinkedList<Role> allroles = new LinkedList<>(); 98 143 for (TaggingPreset p : relationpresets) { … … 114 159 } 115 160 } 116 if (allroles.isEmpty() && n.hasTag("type", "route") 117 && n.hasTag("route", "train", "subway", "monorail", "tram", "bus", "trolleybus", "aerialway", "ferry")) { 118 errors.add(new TestError(this, Severity.WARNING, 119 tr("Route scheme (public_transport or legacy) is unspecified. Add {0}", "public_transport:version"), 120 RELATION_UNKNOWN, n)); 121 } else if (allroles.isEmpty()) { 122 errors.add( new TestError(this, Severity.WARNING, tr("Relation type is unknown"), 123 RELATION_UNKNOWN, n) ); 124 } else { 125 HashMap<String,RoleInfo> map = new HashMap<>(); 126 for (RelationMember m : n.getMembers()) { 127 String s = ""; 128 if (m.hasRole()) { 129 s = m.getRole(); 130 } 131 RoleInfo ri = map.get(s); 132 if (ri == null) { 133 ri = new RoleInfo(); 134 } 135 ri.total++; 136 if (m.isRelation()) { 137 ri.relations.add(m.getRelation()); 138 } else if(m.isWay()) { 139 ri.ways.add(m.getWay()); 140 if (!m.getWay().isClosed()) { 141 ri.openways.add(m.getWay()); 142 } 143 } 144 else if (m.isNode()) { 145 ri.nodes.add(m.getNode()); 146 } 147 map.put(s, ri); 148 } 149 if(map.isEmpty()) { 150 errors.add( new TestError(this, Severity.ERROR, tr("Relation is empty"), 151 RELATION_EMPTY, n) ); 161 return allroles; 162 } 163 164 private void checkRoles(Relation n, LinkedList<Role> allroles, HashMap<String, RoleInfo> map) { 165 List<String> done = new LinkedList<>(); 166 // Remove empty roles if several exist (like in route=hiking, see #9844) 167 List<Role> emptyRoles = new LinkedList<>(); 168 for (Role r : allroles) { 169 if ("".equals(r.key)) { 170 emptyRoles.add(r); 171 } 172 } 173 if (emptyRoles.size() > 1) { 174 allroles.removeAll(emptyRoles); 175 } 176 for (Role r : allroles) { 177 done.add(r.key); 178 String keyname = r.key; 179 if ("".equals(keyname)) { 180 keyname = tr("<empty>"); 181 } 182 RoleInfo ri = map.get(r.key); 183 checkRoleCounts(n, r, keyname, ri); 184 if (ri != null) { 185 if (r.types != null) { 186 checkRoleTypes(n, r, keyname, ri); 187 } 188 if (r.memberExpression != null) { 189 checkRoleMemberExpressions(n, r, keyname, ri); 190 } 191 } 192 } 193 for (String key : map.keySet()) { 194 if (!done.contains(key)) { 195 if (key.length() > 0) { 196 String s = marktr("Role {0} unknown"); 197 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 198 tr(s, key), MessageFormat.format(s, key), ROLE_UNKNOWN, n)); 199 } else { 200 String s = marktr("Empty role found"); 201 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 202 tr(s), s, ROLE_EMPTY, n)); 203 } 204 } 205 } 206 } 207 208 private void checkRoleMemberExpressions(Relation n, Role r, String keyname, RoleInfo ri) { 209 Set<OsmPrimitive> notMatching = new HashSet<>(); 210 Collection<OsmPrimitive> allPrimitives = new ArrayList<>(); 211 allPrimitives.addAll(ri.nodes); 212 allPrimitives.addAll(ri.ways); 213 allPrimitives.addAll(ri.relations); 214 for (OsmPrimitive p : allPrimitives) { 215 if (p.isUsable() && !r.memberExpression.match(p)) { 216 notMatching.add(p); 217 } 218 } 219 if (!notMatching.isEmpty()) { 220 String s = marktr("Member for role ''{0}'' does not match ''{1}''"); 221 LinkedList<OsmPrimitive> highlight = new LinkedList<>(notMatching); 222 highlight.addFirst(n); 223 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 224 tr(s, keyname, r.memberExpression), MessageFormat.format(s, keyname, r.memberExpression), WRONG_TYPE, 225 highlight, notMatching)); 226 } 227 } 228 229 private void checkRoleTypes(Relation n, Role r, String keyname, RoleInfo ri) { 230 Set<OsmPrimitive> wrongTypes = new HashSet<>(); 231 if (!r.types.contains(TaggingPresetType.WAY)) { 232 wrongTypes.addAll(r.types.contains(TaggingPresetType.CLOSEDWAY) ? ri.openways : ri.ways); 233 } 234 if (!r.types.contains(TaggingPresetType.NODE)) { 235 wrongTypes.addAll(ri.nodes); 236 } 237 if (!r.types.contains(TaggingPresetType.RELATION)) { 238 wrongTypes.addAll(ri.relations); 239 } 240 if (!wrongTypes.isEmpty()) { 241 String s = marktr("Member for role {0} of wrong type"); 242 LinkedList<OsmPrimitive> highlight = new LinkedList<>(wrongTypes); 243 highlight.addFirst(n); 244 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 245 tr(s, keyname), MessageFormat.format(s, keyname), WRONG_TYPE, 246 highlight, wrongTypes)); 247 } 248 } 249 250 private void checkRoleCounts(Relation n, Role r, String keyname, RoleInfo ri) { 251 long count = (ri == null) ? 0 : ri.total; 252 long vc = r.getValidCount(count); 253 if (count != vc) { 254 if (count == 0) { 255 String s = marktr("Role {0} missing"); 256 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 257 tr(s, keyname), MessageFormat.format(s, keyname), ROLE_MISSING, n)); 258 } 259 else if (vc > count) { 260 String s = marktr("Number of {0} roles too low ({1})"); 261 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 262 tr(s, keyname, count), MessageFormat.format(s, keyname, count), LOW_COUNT, n)); 152 263 } else { 153 LinkedList<String> done = new LinkedList<>(); 154 for (Role r : allroles) { 155 done.add(r.key); 156 String keyname = r.key; 157 if ("".equals(keyname)) { 158 keyname = tr("<empty>"); 159 } 160 RoleInfo ri = map.get(r.key); 161 long count = (ri == null) ? 0 : ri.total; 162 long vc = r.getValidCount(count); 163 if (count != vc) { 164 if (count == 0) { 165 String s = marktr("Role {0} missing"); 166 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 167 tr(s, keyname), MessageFormat.format(s, keyname), ROLE_MISSING, n)); 168 } 169 else if (vc > count) { 170 String s = marktr("Number of {0} roles too low ({1})"); 171 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 172 tr(s, keyname, count), MessageFormat.format(s, keyname, count), LOW_COUNT, n)); 173 } else { 174 String s = marktr("Number of {0} roles too high ({1})"); 175 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 176 tr(s, keyname, count), MessageFormat.format(s, keyname, count), HIGH_COUNT, n)); 177 } 178 } 179 if (ri != null) { 180 if (r.types != null) { 181 Set<OsmPrimitive> wrongTypes = new HashSet<>(); 182 if (!r.types.contains(TaggingPresetType.WAY)) { 183 wrongTypes.addAll(r.types.contains(TaggingPresetType.CLOSEDWAY) ? ri.openways : ri.ways); 184 } 185 if (!r.types.contains(TaggingPresetType.NODE)) { 186 wrongTypes.addAll(ri.nodes); 187 } 188 if (!r.types.contains(TaggingPresetType.RELATION)) { 189 wrongTypes.addAll(ri.relations); 190 } 191 if (!wrongTypes.isEmpty()) { 192 String s = marktr("Member for role {0} of wrong type"); 193 LinkedList<OsmPrimitive> highlight = new LinkedList<>(wrongTypes); 194 highlight.addFirst(n); 195 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 196 tr(s, keyname), MessageFormat.format(s, keyname), WRONG_TYPE, 197 highlight, wrongTypes)); 198 } 199 } 200 if (r.memberExpression != null) { 201 Set<OsmPrimitive> notMatching = new HashSet<>(); 202 Collection<OsmPrimitive> allPrimitives = new ArrayList<>(); 203 allPrimitives.addAll(ri.nodes); 204 allPrimitives.addAll(ri.ways); 205 allPrimitives.addAll(ri.relations); 206 for (OsmPrimitive p : allPrimitives) { 207 if (p.isUsable() && !r.memberExpression.match(p)) { 208 notMatching.add(p); 209 } 210 } 211 if (!notMatching.isEmpty()) { 212 String s = marktr("Member for role ''{0}'' does not match ''{1}''"); 213 LinkedList<OsmPrimitive> highlight = new LinkedList<>(notMatching); 214 highlight.addFirst(n); 215 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 216 tr(s, keyname, r.memberExpression), MessageFormat.format(s, keyname, r.memberExpression), WRONG_TYPE, 217 highlight, notMatching)); 218 } 219 } 220 } 221 } 222 for (String key : map.keySet()) { 223 if (!done.contains(key)) { 224 if (key.length() > 0) { 225 String s = marktr("Role {0} unknown"); 226 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 227 tr(s, key), MessageFormat.format(s, key), ROLE_UNKNOWN, n)); 228 } else { 229 String s = marktr("Empty role found"); 230 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 231 tr(s), s, ROLE_EMPTY, n)); 232 } 233 } 234 } 264 String s = marktr("Number of {0} roles too high ({1})"); 265 errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, 266 tr(s, keyname, count), MessageFormat.format(s, keyname, count), HIGH_COUNT, n)); 235 267 } 236 268 }
Note:
See TracChangeset
for help on using the changeset viewer.