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