Skip to content

Commit

Permalink
Add check for name being part of alt_name
Browse files Browse the repository at this point in the history
JOSMs validator rules already check if the value of name is equal to alt_name. This rule instead checks if the value of name is part of alt_name when alt_name contains multiple values
  • Loading branch information
Famlam committed Sep 13, 2024
1 parent cb92d3f commit fcaada7
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
63 changes: 63 additions & 0 deletions plugins/TagFix_MultipleTag2.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def init(self, logger):
self.errors[40201] = self.def_class(item = 4020, level = 1, tags = mapcss.list_('tag') + mapcss.list_('fix:chair', 'highway', 'roundabout'), title = mapcss.tr('Roundabout as area'))
self.errors[40303] = self.def_class(item = 4030, level = 1, tags = mapcss.list_('tag') + mapcss.list_('fix:chair'), title = mapcss.tr('Tag conflict'), trap = mapcss.tr('Sometimes the object needs both tags.'), detail = mapcss.tr('The object contains two incompatible tags.'))
self.errors[40401] = self.def_class(item = 4040, level = 2, tags = mapcss.list_('tag') + mapcss.list_('fix:chair', 'name', 'tourism'), title = mapcss.tr('{0} with {1}, likely this is a single pitch instead', mapcss._tag_uncapture(capture_tags, '{0.tag}'), mapcss._tag_uncapture(capture_tags, '{1.tag}')), detail = mapcss.tr('The camping site has a numeric name. Numeric identifiers are much more common for a single pitch (`tourism=camp_pitch`) within a camping site. Possibly the two were interchanged?'))
self.errors[50802] = self.def_class(item = 5080, level = 3, tags = mapcss.list_('tag') + mapcss.list_('name', 'fix:chair'), title = mapcss.tr('{0} contains the value of {1}', mapcss._tag_uncapture(capture_tags, '{0.key}'), mapcss._tag_uncapture(capture_tags, '{1.key}')), trap = mapcss.tr('Possibly a different `alt_name` that is very similar to `name` was meant. Alternative names are often similar (but never equal) to the name.'))
self.errors[71301] = self.def_class(item = 7130, level = 3, tags = mapcss.list_('tag') + mapcss.list_('highway', 'maxheight', 'fix:survey'), title = mapcss.tr('Missing maxheight tag'), detail = mapcss.tr('Missing `maxheight=*` or `maxheight:physical=*` for a tunnel or a way under a bridge.'))
self.errors[303210] = self.def_class(item = 3032, level = 3, tags = mapcss.list_('tag'), title = mapcss.tr('Fence with {0} tag, also add {1}', mapcss._tag_uncapture(capture_tags, '{1.key}'), mapcss._tag_uncapture(capture_tags, '{2.key}')))
self.errors[303211] = self.def_class(item = 3032, level = 3, tags = mapcss.list_('tag'), title = mapcss.tr('suspicious tag combination'))
Expand Down Expand Up @@ -215,6 +216,28 @@ def node(self, data, tags):
'name'])
}})

# *[alt_name][name][alt_name~=*name][alt_name!=*name]
if ('alt_name' in keys and 'name' in keys):
match = False
if not match:
capture_tags = {}
try: match = ((mapcss._tag_capture(capture_tags, 0, tags, 'alt_name')) and (mapcss._tag_capture(capture_tags, 1, tags, 'name')) and (mapcss.list_contains(mapcss._tag_capture(capture_tags, 2, tags, 'alt_name'), mapcss._value_capture(capture_tags, 2, mapcss.tag(tags, 'name')))) and (mapcss._tag_capture(capture_tags, 3, tags, 'alt_name') != mapcss._value_capture(capture_tags, 3, mapcss.tag(tags, 'name'))))
except mapcss.RuleAbort: pass
if match:
# -osmoseTags:list("name","fix:chair")
# -osmoseTrap:tr("Possibly a different `alt_name` that is very similar to `name` was meant. Alternative names are often similar (but never equal) to the name.")
# -osmoseItemClassLevel:"5080/50802/3"
# throwWarning:tr("{0} contains the value of {1}","{0.key}","{1.key}")
# fixAdd:concat("{0.key}=",join_list(";",trim_list(split(";",replace(concat(";",join_list(";",trim_list(split(";",tag("alt_name")))),";"),concat(";",tag("name"),";"),";")))))
# assertMatch:"node name=y alt_name=\"x; y; z\""
# assertMatch:"node name=y alt_name=x;y;z"
# assertNoMatch:"node name=y alt_name=xyz"
# assertNoMatch:"node name=y alt_name=y"
err.append({'class': 50802, 'subclass': 0, 'text': mapcss.tr('{0} contains the value of {1}', mapcss._tag_uncapture(capture_tags, '{0.key}'), mapcss._tag_uncapture(capture_tags, '{1.key}')), 'allow_fix_override': True, 'fix': {
'+': dict([
(mapcss.concat(mapcss._tag_uncapture(capture_tags, '{0.key}='), mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.replace(mapcss.concat(';', mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.tag(tags, 'alt_name')))), ';'), mapcss.concat(';', mapcss.tag(tags, 'name'), ';'), ';')))))).split('=', 1)])
}})

