| 161 | | private void checkRoles(Relation n, LinkedList<Role> allroles, HashMap<String, RoleInfo> map) { |
| 162 | | List<String> done = new LinkedList<>(); |
| 163 | | // Remove empty roles if several exist (like in route=hiking, see #9844) |
| 164 | | List<Role> emptyRoles = new LinkedList<>(); |
| 165 | | for (Role r : allroles) { |
| 166 | | if ("".equals(r.key)) { |
| 167 | | emptyRoles.add(r); |
| | 163 | private boolean checkMemberType(Role r, RelationMember member) { |
| | 164 | if (r.types != null) { |
| | 165 | for (TaggingPresetType type: r.types) { |
| | 166 | if (type.equals(TaggingPresetType.CLOSEDWAY) && member.isWay() && member.getWay().isClosed()) { |
| | 167 | return true; |
| | 168 | } |
| | 169 | if(type.equals(TaggingPresetType.NODE) && member.isNode()) { |
| | 170 | return true; |
| | 171 | } |
| | 172 | if(type.equals(TaggingPresetType.RELATION) && member.isRelation()) { |
| | 173 | return true; |
| | 174 | } |
| | 175 | if(type.equals(TaggingPresetType.WAY) && member.isWay()) { |
| | 176 | return true; |
| | 177 | } |
| 170 | | if (emptyRoles.size() > 1) { |
| 171 | | allroles.removeAll(emptyRoles); |
| | 183 | // if no match is found, then test failed |
| | 184 | return false; |
| | 185 | } |
| | 186 | |
| | 187 | // get all role definition for specified key and check, if some definition matches |
| | 188 | private boolean checkMemberExpressionAndType(RolePreset rolePreset, RelationMember member, Relation n) { |
| | 189 | TestError possibleMatchError = null; |
| | 190 | if (rolePreset == null || rolePreset.roles == null) { |
| | 191 | // no restrictions on role types |
| | 192 | return true; |
| 173 | | for (Role r : allroles) { |
| 174 | | done.add(r.key); |
| 175 | | String keyname = r.key; |
| 176 | | if ("".equals(keyname)) { |
| 177 | | keyname = tr("<empty>"); |
| 178 | | } |
| 179 | | RoleInfo ri = map.get(r.key); |
| 180 | | checkRoleCounts(n, r, keyname, ri); |
| 181 | | if (ri != null) { |
| 182 | | if (r.types != null) { |
| 183 | | checkRoleTypes(n, r, keyname, ri); |
| 184 | | } |
| | 194 | for (Role r: rolePreset.roles) { |
| | 195 | if (checkMemberType(r, member)) { |
| 186 | | checkRoleMemberExpressions(n, r, keyname, ri); |
| | 197 | OsmPrimitive primitive = member.getMember(); |
| | 198 | if(primitive.isUsable()) { |
| | 199 | if(r.memberExpression.match(primitive)) { |
| | 200 | return true; |
| | 201 | } else { |
| | 202 | // possible match error |
| | 203 | String s = marktr("Role member didn''t match expression {0} in template {1}"); |
| | 204 | possibleMatchError = new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, |
| | 205 | tr(s, r.memberExpression, rolePreset.name), s, WRONG_TYPE, |
| | 206 | member.getMember().isUsable() ? member.getMember() : n); |
| | 207 | |
| | 208 | } |
| | 209 | } else { |
| | 210 | // if it is not usable, we can't verify memberExpression |
| | 211 | return true; |
| | 212 | } |
| | 213 | } else { |
| | 214 | return true; |
| | 215 | } |
| | 216 | } else { |
| | 217 | |
| | 218 | } |
| | 219 | } |
| | 220 | if( possibleMatchError != null) { |
| | 221 | errors.add(possibleMatchError); |
| | 222 | } else { |
| | 223 | String s = marktr("Role member type {0} didn''t match accepted list of {1} in template {2}"); |
| | 224 | Set<Enum<TaggingPresetType>> types = new HashSet<>(); |
| | 225 | for (Role r: rolePreset.roles) { |
| | 226 | types.addAll(r.types); |
| | 227 | } |
| | 228 | errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, |
| | 229 | tr(s, member.getType(), types, rolePreset.name), s, WRONG_TYPE, |
| | 230 | member.getMember().isUsable() ? member.getMember() : n)); |
| | 231 | } |
| | 232 | return false; |
| | 233 | } |
| | 234 | |
| | 235 | |
| | 236 | private void checkRoles(Relation n, HashMap<String, RolePreset> allroles, HashMap<String, RoleInfo> map) { |
| | 237 | Set<String> done = new HashSet<>(); |
| | 238 | |
| | 239 | // go through all members of relation |
| | 240 | for (RelationMember member: n.getMembers()) { |
| | 241 | String role = member.getRole(); |
| | 242 | done.add(role); |
| | 243 | |
| | 244 | // error reporting done inside |
| | 245 | checkMemberExpressionAndType(allroles.get(role), member, n); |
| | 246 | } |
| | 247 | |
| | 248 | // verify role counts based on whole role sets |
| | 249 | for(RolePreset rp: allroles.values()) { |
| | 250 | for (Role r: rp.roles) { |
| | 251 | String keyname = r.key; |
| | 252 | if ("".equals(keyname)) { |
| | 253 | keyname = tr("<empty>"); |
| 205 | | private void checkRoleMemberExpressions(Relation n, Role r, String keyname, RoleInfo ri) { |
| 206 | | Set<OsmPrimitive> notMatching = new HashSet<>(); |
| 207 | | Collection<OsmPrimitive> allPrimitives = new ArrayList<>(); |
| 208 | | allPrimitives.addAll(ri.nodes); |
| 209 | | allPrimitives.addAll(ri.ways); |
| 210 | | allPrimitives.addAll(ri.relations); |
| 211 | | for (OsmPrimitive p : allPrimitives) { |
| 212 | | if (p.isUsable() && !r.memberExpression.match(p)) { |
| 213 | | notMatching.add(p); |
| 214 | | } |
| 215 | | } |
| 216 | | if (!notMatching.isEmpty()) { |
| 217 | | String s = marktr("Member for role ''{0}'' does not match ''{1}''"); |
| 218 | | LinkedList<OsmPrimitive> highlight = new LinkedList<>(notMatching); |
| 219 | | highlight.addFirst(n); |
| 220 | | errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, |
| 221 | | tr(s, keyname, r.memberExpression), MessageFormat.format(s, keyname, r.memberExpression), WRONG_TYPE, |
| 222 | | highlight, notMatching)); |
| 223 | | } |
| 224 | | } |
| 225 | | |
| 226 | | private void checkRoleTypes(Relation n, Role r, String keyname, RoleInfo ri) { |
| 227 | | Set<OsmPrimitive> wrongTypes = new HashSet<>(); |
| 228 | | if (!r.types.contains(TaggingPresetType.WAY)) { |
| 229 | | wrongTypes.addAll(r.types.contains(TaggingPresetType.CLOSEDWAY) ? ri.openways : ri.ways); |
| 230 | | } |
| 231 | | if (!r.types.contains(TaggingPresetType.NODE)) { |
| 232 | | wrongTypes.addAll(ri.nodes); |
| 233 | | } |
| 234 | | if (!r.types.contains(TaggingPresetType.RELATION)) { |
| 235 | | wrongTypes.addAll(ri.relations); |
| 236 | | } |
| 237 | | if (!wrongTypes.isEmpty()) { |
| 238 | | String s = marktr("Member for role {0} of wrong type"); |
| 239 | | LinkedList<OsmPrimitive> highlight = new LinkedList<>(wrongTypes); |
| 240 | | highlight.addFirst(n); |
| 241 | | errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG, |
| 242 | | tr(s, keyname), MessageFormat.format(s, keyname), WRONG_TYPE, |
| 243 | | highlight, wrongTypes)); |
| 244 | | } |
| 245 | | } |