Skip to content

Commit 3844e43

Browse files
authored
MixedCaseNameCheck Enhancements (without AutoFix) (#546)
* fixing rebase issues. * Revert "fixing rebase issues." This reverts commit 4573d4a * fixing ci issues. * reverting commit. * MixedCaseNameCheck Autofix initial draft * Removed AutoFix, added more handling and unittest * code smells: reduce number of Cognitive Complexity. * code smells: reduce number of Cognitive Complexity 2. * adding more handling to 'n' case. * minor fix
1 parent 9cc4d42 commit 3844e43

File tree

4 files changed

+157
-6
lines changed

4 files changed

+157
-6
lines changed

config/configuration.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,8 @@
696696
"language.keys":["name:en"],
697697
"affixes":["Mc", "Mac", "Mck","Mhic", "Mic"],
698698
"articles": ["a", "an", "the"],
699-
"prepositions": ["and", "from", "to", "of", "by", "upon", "on", "off", "at", "as",
700-
"into", "like", "near", "onto", "per", "till", "up", "via", "with", "for", "in"],
699+
"prepositions": ["and", "from", "to", "of", "by", "upon", "on", "off", "at", "as", "into", "like", "near",
700+
"onto", "per", "till", "up", "via", "with", "for", "in", "de", "la", "del", "du", "van", "der"],
701701
"units":["kv"]
702702
},
703703
"regex.split":" -/&@–",