# node[tunnel][!highway][!area:highway][!railway][!waterway][!piste:type][type!=tunnel][public_transport!=platform][route!=ferry][man_made!=pipeline][man_made!=goods_conveyor][man_made!=wildlife_crossing][man_made!=tunnel][power!=cable]
if ('tunnel' in keys):
match = False
Expand Down Expand Up @@ -507,6 +530,24 @@ def way(self, data, tags, nds):
'name'])
}})

# *[alt_name][name][alt_name~=*name][alt_name!=*name]
if ('alt_name' in keys and 'name' in keys):
match = False
if not match:
capture_tags = {}
try: match = ((mapcss._tag_capture(capture_tags, 0, tags, 'alt_name')) and (mapcss._tag_capture(capture_tags, 1, tags, 'name')) and (mapcss.list_contains(mapcss._tag_capture(capture_tags, 2, tags, 'alt_name'), mapcss._value_capture(capture_tags, 2, mapcss.tag(tags, 'name')))) and (mapcss._tag_capture(capture_tags, 3, tags, 'alt_name') != mapcss._value_capture(capture_tags, 3, mapcss.tag(tags, 'name'))))
except mapcss.RuleAbort: pass
if match:
# -osmoseTags:list("name","fix:chair")
# -osmoseTrap:tr("Possibly a different `alt_name` that is very similar to `name` was meant. Alternative names are often similar (but never equal) to the name.")
# -osmoseItemClassLevel:"5080/50802/3"
# throwWarning:tr("{0} contains the value of {1}","{0.key}","{1.key}")
# fixAdd:concat("{0.key}=",join_list(";",trim_list(split(";",replace(concat(";",join_list(";",trim_list(split(";",tag("alt_name")))),";"),concat(";",tag("name"),";"),";")))))
err.append({'class': 50802, 'subclass': 0, 'text': mapcss.tr('{0} contains the value of {1}', mapcss._tag_uncapture(capture_tags, '{0.key}'), mapcss._tag_uncapture(capture_tags, '{1.key}')), 'allow_fix_override': True, 'fix': {
'+': dict([
(mapcss.concat(mapcss._tag_uncapture(capture_tags, '{0.key}='), mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.replace(mapcss.concat(';', mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.tag(tags, 'alt_name')))), ';'), mapcss.concat(';', mapcss.tag(tags, 'name'), ';'), ';')))))).split('=', 1)])
}})

return err

def relation(self, data, tags, members):
Expand Down Expand Up @@ -660,6 +701,24 @@ def relation(self, data, tags, members):
'name'])
}})

