source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/NameMismatch.java

Last change on this file was 16643, checked in by simon04, 4 years ago

see #19334 - https://errorprone.info/bugpattern/StringSplitter

  • Property svn:eol-style set to native
File size: 4.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.util.Arrays;
8import java.util.List;
9import java.util.Map.Entry;
10import java.util.Set;
11import java.util.regex.Pattern;
12import java.util.stream.Collectors;
13
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.validation.Severity;
16import org.openstreetmap.josm.data.validation.Test;
17import org.openstreetmap.josm.data.validation.TestError;
18
19/**
20 * Check for missing name:* translations.
21 * <p>
22 * This test finds multilingual objects whose 'name' attribute is not
23 * equal to any 'name:*' attribute and not a composition of some
24 * 'name:*' attributes separated by ' - '.
25 * <p>
26 * For example, a node with name=Europe, name:de=Europa should have
27 * name:en=Europe to avoid triggering this test. An object with
28 * name='Suomi - Finland' should have at least name:fi=Suomi and
29 * name:sv=Finland to avoid a warning (name:et=Soome would not
30 * matter). Also, complain if an object has some name:* attribute but
31 * no name.
32 *
33 * @author Skela
34 */
35public class NameMismatch extends Test.TagTest {
36 protected static final int NAME_MISSING = 1501;
37 protected static final int NAME_TRANSLATION_MISSING = 1502;
38 private static final Pattern NAME_SPLIT_PATTERN = Pattern.compile(" - ");
39
40 private static final List<String> EXCLUSIONS = Arrays.asList(
41 "name:botanical",
42 "name:etymology:wikidata",
43 "name:full",
44 "name:genitive",
45 "name:left",
46 "name:prefix",
47 "name:right",
48 "name:source"
49 );
50
51 /**
52 * Constructs a new {@code NameMismatch} test.
53 */
54 public NameMismatch() {
55 super(tr("Missing name:* translation"),
56 tr("This test finds multilingual objects whose ''name'' attribute is not equal to some ''name:*'' attribute " +
57 "and not a composition of ''name:*'' attributes, e.g., Italia - Italien - Italy."));
58 }
59
60 /**
61 * Report a missing translation.
62 *
63 * @param p The primitive whose translation is missing
64 * @param name The name whose translation is missing
65 */
66 private void missingTranslation(OsmPrimitive p, String name) {
67 errors.add(TestError.builder(this, Severity.OTHER, NAME_TRANSLATION_MISSING)
68 .message(tr("Missing name:* translation"), marktr("Missing name:*={0}. Add tag with correct language key."), name)
69 .primitives(p)
70 .build());
71 }
72
73 /**
74 * Check a primitive for a name mismatch.
75 *
76 * @param p The primitive to be tested
77 */
78 @Override
79 public void check(OsmPrimitive p) {
80 if (!p.isTagged())
81 return;
82 Set<String> names = p.getKeys().entrySet().stream()
83 .filter(e -> e.getValue() != null && e.getKey().startsWith("name:") && !EXCLUSIONS.contains(e.getKey()))
84 .map(Entry::getValue)
85 .collect(Collectors.toSet());
86
87 if (names.isEmpty()) return;
88
89 String name = p.get("name");
90
91 if (name == null) {
92 errors.add(TestError.builder(this, Severity.OTHER, NAME_MISSING)
93 .message(tr("A name is missing, even though name:* exists."))
94 .primitives(p)
95 .build());
96 return;
97 }
98
99 if (names.contains(name)) return;
100 /* If name is not equal to one of the name:*, it should be a
101 composition of some (not necessarily all) name:* labels.
102 Check if this is the case. */
103
104 String[] splitNames = NAME_SPLIT_PATTERN.split(name, -1);
105 if (splitNames.length == 1) {
106 /* The name is not composed of multiple parts. Complain. */
107 missingTranslation(p, splitNames[0]);
108 return;
109 }
110
111 /* Check that each part corresponds to a translated name:*. */
112 for (String n : splitNames) {
113 if (!names.contains(n)) {
114 missingTranslation(p, n);
115 }
116 }
117 }
118
119 @Override
120 public boolean isPrimitiveUsable(OsmPrimitive p) {
121 return p.isTagged() && super.isPrimitiveUsable(p);
122 }
123
124}
Note: See TracBrowser for help on using the repository browser.