src/main/java/org/openstreetmap/atlas/checks/validation/tag/MixedCaseNameCheck.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
import org.openstreetmap.atlas.geography.atlas.items.LocationItem;
1616
import org.openstreetmap.atlas.geography.atlas.items.Relation;
1717
import org.openstreetmap.atlas.geography.atlas.walker.OsmWayWalker;
18+
import org.openstreetmap.atlas.tags.AmenityTag;
19+
import org.openstreetmap.atlas.tags.BrandTag;
1820
import org.openstreetmap.atlas.tags.ISOCountryTag;
21+
import org.openstreetmap.atlas.tags.LeisureTag;
22+
import org.openstreetmap.atlas.tags.ShopTag;
1923
import org.openstreetmap.atlas.tags.annotations.validation.Validators;
2024
import org.openstreetmap.atlas.tags.names.NameTag;
2125
import org.openstreetmap.atlas.utilities.configuration.Configuration;
@@ -40,7 +44,7 @@ public class MixedCaseNameCheck extends BaseCheck<String>
4044
private static final List<String> LANGUAGE_NAME_TAGS_DEFAULT = Arrays.asList("name:en");
4145
private static final List<String> LOWER_CASE_PREPOSITIONS_DEFAULT = Arrays.asList("and", "from",
4246
"to", "of", "by", "upon", "on", "off", "at", "as", "into", "like", "near", "onto",
43-
"per", "till", "up", "via", "with", "for", "in");
47+
"per", "till", "up", "via", "with", "for", "in", "de", "la", "del", "du", "van", "der");
4448
private static final List<String> LOWER_CASE_ARTICLES_DEFAULT = Arrays.asList("a", "an", "the");
4549
private static final String SPLIT_CHARACTERS_DEFAULT = " -/&@–";
4650
private static final List<String> NAME_AFFIXES_DEFAULT = Arrays.asList("Mc", "Mac", "Mck",
@@ -69,6 +73,8 @@ public class MixedCaseNameCheck extends BaseCheck<String>
6973
private final Pattern mixedCaseUnitsPattern;
7074
private final Pattern mixedCaseApostrophePattern;
7175
private final Pattern nonFirstCapitalPattern;
76+
private final Pattern iCasePattern;
77+
private final Pattern dashAndDashPattern;
7278

7379
/**
7480
* The default constructor that must be supplied. The Atlas Checks framework will generate the
@@ -106,6 +112,8 @@ public MixedCaseNameCheck(final Configuration configuration)
106112
.compile("([^\\p{Ll}]+'\\p{Ll})|([^\\p{Ll}]+\\p{Ll}')");
107113
this.nonFirstCapitalPattern = Pattern.compile(String.format(
108114
"(\\p{L}.*(?<!'|%1$s)(\\p{Lu}))|(\\p{L}.*(?<=')\\p{Lu}(?!.))", this.nameAffixes));
115+
this.iCasePattern = Pattern.compile("^i[A-Z]");
116+
this.dashAndDashPattern = Pattern.compile("^n$|^n'$|^'n$|^'n'$");
109117
}
110118

111119
/**
@@ -127,6 +135,10 @@ public boolean validCheckForObject(final AtlasObject object)
127135
.contains(object.tag(ISOCountryTag.KEY).toUpperCase())
128136
// And have a name tag
129137
&& Validators.hasValuesFor(object, NameTag.class)
138+
// Excluding names with following tags to reduce number of legit
139+
// MixedCaseNames
140+
&& !Validators.hasValuesFor(object, BrandTag.class, ShopTag.class,
141+
AmenityTag.class, LeisureTag.class)
130142
// And if an Edge, is a main edge
131143
&& (!(object instanceof Edge) || ((Edge) object).isMainEdge())
132144
// Or it must have a specific language name tag from languageNameTags
@@ -191,6 +203,44 @@ protected List<String> getFallbackInstructions()
191203
return FALLBACK_INSTRUCTIONS;
192204
}
193205

206+
/**
207+
* Tests if {@link String} matches one of the patterns.
208+
*
209+
* @param word
210+
* {@link String} to test
211+
* @return true if {@code word} matches the {@code dashAndDashPattern} or {@code iCasePattern}.
212+
*/
213+
private boolean isAlowedPatternHandling(final String word)
214+
{
215+
return this.isMixedCaseUnit(word) || this.isICase(word) || this.isDashAndDashCase(word);
216+
}
217+
218+
/**
219+
* Tests if {@link String} is "n" or "'n"
220+
*
221+
* @param word
222+
* {@link String} to test
223+
* @return true if {@code word} matches the {@code dashAndDashPattern}.
224+
*/
225+
private boolean isDashAndDashCase(final String word)
226+
{
227+
// return true for following cases: Rock-n-Roll, Rock n' Roll
228+
return this.dashAndDashPattern.matcher(word).find();
229+
}
230+
231+
/**
232+
* Tests if {@link String} starts with lower "i" character followed by capital letter.
233+
*
234+
* @param word
235+
* {@link String} to test
236+
* @return true if {@code word} matches the {@code iCasePattern}.
237+
*/
238+
private boolean isICase(final String word)
239+
{
240+
// return true for following cases: iExample, iCode
241+
return this.iCasePattern.matcher(word).find();
242+
}
243+
194244
/**
195245
* Tests each word in a string for proper use of case in a name.
196246
*
@@ -210,7 +260,7 @@ private boolean isMixedCase(final String value)
210260
for (final String word : wordArray)
211261
{
212262
// Check if the word is intentionally mixed case
213-
if (!this.isMixedCaseUnit(word))
263+
if (!this.isAlowedPatternHandling(word))
214264
{
215265
final Matcher firstLetterMatcher = this.anyLetterPattern.matcher(word);
216266
// If the word is not in the list of prepositions, and the

src/test/java/org/openstreetmap/atlas/checks/validation/tag/MixedCaseNameCheckTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ public void invalidNameEdgeTest()
3939
this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size()));
4040
}
4141

42+
@Test
43+
public void invalidNameICase()
44+
{
45+
this.verifier.actual(this.setup.invalidNameICase(),
46+
new MixedCaseNameCheck(this.inlineConfiguration));
47+
this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size()));
48+
}
49+
50+
@Test
51+
public void invalidNameICaseMiddle()
52+
{
53+
this.verifier.actual(this.setup.invalidNameICaseMiddle(),
54+
new MixedCaseNameCheck(this.inlineConfiguration));
55+
this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size()));
56+
}
57+
4258
@Test
4359
public void invalidNameLineTest()
4460
{
@@ -135,6 +151,15 @@ public void invalidNamePointTest()
135151
this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size()));
136152
}
137153

154+
@Test
155+
public void validNameICase()
156+
{
157+
// Example: iRobot
158+
this.verifier.actual(this.setup.validNameICase(),
159+
new MixedCaseNameCheck(this.inlineConfiguration));
160+
this.verifier.globallyVerify(flags -> Assert.assertEquals(0, flags.size()));
161+
}
162+
138163
@Test
139164
public void validNamePointAffixTest()
140165
{
@@ -199,6 +224,15 @@ public void validNamePointChnTest()
199224
this.verifier.globallyVerify(flags -> Assert.assertEquals(0, flags.size()));
200225
}
201226

227+
@Test
228+
public void validNamePointDashAndDashTest()
229+
{
230+
// example: Rock-n-Roll
231+
this.verifier.actual(this.setup.validNamePointDashAndDash(),
232+
new MixedCaseNameCheck(this.inlineConfiguration));
233+
this.verifier.globallyVerify(flags -> Assert.assertEquals(0, flags.size()));
234+
}
235+
202236
@Test
203237
public void validNamePointGreekElTest()
204238
{

src/test/java/org/openstreetmap/atlas/checks/validation/tag/MixedCaseNameCheckTestRule.java

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,34 @@ public class MixedCaseNameCheckTestRule extends CoreTestRule
140140

141141
@TestAtlas(
142142
// points
143-
points = { @Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
144-
"name=Test of Test" }) })
143+
points = {
144+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
145+
"name=Test-n-Test" }),
146+
@Point(coordinates = @Loc(value = TEST_2), tags = { "iso_country_code=USA",
147+
"name=Test n' Test" }),
148+
@Point(coordinates = @Loc(value = TEST_2), tags = { "iso_country_code=USA",
149+
"name=Test 'n Test" }),
150+
@Point(coordinates = @Loc(value = TEST_2), tags = { "iso_country_code=USA",
151+
"name=Test 'n' Test" }) })
152+
private Atlas validNamePointDashAndDash;
153+
154+
@TestAtlas(
155+
// points
156+
points = {
157+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
158+
"name=Test of Test" }),
159+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
160+
"name=Plaza de la Test" }),
161+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
162+
"name=Via del Test" }),
163+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
164+
"name=Test de Test" }),
165+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
166+
"name=Test of Test" }),
167+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
168+
"name=Test van der Test" }),
169+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
170+
"name=Test du Test" }) })
145171
private Atlas validNamePointLowerCasePrepositionAtlas;
146172

147173
@TestAtlas(
@@ -210,6 +236,27 @@ public class MixedCaseNameCheckTestRule extends CoreTestRule
210236
"name:en=Test of Test", "name=tEst TeSt" }) })
211237
private Atlas validNamePointChnAtlas;
212238

239+
@TestAtlas(
240+
// points
241+
points = {
242+
@Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
243+
"name:en=iTest", "name=iTest" }),
244+
@Point(coordinates = @Loc(value = TEST_2), tags = { "iso_country_code=USA",
245+
"name=Test of iTest Middle" }) })
246+
private Atlas validNameICase;
247+
248+
@TestAtlas(
249+
// points
250+
points = { @Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
251+
"name=itest Corp" }) })
252+
private Atlas invalidNameICase;
253+
254+
@TestAtlas(
255+
// points
256+
points = { @Point(coordinates = @Loc(value = TEST_1), tags = { "iso_country_code=USA",
257+
"name=MiddleiTest" }) })
258+
private Atlas invalidNameICaseMiddle;
259+
213260
public Atlas invalidNameAreaAtlas()
214261
{
215262
return this.invalidNameAreaAtlas;
@@ -220,6 +267,16 @@ public Atlas invalidNameEdgeAtlas()
220267
return this.invalidNameEdgeAtlas;
221268
}
222269

270+
public Atlas invalidNameICase()
271+
{
272+
return this.invalidNameICase;
273+
}
274+
275+
public Atlas invalidNameICaseMiddle()
276+
{
277+
return this.invalidNameICaseMiddle;
278+
}
279+
223280
public Atlas invalidNameLineAtlas()
224281
{
225282
return this.invalidNameLineAtlas;
@@ -280,6 +337,11 @@ public Atlas invalidNamePointOneWordAtlas()
280337
return this.invalidNamePointOneWordAtlas;
281338
}
282339

340+
public Atlas validNameICase()
341+
{
342+
return this.validNameICase;
343+
}
344+
283345
public Atlas validNamePointAffixAtlas()
284346
{
285347
return this.validNamePointAffixAtlas;
@@ -320,6 +382,11 @@ public Atlas validNamePointChnAtlas()
320382
return this.validNamePointChnAtlas;
321383
}
322384

385+
public Atlas validNamePointDashAndDash()
386+
{
387+
return this.validNamePointDashAndDash;
388+
}
389+
323390
public Atlas validNamePointGreekAtlas()
324391
{
325392
return this.validNamePointGreekAtlas;

0 commit comments

Comments
 (0)