- Timestamp:
- 2023-06-14T18:01:00+02:00 (14 months ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/resources/data/validator/numeric.mapcss
r18731 r18757 68 68 } 69 69 70 *[height][height =~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {71 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");72 set height_meter_autofix;73 fixAdd: concat("height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("height")),1)," m");74 assertMatch: "node height=6.78 meters";75 assertMatch: "node height=5 metre";76 assertMatch: "node height=2m";77 assertNoMatch: "node height=2 m";78 assertNoMatch: "node height=5";79 }80 *[height][height =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {81 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");82 set height_foot_autofix;83 fixAdd: concat("height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("height")),1)," ft");84 assertMatch: "node height=6.78 foot";85 assertMatch: "node height=5 Feet";86 assertMatch: "node height=2ft";87 assertNoMatch: "node height=2 ft";88 assertNoMatch: "node height=5";89 }90 *[height][height =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {91 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");92 fixAdd: concat("height=", replace(tag("height"), ",", "."));93 set height_separator_autofix;94 assertMatch: "node height=5,5";95 assertMatch: "node height=12,00";96 assertMatch: "node height=12,5 ft";97 assertNoMatch: "node height=12,000";98 assertNoMatch: "node height=3,50,5";99 assertNoMatch: "node height=3.5";100 assertNoMatch: "node height=4";101 }102 103 *[maxheight][maxheight =~ /^[1-9][0-9]*(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {104 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");105 set maxheight_meter_autofix;106 fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxheight")),1)," m");107 assertMatch: "node maxheight=6.78 meters";108 assertMatch: "node maxheight=5 metre";109 assertMatch: "node maxheight=2m";110 assertNoMatch: "node maxheight=2 m";111 assertNoMatch: "node maxheight=5";112 }113 *[maxheight][maxheight =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {114 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");115 set maxheight_foot_autofix;116 fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxheight")),1)," ft");117 assertMatch: "node maxheight=6.78 foot";118 assertMatch: "node maxheight=5 Feet";119 assertMatch: "node maxheight=2ft";120 assertNoMatch: "node maxheight=2 ft";121 assertNoMatch: "node maxheight=5";122 }123 *[maxheight][maxheight =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {124 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");125 fixAdd: concat("maxheight=", replace(tag("maxheight"), ",", "."));126 set maxheight_separator_autofix;127 assertMatch: "node maxheight=5,5";128 assertMatch: "node maxheight=12,00";129 assertMatch: "node maxheight=12,5 ft";130 assertNoMatch: "node maxheight=12,000";131 assertNoMatch: "node maxheight=3,50,5";132 assertNoMatch: "node maxheight=3.5";133 assertNoMatch: "node maxheight=4";134 }135 136 70 *[roof:height][roof:height =~ /^0*(\.0*)?( (m|ft))?$/][roof:shape=flat] { 137 71 throwWarning: tr("{0} is unnecessary for {1}", "{0.tag}", "{2.tag}"); … … 144 78 assertNoMatch: "node roof:height=0 roof:shape=gabled"; 145 79 } 146 *[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/]!.zero_roof_height_flat { 80 81 /********************* 82 * Begin Unit checks * 83 *********************/ 84 /* See https://wiki.openstreetmap.org/wiki/Map_features/Units */ 85 /* 1. Replace aliases to make the rest of the checks easier to implement */ 86 /* Distance measurements, note that these should look also match `,` separators to ensure that at least one error is matched */ 87 /* Meters; Note that we cannot assertMatch "2 m" since we replace the double space with a single space */ 88 *[height][height =~ /^(?i)[0-9]+([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/], 89 *[roof:height][roof:height =~ /^(?i)[0-9]+([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/]!.zero_roof_height_flat, 90 *[width][width =~ /^(?i)[0-9]+([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/], 91 *[maxwidth][maxwidth =~ /^(?i)[0-9]+([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/], 92 *[min_height][min_height =~ /^(?i)-?[0-9]+([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/], 93 *[maxheight][maxheight =~ /^(?i)[1-9][0-9]*([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/], 94 *[maxlength][maxlength =~ /^(?i)[1-9][0-9]*([.,][0-9]+)?( *(metres?|meters?)|m| {2,}m)$/] { 95 set _unit_auto_fix; 147 96 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}"); 148 set roof_height_meter_autofix; 149 fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("roof:height")),1)," m"); 97 fixAdd: concat("{0.key}", "=", get(regexp_match("([0-9.,]+) *.+", "{0.value}"), 1), " m"); 98 assertMatch: "node height=6.78 meters"; 99 assertMatch: "node height=6,78 meters"; 100 assertMatch: "node height=5 metre"; 101 assertMatch: "node height=2m"; 102 assertNoMatch: "node height=2 m"; 103 assertNoMatch: "node height=5"; 104 assertMatch: "node maxheight=6.78 meters"; 105 assertMatch: "node maxheight=5 metre"; 106 assertMatch: "node maxheight=2m"; 107 assertNoMatch: "node maxheight=2 m"; 108 assertNoMatch: "node maxheight=5"; 150 109 assertMatch: "node roof:height=6.78 meters"; 151 110 assertMatch: "node roof:height=5 metre"; … … 153 112 assertNoMatch: "node roof:height=2 m"; 154 113 assertNoMatch: "node roof:height=5"; 155 }156 *[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/]!.zero_roof_height_flat {157 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");158 set roof_height_foot_autofix;159 fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("roof:height")),1)," ft");160 assertMatch: "node roof:height=6.78 foot";161 assertMatch: "node roof:height=5 Feet";162 assertMatch: "node roof:height=2ft";163 assertNoMatch: "node roof:height=2 ft";164 assertNoMatch: "node roof:height=5";165 }166 *[roof:height][roof:height =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {167 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");168 fixAdd: concat("roof:height=", replace(tag("roof:height"), ",", "."));169 set roof_height_separator_autofix;170 assertMatch: "node roof:height=5,5";171 assertMatch: "node roof:height=12,00";172 assertMatch: "node roof:height=12,5 ft";173 assertNoMatch: "node roof:height=12,000";174 assertNoMatch: "node roof:height=3,50,5";175 assertNoMatch: "node roof:height=3.5";176 assertNoMatch: "node roof:height=4";177 }178 179 *[maxlength][maxlength =~ /^[1-9][0-9]*(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {180 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");181 set maxlength_meter_autofix;182 fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxlength")),1)," m");183 114 assertMatch: "node maxlength=6.78 meters"; 184 115 assertMatch: "node maxlength=5 metre"; … … 186 117 assertNoMatch: "node maxlength=2 m"; 187 118 assertNoMatch: "node maxlength=5"; 188 }189 *[maxlength][maxlength =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {190 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");191 set maxlength_foot_autofix;192 fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxlength")),1)," ft");193 assertMatch: "node maxlength=6.78 foot";194 assertMatch: "node maxlength=5 Feet";195 assertMatch: "node maxlength=2ft";196 assertNoMatch: "node maxlength=2 ft";197 assertNoMatch: "node maxlength=5";198 }199 *[maxlength][maxlength =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {200 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");201 fixAdd: concat("maxlength=", replace(tag("maxlength"), ",", "."));202 set maxlength_separator_autofix;203 assertMatch: "node maxlength=5,5";204 assertMatch: "node maxlength=12,00";205 assertMatch: "node maxlength=12,5 ft";206 assertNoMatch: "node maxlength=12,000";207 assertNoMatch: "node maxlength=3,50,5";208 assertNoMatch: "node maxlength=3.5";209 assertNoMatch: "node maxlength=4";210 }211 212 *[width][width =~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {213 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");214 set width_meter_autofix;215 fixAdd: concat("width=", get(regexp_match("([0-9.]+)( )*(.+)",tag("width")),1)," m");216 119 assertMatch: "node width=6.78 meters"; 217 120 assertMatch: "node width=5 metre"; … … 219 122 assertNoMatch: "node width=2 m"; 220 123 assertNoMatch: "node width=5"; 221 } 222 *[width][width =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] { 223 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}"); 224 set width_foot_autofix; 225 fixAdd: concat("width=", get(regexp_match("([0-9.]+)( )*(.+)",tag("width")),1)," ft"); 124 assertMatch: "node maxwidth=6.78 meters"; 125 assertMatch: "node maxwidth=5 metre"; 126 assertMatch: "node maxwidth=2m"; 127 assertNoMatch: "node maxwidth=2 m"; 128 assertNoMatch: "node maxwidth=5"; 129 assertMatch: "node min_height=6.78 meters"; 130 assertMatch: "node min_height=5 metre"; 131 assertMatch: "node min_height=2m"; 132 assertNoMatch: "node min_height=2 m"; 133 assertNoMatch: "node min_height=5"; 134 } 135 136 /* Foot inches */ 137 *[height][height =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/], 138 *[maxheight][maxheight =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/], 139 *[roof:height][roof:height =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/]!.zero_roof_height_flat, 140 *[maxlength][maxlength =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/], 141 *[width][width =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/], 142 *[maxwidth][maxwidth =~ /^(?i)[0-9]+([.,][0-9]+)?( *(foot|feet|ft)| +\')$/] { 143 set _unit_auto_fix; 144 throwWarning: tr("unusual value of {0}: use '' for foot and \" for inches, no spaces", "{0.key}"); 145 fixAdd: concat("{0.key}", "=", get(regexp_match("([0-9.,]+) *.+", "{0.value}"), 1), "'"); 146 assertMatch: "node height=6.78 foot"; 147 assertMatch: "node height=5 Feet"; 148 assertMatch: "node height=2 '"; 149 assertNoMatch: "node height=2'"; 150 assertNoMatch: "node height=5"; 151 assertMatch: "node maxheight=6.78 foot"; 152 assertMatch: "node maxheight=5 Feet"; 153 assertMatch: "node maxheight=2 '"; 154 assertNoMatch: "node maxheight=2'"; 155 assertNoMatch: "node maxheight=5"; 156 assertMatch: "node roof:height=6.78 foot"; 157 assertMatch: "node roof:height=5 Feet"; 158 assertMatch: "node roof:height=2 '"; 159 assertNoMatch: "node roof:height=2'"; 160 assertNoMatch: "node roof:height=5"; 161 assertMatch: "node maxlength=6.78 foot"; 162 assertMatch: "node maxlength=5 Feet"; 163 assertMatch: "node maxlength=2 '"; 164 assertNoMatch: "node maxlength=2'"; 165 assertNoMatch: "node maxlength=5"; 226 166 assertMatch: "node width=6.78 foot"; 227 167 assertMatch: "node width=5 Feet"; 228 assertMatch: "node width=2 ft";229 assertNoMatch: "node width=2 ft";168 assertMatch: "node width=2 '"; 169 assertNoMatch: "node width=2'"; 230 170 assertNoMatch: "node width=5"; 231 } 232 *[width][width =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] { 171 assertMatch: "node maxwidth=6.78 foot"; 172 assertMatch: "node maxwidth=5 Feet"; 173 assertMatch: "node maxwidth=2 '"; 174 assertNoMatch: "node maxwidth=2'"; 175 assertNoMatch: "node maxwidth=5"; 176 } 177 178 /* 2. Convert `,` to `.` */ 179 *[height][height =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 180 *[maxheight][maxheight =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 181 *[roof:height][roof:height =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 182 *[maxlength][maxlength =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 183 *[width][width =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 184 *[maxwidth][maxwidth =~ /^[0-9]+,[0-9][0-9]?( m|\')?$/], 185 *[min_height][min_height =~ /^-?[0-9]+,[0-9][0-9]?( m|\')?$/], 186 *[maxaxleload][maxaxleload =~ /^[0-9]+,[0-9][0-9]?( (t|kg|st|lbs))?$/], 187 *[maxweight][maxweight =~ /^[0-9]+,[0-9][0-9]?( (t|kg|st|lbs))?$/], 188 *[distance][distance =~ /^[0-9]+,[0-9][0-9]?( (m|km|mi|nmi))?$/] { 189 set _unit_auto_fix; 233 190 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}"); 234 fixAdd: concat("width=", replace(tag("width"), ",", ".")); 235 set width_separator_autofix; 191 fixAdd: concat("{0.key}", "=", replace(tag("{0.key}"), ",", ".")); 192 assertMatch: "node height=5,5"; 193 assertMatch: "node height=12,00"; 194 assertMatch: "node height=12,5'"; 195 assertNoMatch: "node height=12,000"; 196 assertNoMatch: "node height=3,50,5"; 197 assertNoMatch: "node height=3.5"; 198 assertNoMatch: "node height=4"; 199 assertMatch: "node maxheight=5,5"; 200 assertMatch: "node maxheight=12,00"; 201 assertMatch: "node maxheight=12,5'"; 202 assertNoMatch: "node maxheight=12,000"; 203 assertNoMatch: "node maxheight=3,50,5"; 204 assertNoMatch: "node maxheight=3.5"; 205 assertNoMatch: "node maxheight=4"; 206 assertMatch: "node roof:height=5,5"; 207 assertMatch: "node roof:height=12,00"; 208 assertMatch: "node roof:height=12,5'"; 209 assertNoMatch: "node roof:height=12,000"; 210 assertNoMatch: "node roof:height=3,50,5"; 211 assertNoMatch: "node roof:height=3.5"; 212 assertNoMatch: "node roof:height=4"; 213 assertMatch: "node maxlength=5,5"; 214 assertMatch: "node maxlength=12,00"; 215 assertMatch: "node maxlength=12,5'"; 216 assertNoMatch: "node maxlength=12,000"; 217 assertNoMatch: "node maxlength=3,50,5"; 218 assertNoMatch: "node maxlength=3.5"; 219 assertNoMatch: "node maxlength=4"; 236 220 assertMatch: "node width=5,5"; 237 221 assertMatch: "node width=12,00"; … … 240 224 assertNoMatch: "node width=3.5"; 241 225 assertNoMatch: "node width=4"; 242 }243 244 *[maxwidth][maxwidth=~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {245 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");246 set maxwidth_meter_autofix;247 fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxwidth")),1)," m");248 assertMatch: "node maxwidth=6.78 meters";249 assertMatch: "node maxwidth=5 metre";250 assertMatch: "node maxwidth=2m";251 assertNoMatch: "node maxwidth=2 m";252 assertNoMatch: "node maxwidth=5";253 }254 *[maxwidth][maxwidth =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {255 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");256 set maxwidth_foot_autofix;257 fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxwidth")),1)," ft");258 assertMatch: "node maxwidth=6.78 foot";259 assertMatch: "node maxwidth=5 Feet";260 assertMatch: "node maxwidth=2ft";261 assertNoMatch: "node maxwidth=2 ft";262 assertNoMatch: "node maxwidth=5";263 }264 *[maxwidth][maxwidth =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {265 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");266 fixAdd: concat("maxwidth=", replace(tag("maxwidth"), ",", "."));267 set maxwidth_separator_autofix;268 226 assertMatch: "node maxwidth=5,5"; 269 227 assertMatch: "node maxwidth=12,00"; … … 272 230 assertNoMatch: "node maxwidth=3.5"; 273 231 assertNoMatch: "node maxwidth=4"; 274 } 275 276 *[height ][height !~ /^(([0-9]+(\.[0-9]+)?( (m|ft))?)|([1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!.height_separator_autofix!.height_meter_autofix!.height_foot_autofix, 277 *[maxheight ][maxheight !~ /^(([1-9][0-9]*(\.[0-9]+)?( (m|ft))?)|([0-9]+\'(([0-9]|10|11)(\.[0-9]*)?\")?)|none|default|below_default)$/]!.maxheight_separator_autofix!.maxheight_meter_autofix!.maxheight_foot_autofix, 278 *[roof:height][roof:height !~ /^(([0-9]+(\.[0-9]+)?( (m|ft))?)|([1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!.roof_height_separator_autofix!.roof_height_meter_autofix!.roof_height_foot_autofix!.zero_roof_height_flat, 279 *[maxlength ][maxlength !~ /^(([1-9][0-9]*(\.[0-9]+)?( (m|ft))?)|([0-9]+\'(([0-9]|10|11)(\.[0-9]*)?\")?)|none|default|below_default)$/]!.maxlength_separator_autofix!.maxlength_meter_autofix!.maxlength_foot_autofix, 280 *[width ][width !~ /^(([0-9]+(\.[0-9]+)?( (m|ft))?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/]!.width_separator_autofix!.width_meter_autofix!.width_foot_autofix, 281 *[maxwidth ][maxwidth !~ /^(([0-9]+(\.[0-9]+)?( (m|ft))?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/]!.maxwidth_separator_autofix!.maxwidth_meter_autofix!.maxwidth_foot_autofix { 282 throwWarning: tr("unusual value of {0}: {1} is default; only positive values; point is decimal separator; if units, put space then unit", "{0.key}", tr("meters")); 232 assertMatch: "node min_height=5,5"; 233 assertMatch: "node min_height=12,00"; 234 assertMatch: "node min_height=12,5'"; 235 assertNoMatch: "node min_height=12,000"; 236 assertNoMatch: "node min_height=3,50,5"; 237 assertNoMatch: "node min_height=3.5"; 238 assertNoMatch: "node min_height=4"; 239 assertMatch: "node maxaxleload=5,5"; 240 assertMatch: "node maxaxleload=12,00"; 241 assertNoMatch: "node maxaxleload=12,000"; 242 assertNoMatch: "node maxaxleload=3,50,5"; 243 assertNoMatch: "node maxaxleload=3.5"; 244 assertNoMatch: "node maxaxleload=4"; 245 assertMatch: "node maxweight=5,5"; 246 assertMatch: "node maxweight=12,00"; 247 assertNoMatch: "node maxweight=12,000"; 248 assertNoMatch: "node maxweight=3,50,5"; 249 assertNoMatch: "node maxweight=3.5"; 250 assertNoMatch: "node maxweight=4"; 251 assertMatch: "node distance=5,5"; 252 assertMatch: "node distance=12,00"; 253 assertNoMatch: "node distance=12,000"; 254 assertNoMatch: "node distance=3,50,5"; 255 assertNoMatch: "node distance=3.5"; 256 assertNoMatch: "node distance=4"; 257 } 258 /* 3. Convert to the default unit for usage later. Use the tag prefixed with _. */ 259 /* 4. Start doing comparison checks. */ 260 261 *[height ][height !~ /^(([0-9]+(\.[0-9]+)?( m)?)|([1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!._unit_auto_fix, 262 *[maxheight ][maxheight !~ /^(([1-9][0-9]*(\.[0-9]+)?( m)?)|([0-9]+\'(([0-9]|10|11)(\.[0-9]*)?\")?)|none|default|below_default)$/]!._unit_auto_fix, 263 *[min_height ][min_height !~ /^(-?([0-9]+(\.[0-9]+)?( m)?)|(-?[1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!._unit_auto_fix, 264 *[roof:height][roof:height !~ /^(([0-9]+(\.[0-9]+)?( m)?)|([1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!.zero_roof_height_flat!._unit_auto_fix, 265 *[maxlength ][maxlength !~ /^(([1-9][0-9]*(\.[0-9]+)?( m)?)|([0-9]+\'(([0-9]|10|11)(\.[0-9]*)?\")?)|none|default|below_default)$/]!._unit_auto_fix, 266 *[width ][width !~ /^(([0-9]+(\.[0-9]+)?( m)?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/]!._unit_auto_fix, 267 *[maxwidth ][maxwidth !~ /^(([0-9]+(\.[0-9]+)?( m)?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/]!._unit_auto_fix { 268 throwWarning: tr("unusual value of {0}: meters is default; only positive values; point is decimal separator; if units, put space then unit", "{0.key}"); 283 269 assertMatch: "node height=medium"; 284 270 assertMatch: "node maxheight=-5"; … … 288 274 assertMatch: "node maxheight=\"2. m\""; 289 275 assertMatch: "node height=\"12. m\""; 290 assertNoMatch: "node height=6.78 m eters";291 assertNoMatch: "node height=5 m etre";292 assertNoMatch: "node height=2 m";276 assertNoMatch: "node height=6.78 m"; 277 assertNoMatch: "node height=5 m"; 278 assertNoMatch: "node height=2 m"; 293 279 assertNoMatch: "node height=3"; 294 280 assertNoMatch: "node height=2.22 m"; 295 281 assertNoMatch: "node height=7.8"; 296 assertNoMatch: "node maxwidth=7 ft"; 282 assertMatch: "node min_height=\"12. m\""; 283 assertNoMatch: "node min_height=-5"; 284 assertNoMatch: "node maxwidth=7'"; 297 285 assertNoMatch: "node height=22'"; 298 286 assertNoMatch: "node width=10'5\""; … … 300 288 } 301 289 302 *[min_height][min_height =~ /^-?[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] { 303 throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}"); 304 fixAdd: concat("min_height=", get(regexp_match("(-?[0-9.]+)( )*(.+)",tag("min_height")),1)," m"); 305 set min_height_meter_autofix; 306 assertMatch: "node min_height=6.78 meters"; 307 assertMatch: "node min_height=5 metre"; 308 assertMatch: "node min_height=2m"; 309 assertNoMatch: "node min_height=2 m"; 310 assertNoMatch: "node min_height=5"; 311 } 312 *[min_height][min_height =~ /^-?[0-9]+,[0-9][0-9]?( m|\')?$/] { 313 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}"); 314 fixAdd: concat("min_height=", replace(tag("min_height"), ",", ".")); 315 set min_height_separator_autofix; 316 assertMatch: "node min_height=5,5"; 317 assertMatch: "node min_height=12,00"; 318 assertMatch: "node min_height=12,5'"; 319 assertNoMatch: "node min_height=12,000"; 320 assertNoMatch: "node min_height=3,50,5"; 321 assertNoMatch: "node min_height=3.5"; 322 assertNoMatch: "node min_height=4"; 323 } 324 *[min_height ][min_height !~ /^(-?([0-9]+(\.[0-9]+)?( m)?)|(-?[1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!.min_height_separator_autofix!.min_height_meter_autofix!.min_height_foot_autofix { 325 throwWarning: tr("unusual value of {0}: {1} is default; point is decimal separator; if units, put space then unit", "{0.key}", tr("meters")); 326 assertMatch: "node min_height=\"12. m\""; 327 assertNoMatch: "node min_height=-5"; 328 } 329 330 *[maxaxleload][maxaxleload =~ /^[0-9]+,[0-9][0-9]?( (t|kg|st|lbs))?$/] { 331 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}"); 332 fixAdd: concat("maxaxleload=", replace(tag("maxaxleload"), ",", ".")); 333 set maxaxleload_separator_autofix; 334 assertMatch: "node maxaxleload=5,5"; 335 assertMatch: "node maxaxleload=12,00"; 336 assertNoMatch: "node maxaxleload=12,000"; 337 assertNoMatch: "node maxaxleload=3,50,5"; 338 assertNoMatch: "node maxaxleload=3.5"; 339 assertNoMatch: "node maxaxleload=4"; 340 } 341 342 *[maxweight][maxweight =~ /^[0-9]+,[0-9][0-9]?( (t|kg|st|lbs))?$/] { 343 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}"); 344 fixAdd: concat("maxweight=", replace(tag("maxweight"), ",", ".")); 345 set maxweight_separator_autofix; 346 assertMatch: "node maxweight=5,5"; 347 assertMatch: "node maxweight=12,00"; 348 assertNoMatch: "node maxweight=12,000"; 349 assertNoMatch: "node maxweight=3,50,5"; 350 assertNoMatch: "node maxweight=3.5"; 351 assertNoMatch: "node maxweight=4"; 352 } 353 354 *[maxaxleload][maxaxleload !~ /^([0-9]+(\.[0-9]+)?( (t|kg|st|lbs))?)$/]!.maxaxleload_separator_autofix, 355 *[maxweight][maxweight !~ /^([0-9]+(\.[0-9]+)?( (t|kg|st|lbs))?)$/]!.maxweight_separator_autofix { 290 *[maxaxleload][maxaxleload !~ /^([0-9]+(\.[0-9]+)?( (t|kg|st|lbs))?)$/], 291 *[maxweight][maxweight !~ /^([0-9]+(\.[0-9]+)?( (t|kg|st|lbs))?)$/] { 356 292 throwWarning: tr("unusual value of {0}: {1} is default; only positive values; point is decimal separator; if units, put space then unit", "{0.key}", tr("tonne")); 357 293 assertMatch: "node maxaxleload=something"; … … 380 316 } 381 317 382 *[distance][distance =~ /^[0-9]+,[0-9][0-9]?( (m|km|mi|nmi))?$/] { 383 throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}"); 384 fixAdd: concat("distance=", replace(tag("distance"), ",", ".")); 385 set distance_separator_autofix; 386 assertMatch: "node distance=5,5"; 387 assertMatch: "node distance=12,00"; 388 assertNoMatch: "node distance=12,000"; 389 assertNoMatch: "node distance=3,50,5"; 390 assertNoMatch: "node distance=3.5"; 391 assertNoMatch: "node distance=4"; 392 } 393 *[distance][distance !~ /^(([0-9]+(\.[0-9]+)?( (m|km|mi|nmi))?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/]!.distance_separator_autofix { 318 *[distance][distance !~ /^(([0-9]+(\.[0-9]+)?( (m|km|mi|nmi))?)|([0-9]+\'([0-9]+(\.[0-9]+)?\")?))$/] { 394 319 throwWarning: tr("unusual value of {0}: {1} is default; only positive values; point is decimal separator; if units, put space then unit", "{0.key}", tr("kilometers")); 395 320 assertMatch: "way distance=something"; … … 421 346 assertNoMatch: "way frequency=123.5 MHz"; 422 347 } 348 349 /******************* 350 * End Unit checks * 351 *******************/ 423 352 424 353 way[gauge][gauge =~ /^(broad|standard|narrow)$/], … … 524 453 assertNoMatch: "node direction=45-100;190-250;300"; 525 454 assertNoMatch: "node direction=90;270"; 526 assertNoMatch: "node direction=up"; 455 assertNoMatch: "node direction=up"; 527 456 assertNoMatch: "node direction=down"; /* up/down are replaced by incline tag, has separate warning */ 528 457 assertMatch: "node direction=-10"; -
trunk/resources/data/validator/wikipedia.mapcss
r18509 r18757 55 55 *[/^wikipedia:[-a-z]{2,12}$/][/^wikipedia:[-a-z]{2,12}$/ =~ /(?i).*%[0-9A-F][0-9A-F]/] { 56 56 throwError: tr("{0} tag should not have URL-encoded values like ''%27''", "{0.key}"); 57 /* fixAdd: concat("{0.key}", "=", get(regexp_match("(?i)^([-a-z]+:)(.*)$", tag("{0.key}")),1), trim(replace(URL_decode(get(regexp_match("(?i)^([-a-z]+:)(.+)$", tag("{0.key}")),2)), "_", " "))); */ 58 /* tag("{0.key}") is not yet supported */ 57 fixAdd: concat("{0.key}", "=", get(regexp_match("(?i)^([-a-z]+:)?(.*)$", tag("{0.key}")),1), trim(replace(URL_decode(get(println(regexp_match("(?i)^([-a-z]+:)?(.+)$", tag("{0.key}"))),2)), "_", " "))); 59 58 assertMatch: "node wikipedia:de=Foo%27s"; 60 59 assertNoMatch: "node wikipedia:de=Foo"; -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
r18365 r18757 232 232 final Selector selector = check.whichSelectorMatchesEnvironment(env); 233 233 if (selector != null) { 234 check.rule.declaration.execute(env); 234 final Environment envWithSelector = env.withSelector(selector); 235 check.rule.declaration.execute(envWithSelector); 235 236 if (!ignoreError && !check.errors.isEmpty()) { 236 r.addAll(check.getErrorsForPrimitive(p, selector, env , new MapCSSTagCheckerAndRule(check.rule)));237 r.addAll(check.getErrorsForPrimitive(p, selector, envWithSelector, new MapCSSTagCheckerAndRule(check.rule))); 237 238 } 238 239 } -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerAsserts.java
r18365 r18757 75 75 Command fix = check.fixPrimitive(p); 76 76 if (fix != null && fix.executeCommand() && !MapCSSTagChecker.getErrorsForPrimitive(p, true, checksToRun).isEmpty()) { 77 assertionConsumer.accept(MessageFormat.format("Autofix does not work for test ''{0}'' (i.e., {1}) ",78 check.getMessage(p), check.rule.selectors ));77 assertionConsumer.accept(MessageFormat.format("Autofix does not work for test ''{0}'' (i.e., {1}). Failing test: {2}", 78 check.getMessage(p), check.rule.selectors, i.getKey())); 79 79 } 80 80 } -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerFixCommand.java
r17620 r18757 49 49 final String s; 50 50 if (obj instanceof Expression) { 51 s = (String) ((Expression) obj).evaluate(new Environment(p) );51 s = (String) ((Expression) obj).evaluate(new Environment(p).withSelector(matchingSelector)); 52 52 } else if (obj instanceof String) { 53 53 s = (String) obj; -
trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerRule.java
r18365 r18757 18 18 import java.util.function.Consumer; 19 19 import java.util.function.Predicate; 20 import java.util.regex.Matcher;21 import java.util.regex.Pattern;22 20 import java.util.stream.Collectors; 23 21 … … 27 25 import org.openstreetmap.josm.data.osm.IPrimitive; 28 26 import org.openstreetmap.josm.data.osm.OsmPrimitive; 29 import org.openstreetmap.josm.data.osm.Tag;30 27 import org.openstreetmap.josm.data.osm.Way; 31 28 import org.openstreetmap.josm.data.osm.WaySegment; … … 35 32 import org.openstreetmap.josm.gui.mappaint.Environment; 36 33 import org.openstreetmap.josm.gui.mappaint.Keyword; 34 import org.openstreetmap.josm.gui.mappaint.MultiCascade; 37 35 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition; 38 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;39 36 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression; 40 37 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction; 41 38 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule; 42 39 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource; 40 import org.openstreetmap.josm.gui.mappaint.mapcss.PlaceholderExpression; 43 41 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 44 42 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser; … … 215 213 216 214 Selector whichSelectorMatchesPrimitive(OsmPrimitive primitive) { 217 return whichSelectorMatchesEnvironment(new Environment(primitive ));215 return whichSelectorMatchesEnvironment(new Environment(primitive, new MultiCascade(), Environment.DEFAULT_LAYER, null)); 218 216 } 219 217 … … 226 224 227 225 /** 228 * Determines the {@code index}-th key/value/tag (depending on {@code type}) of the229 * {@link org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector}.230 *231 * @param matchingSelector matching selector232 * @param index index233 * @param type selector type ("key", "value" or "tag")234 * @param p OSM primitive235 * @return argument value, can be {@code null}236 */237 static String determineArgument(Selector.GeneralSelector matchingSelector, int index, String type, OsmPrimitive p) {238 try {239 final Condition c = matchingSelector.getConditions().get(index);240 final Tag tag = c instanceof TagCondition241 ? ((TagCondition) c).asTag(p)242 : null;243 if (tag == null) {244 return null;245 } else if ("key".equals(type)) {246 return tag.getKey();247 } else if ("value".equals(type)) {248 return tag.getValue();249 } else if ("tag".equals(type)) {250 return tag.toString();251 }252 } catch (IndexOutOfBoundsException ignore) {253 Logging.debug(ignore);254 }255 return null;256 }257 258 /**259 226 * Replaces occurrences of <code>{i.key}</code>, <code>{i.value}</code>, <code>{i.tag}</code> in {@code s} by the corresponding 260 227 * key/value/tag of the {@code index}-th {@link Condition} of {@code matchingSelector}. … … 266 233 */ 267 234 static String insertArguments(Selector matchingSelector, String s, OsmPrimitive p) { 268 if (s != null && matchingSelector instanceof Selector.ChildOrParentSelector) { 269 return insertArguments(((Selector.ChildOrParentSelector) matchingSelector).right, s, p); 270 } else if (s == null || !(matchingSelector instanceof Selector.GeneralSelector)) { 271 return s; 272 } 273 final Matcher m = Pattern.compile("\\{(\\d+)\\.(key|value|tag)\\}").matcher(s); 274 final StringBuffer sb = new StringBuffer(); 275 while (m.find()) { 276 final String argument = determineArgument((Selector.GeneralSelector) matchingSelector, 277 Integer.parseInt(m.group(1)), m.group(2), p); 278 try { 279 // Perform replacement with null-safe + regex-safe handling 280 m.appendReplacement(sb, String.valueOf(argument).replace("^(", "").replace(")$", "")); 281 } catch (IndexOutOfBoundsException | IllegalArgumentException e) { 282 Logging.log(Logging.LEVEL_ERROR, tr("Unable to replace argument {0} in {1}: {2}", argument, sb, e.getMessage()), e); 283 } 284 } 285 m.appendTail(sb); 286 return sb.toString(); 235 return PlaceholderExpression.insertArguments(matchingSelector, s, p); 287 236 } 288 237 … … 329 278 return String.valueOf( 330 279 val instanceof Expression 331 ? ((Expression) val).evaluate(new Environment(p) )280 ? ((Expression) val).evaluate(new Environment(p).withSelector(p == null ? null : whichSelectorMatchesPrimitive(p))) 332 281 : val 333 282 ); -
trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java
r18275 r18757 13 13 import org.openstreetmap.josm.data.osm.WaySegment; 14 14 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; 15 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 15 16 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector; 16 17 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 42 43 private Context context = Context.PRIMITIVE; 43 44 45 /** The selector that is currently being evaluated */ 46 private final Selector selector; 47 44 48 /** 45 49 * The name of the default layer. It is used if no layer is specified in the MapCSS rule … … 98 102 public Environment() { 99 103 // environment can be initialized later through with* methods 104 this.selector = null; 100 105 } 101 106 … … 107 112 */ 108 113 public Environment(IPrimitive osm) { 109 this .osm = osm;114 this(osm, null, null, null); 110 115 } 111 116 … … 123 128 this.layer = layer; 124 129 this.source = source; 130 this.selector = null; 125 131 } 126 132 … … 132 138 */ 133 139 public Environment(Environment other) { 140 this(other, other.selector); 141 } 142 143 /** 144 * Creates a clone of the environment {@code other}. 145 * 146 * @param other the other environment. Must not be null. 147 * @param selector the selector for this environment. May be null. 148 * @throws IllegalArgumentException if {@code param} is {@code null} 149 */ 150 private Environment(Environment other, Selector selector) { 134 151 CheckParameterUtil.ensureParameterNotNull(other); 135 152 this.osm = other.osm; … … 147 164 this.mpAreaCache = other.mpAreaCache; 148 165 this.toMatchForSurrounding = other.toMatchForSurrounding; 166 this.selector = selector; 149 167 } 150 168 … … 264 282 265 283 /** 284 * Creates a clone of this environment, with the selector set 285 * @param selector The selector to use 286 * @return A clone of this environment, with the specified selector 287 * @since xxx 288 */ 289 public Environment withSelector(Selector selector) { 290 return new Environment(this, selector); 291 } 292 293 /** 266 294 * Determines if the context of this environment is {@link Context#LINK}. 267 295 * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise … … 302 330 return ((Relation) osm).getMember(index).getRole(); 303 331 return null; 332 } 333 334 /** 335 * Get the selector for this environment 336 * @return The selector. May be {@code null}. 337 * @since xxx 338 */ 339 public Selector selector() { 340 return this.selector; 304 341 } 305 342 -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
r18712 r18757 32 32 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule; 33 33 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource; 34 import org.openstreetmap.josm.gui.mappaint.mapcss.PlaceholderExpression; 34 35 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; 35 36 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector; … … 1053 1054 if (lit == null) 1054 1055 return NullExpression.INSTANCE; 1056 else if (lit instanceof String && PlaceholderExpression.PATTERN_PLACEHOLDER.matcher((String) lit).find()) { 1057 return new PlaceholderExpression((String) lit); 1058 } 1055 1059 return new LiteralExpression(lit); 1056 1060 } -
trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java
r18690 r18757 44 44 import org.openstreetmap.josm.io.OsmReader; 45 45 import org.openstreetmap.josm.testutils.JOSMTestRules; 46 import org.openstreetmap.josm.testutils.annotations.BasicPreferences; 47 import org.openstreetmap.josm.testutils.annotations.Projection; 46 48 import org.openstreetmap.josm.tools.Logging; 47 49 … … 51 53 * JUnit Test of {@link MapCSSTagChecker}. 52 54 */ 55 @BasicPreferences 56 @Projection 53 57 class MapCSSTagCheckerTest { 54 58 … … 58 62 @RegisterExtension 59 63 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 60 public JOSMTestRules test = new JOSMTestRules(). projection().territories().preferences();64 public JOSMTestRules test = new JOSMTestRules().territories(); 61 65 62 66 /** … … 96 100 assertNotNull(check); 97 101 assertEquals("{0.key}=null is deprecated", check.getDescription(null)); 98 assertEquals("fixRemove: {0.key}", check.fixCommands.get(0).toString());102 assertEquals("fixRemove: <{0.key}>", check.fixCommands.get(0).toString()); 99 103 assertEquals("fixAdd: natural=wetland", check.fixCommands.get(1).toString()); 100 104 assertEquals("fixAdd: wetland=marsh", check.fixCommands.get(2).toString());
Note:
See TracChangeset
for help on using the changeset viewer.