| | 1 | package org.openstreetmap.josm.plugins.validator.tests; |
| | 2 | |
| | 3 | import static org.openstreetmap.josm.tools.I18n.tr; |
| | 4 | |
| | 5 | import java.util.Collection; |
| | 6 | import java.util.HashSet; |
| | 7 | |
| | 8 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| | 9 | import org.openstreetmap.josm.plugins.validator.Severity; |
| | 10 | import org.openstreetmap.josm.plugins.validator.Test; |
| | 11 | import org.openstreetmap.josm.plugins.validator.TestError; |
| | 12 | |
| | 13 | /** |
| | 14 | * Check for name not equal to any name:* |
| | 15 | * <p> |
| | 16 | * This test finds multilingual objects whose 'name' attribute is not |
| | 17 | * equal to any 'name:*' attribute and not a composition of some |
| | 18 | * 'name:*' attributes separated by ' - '. For example, a node with |
| | 19 | * name=Europe, name:de=Europa should have name:en=Europe to avoid |
| | 20 | * triggering this test. |
| | 21 | * |
| | 22 | * @author Skela |
| | 23 | */ |
| | 24 | public class NameMismatch extends Test { |
| | 25 | protected static final int NAME_MISSING = 1501; |
| | 26 | protected static final int NAME_TRANSLATION_MISSING = 1502; |
| | 27 | |
| | 28 | public NameMismatch() { |
| | 29 | super(tr("Missing name:* translation."), |
| | 30 | tr("This test finds multilingual objects whose 'name' attribute is not equal to some 'name:*' attribute and not a composition of 'name:*' attributes, e.g., Italia-Italien-Italy.")); |
| | 31 | } |
| | 32 | |
| | 33 | /** |
| | 34 | * Report a missing translation. |
| | 35 | * |
| | 36 | * @param p The primitive whose translation is missing |
| | 37 | */ |
| | 38 | private void missingTranslation(OsmPrimitive p) { |
| | 39 | errors.add(new TestError(this, Severity.OTHER, |
| | 40 | tr("A name:* translation is missing."), |
| | 41 | NAME_TRANSLATION_MISSING, p)); |
| | 42 | } |
| | 43 | |
| | 44 | /** |
| | 45 | * Check a primitive for a name mismatch. |
| | 46 | * |
| | 47 | * @param p The primitive to be tested |
| | 48 | */ |
| | 49 | public void check(OsmPrimitive p) { |
| | 50 | HashSet<String> names = new HashSet<String>(); |
| | 51 | |
| | 52 | for (String key : p.keySet()) { |
| | 53 | if (key.startsWith("name:")) { |
| | 54 | String name_s = p.get(key); |
| | 55 | if (name_s != null) { |
| | 56 | names.add(name_s); |
| | 57 | } |
| | 58 | } |
| | 59 | } |
| | 60 | |
| | 61 | if (names.isEmpty()) return; |
| | 62 | |
| | 63 | String name = p.get("name"); |
| | 64 | |
| | 65 | if (name == null) |
| | 66 | errors.add(new TestError(this, Severity.OTHER, |
| | 67 | tr("A name is missing, even though name:* exists."), |
| | 68 | NAME_MISSING, p)); |
| | 69 | |
| | 70 | if (names.contains(name)) return; |
| | 71 | /* If name is not equal to one of the name:*, it should be a |
| | 72 | composition of some (not necessarily all) name:* labels. |
| | 73 | Check if this is the case. */ |
| | 74 | |
| | 75 | String split_names[] = name.split(" - "); |
| | 76 | if (split_names.length == 1) { |
| | 77 | /* The name is not composed of multiple parts. Complain. */ |
| | 78 | missingTranslation(p); |
| | 79 | return; |
| | 80 | } |
| | 81 | |
| | 82 | /* Check that each part corresponds to a translated name:*. */ |
| | 83 | for (String n : split_names) { |
| | 84 | if (!names.contains(n)) { |
| | 85 | missingTranslation(p); |
| | 86 | return; |
| | 87 | } |
| | 88 | } |
| | 89 | } |
| | 90 | |
| | 91 | /** |
| | 92 | * Checks a name mismatch in all primitives. |
| | 93 | * |
| | 94 | * @param selection The primitives to be tested |
| | 95 | */ |
| | 96 | @Override public void visit(Collection<OsmPrimitive> selection) { |
| | 97 | for (OsmPrimitive p : selection) |
| | 98 | if (!p.isDeleted() && !p.incomplete) |
| | 99 | check(p); |
| | 100 | } |
| | 101 | } |