# *[alt_name][name][alt_name~=*name][alt_name!=*name]
if ('alt_name' in keys and 'name' in keys):
match = False
if not match:
capture_tags = {}
try: match = ((mapcss._tag_capture(capture_tags, 0, tags, 'alt_name')) and (mapcss._tag_capture(capture_tags, 1, tags, 'name')) and (mapcss.list_contains(mapcss._tag_capture(capture_tags, 2, tags, 'alt_name'), mapcss._value_capture(capture_tags, 2, mapcss.tag(tags, 'name')))) and (mapcss._tag_capture(capture_tags, 3, tags, 'alt_name') != mapcss._value_capture(capture_tags, 3, mapcss.tag(tags, 'name'))))
except mapcss.RuleAbort: pass
if match:
# -osmoseTags:list("name","fix:chair")
# -osmoseTrap:tr("Possibly a different `alt_name` that is very similar to `name` was meant. Alternative names are often similar (but never equal) to the name.")
# -osmoseItemClassLevel:"5080/50802/3"
# throwWarning:tr("{0} contains the value of {1}","{0.key}","{1.key}")
# fixAdd:concat("{0.key}=",join_list(";",trim_list(split(";",replace(concat(";",join_list(";",trim_list(split(";",tag("alt_name")))),";"),concat(";",tag("name"),";"),";")))))
err.append({'class': 50802, 'subclass': 0, 'text': mapcss.tr('{0} contains the value of {1}', mapcss._tag_uncapture(capture_tags, '{0.key}'), mapcss._tag_uncapture(capture_tags, '{1.key}')), 'allow_fix_override': True, 'fix': {
'+': dict([
(mapcss.concat(mapcss._tag_uncapture(capture_tags, '{0.key}='), mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.replace(mapcss.concat(';', mapcss.join_list(';', mapcss.trim_list(mapcss.split(';', mapcss.tag(tags, 'alt_name')))), ';'), mapcss.concat(';', mapcss.tag(tags, 'name'), ';'), ';')))))).split('=', 1)])
}})

return err


Expand Down Expand Up @@ -688,6 +747,10 @@ class father:
self.check_err(n.node(data, {'barrier': 'fence', 'material': 'wood'}), expected={'class': 303210, 'subclass': 0})
self.check_err(n.node(data, {'name': '24', 'tourism': 'camp_site'}), expected={'class': 40401, 'subclass': 0})
self.check_not_err(n.node(data, {'name': '24tents', 'tourism': 'camp_site'}), expected={'class': 40401, 'subclass': 0})
self.check_err(n.node(data, {'alt_name': 'x; y; z', 'name': 'y'}), expected={'class': 50802, 'subclass': 0})
self.check_err(n.node(data, {'alt_name': 'x;y;z', 'name': 'y'}), expected={'class': 50802, 'subclass': 0})
self.check_not_err(n.node(data, {'alt_name': 'xyz', 'name': 'y'}), expected={'class': 50802, 'subclass': 0})
self.check_not_err(n.node(data, {'alt_name': 'y', 'name': 'y'}), expected={'class': 50802, 'subclass': 0})
self.check_err(n.way(data, {'amenity': 'fuel', 'building': 'roof'}, [0]), expected={'class': 30322, 'subclass': 0})
self.check_not_err(n.way(data, {'amenity': 'parking', 'building': 'roof', 'parking': 'rooftop'}, [0]), expected={'class': 30322, 'subclass': 0})
self.check_err(n.way(data, {'fee': 'yes', 'highway': 'primary'}, [0]), expected={'class': 30320, 'subclass': 1000})
Expand Down
13 changes: 13 additions & 0 deletions plugins/TagFix_MultipleTag2.validator.mapcss
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,19 @@ area[tourism=caravan_site][name][name=~/^[0-9]+$/][!ref][!building] {
}


*[alt_name][name][alt_name~=*name][alt_name!=*name] {
throwWarning: tr("{0} contains the value of {1}", "{0.key}", "{1.key}");
assertMatch: "node name=y alt_name=x;y;z";
assertMatch: "node name=y alt_name=\"x; y; z\"";
assertNoMatch: "node name=y alt_name=y"; /* already checked by mapcss validator rules of JOSM */
assertNoMatch: "node name=y alt_name=xyz";
fixAdd: concat("{0.key}=", join_list(";", trim_list(split(";", replace(concat(";", join_list(";", trim_list(split(";", tag("alt_name")))), ";"), concat(";", tag("name"), ";"), ";")))));
-osmoseItemClassLevel: "5080/50802/3";
-osmoseTags: list("name", "fix:chair");
-osmoseTrap: tr("Possibly a different `alt_name` that is very similar to `name` was meant. Alternative names are often similar (but never equal) to the name.");
}


/* Workaround for issue #1766 */
node[tunnel][!highway][!area:highway][!railway][!waterway][!piste:type][type!=tunnel][public_transport!=platform][route!=ferry][man_made!=pipeline][man_made!=goods_conveyor][man_made!=wildlife_crossing][man_made!=tunnel][power!=cable] {
throwWarning: tr("{0} on suspicious object", "{0.key}");
Expand Down

0 comments on commit fcaada7

Please sign in to comment.