| 1 | package org.openstreetmap.josm.data.validation.tests; |
|---|
| 2 | |
|---|
| 3 | import static org.openstreetmap.josm.tools.I18n.tr; |
|---|
| 4 | |
|---|
| 5 | import java.util.Collection; |
|---|
| 6 | import java.util.LinkedList; |
|---|
| 7 | import java.util.List; |
|---|
| 8 | |
|---|
| 9 | import org.openstreetmap.josm.command.ChangePropertyCommand; |
|---|
| 10 | import org.openstreetmap.josm.command.Command; |
|---|
| 11 | import org.openstreetmap.josm.command.SequenceCommand; |
|---|
| 12 | import org.openstreetmap.josm.data.osm.Node; |
|---|
| 13 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
|---|
| 14 | import org.openstreetmap.josm.data.osm.Relation; |
|---|
| 15 | import org.openstreetmap.josm.data.osm.Tag; |
|---|
| 16 | import org.openstreetmap.josm.data.osm.Way; |
|---|
| 17 | import org.openstreetmap.josm.data.validation.Severity; |
|---|
| 18 | import org.openstreetmap.josm.data.validation.Test; |
|---|
| 19 | import org.openstreetmap.josm.data.validation.TestError; |
|---|
| 20 | import org.openstreetmap.josm.tools.Utils; |
|---|
| 21 | |
|---|
| 22 | public class DeprecatedTags extends Test { |
|---|
| 23 | |
|---|
| 24 | private List<DeprecationCheck> checks = new LinkedList<DeprecationCheck>(); |
|---|
| 25 | |
|---|
| 26 | public DeprecatedTags() { |
|---|
| 27 | super(tr("Deprecated Tags"), tr("Checks and corrects deprecated tags.")); |
|---|
| 28 | checks.add(new DeprecationCheck(2101). |
|---|
| 29 | testAndRemove("barrier", "wire_fence"). |
|---|
| 30 | add("barrier", "fence"). |
|---|
| 31 | add("fence_type", "chain")); |
|---|
| 32 | checks.add(new DeprecationCheck(2102). |
|---|
| 33 | testAndRemove("barrier", "wood_fence"). |
|---|
| 34 | add("barrier", "fence"). |
|---|
| 35 | add("fence_type", "wood")); |
|---|
| 36 | checks.add(new DeprecationCheck(2103). |
|---|
| 37 | testAndRemove("highway", "ford"). |
|---|
| 38 | add("ford", "yes")); |
|---|
| 39 | // from http://wiki.openstreetmap.org/wiki/Deprecated_features |
|---|
| 40 | checks.add(new DeprecationCheck(2104). |
|---|
| 41 | test("class"). |
|---|
| 42 | alternative("highway")); |
|---|
| 43 | checks.add(new DeprecationCheck(2105). |
|---|
| 44 | testAndRemove("highway", "stile"). |
|---|
| 45 | add("barrier", "stile")); |
|---|
| 46 | checks.add(new DeprecationCheck(2106). |
|---|
| 47 | testAndRemove("highway", "incline"). |
|---|
| 48 | add("highway", "road"). |
|---|
| 49 | add("incline", "up")); |
|---|
| 50 | checks.add(new DeprecationCheck(2107). |
|---|
| 51 | testAndRemove("highway", "incline_steep"). |
|---|
| 52 | add("highway", "road"). |
|---|
| 53 | add("incline", "up")); |
|---|
| 54 | checks.add(new DeprecationCheck(2108). |
|---|
| 55 | testAndRemove("highway", "unsurfaced"). |
|---|
| 56 | add("highway", "road"). |
|---|
| 57 | add("incline", "unpaved")); |
|---|
| 58 | checks.add(new DeprecationCheck(2109). |
|---|
| 59 | test("landuse", "wood"). |
|---|
| 60 | alternative("landuse", "forest"). |
|---|
| 61 | alternative("natural", "wood")); |
|---|
| 62 | checks.add(new DeprecationCheck(2110). |
|---|
| 63 | testAndRemove("natural", "marsh"). |
|---|
| 64 | add("natural", "wetland"). |
|---|
| 65 | add("wetland", "marsh")); |
|---|
| 66 | checks.add(new DeprecationCheck(2111). |
|---|
| 67 | test("highway", "byway")); |
|---|
| 68 | checks.add(new DeprecationCheck(2112). |
|---|
| 69 | test("power_source"). |
|---|
| 70 | alternative("generator:source")); |
|---|
| 71 | checks.add(new DeprecationCheck(2113). |
|---|
| 72 | test("power_rating"). |
|---|
| 73 | alternative("generator:output")); |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | public void visit(OsmPrimitive p) { |
|---|
| 77 | for (DeprecationCheck check : checks) { |
|---|
| 78 | if (check.matchesPrimitive(p)) { |
|---|
| 79 | errors.add(new DeprecationError(p, check)); |
|---|
| 80 | } |
|---|
| 81 | } |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | @Override |
|---|
| 85 | public void visit(Node n) { |
|---|
| 86 | visit((OsmPrimitive) n); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | @Override |
|---|
| 90 | public void visit(Way w) { |
|---|
| 91 | visit((OsmPrimitive) w); |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | @Override |
|---|
| 95 | public void visit(Relation r) { |
|---|
| 96 | visit((OsmPrimitive) r); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | private static class DeprecationCheck { |
|---|
| 100 | |
|---|
| 101 | int code; |
|---|
| 102 | List<Tag> test = new LinkedList<Tag>(); |
|---|
| 103 | List<Tag> change = new LinkedList<Tag>(); |
|---|
| 104 | List<Tag> alternatives = new LinkedList<Tag>(); |
|---|
| 105 | |
|---|
| 106 | public DeprecationCheck(int code) { |
|---|
| 107 | this.code = code; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | DeprecationCheck test(String key, String value) { |
|---|
| 111 | test.add(new Tag(key, value)); |
|---|
| 112 | return this; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | DeprecationCheck test(String key) { |
|---|
| 116 | return test(key, null); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | DeprecationCheck add(String key, String value) { |
|---|
| 120 | change.add(new Tag(key, value)); |
|---|
| 121 | return this; |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | DeprecationCheck remove(String key) { |
|---|
| 125 | change.add(new Tag(key)); |
|---|
| 126 | return this; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | DeprecationCheck testAndRemove(String key, String value) { |
|---|
| 130 | return test(key, value).remove(key); |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | DeprecationCheck testAndRemove(String key) { |
|---|
| 134 | return test(key).remove(key); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | DeprecationCheck alternative(String key, String value) { |
|---|
| 138 | alternatives.add(new Tag(key, value)); |
|---|
| 139 | return this; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | DeprecationCheck alternative(String key) { |
|---|
| 143 | return alternative(key, null); |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | boolean matchesPrimitive(OsmPrimitive p) { |
|---|
| 147 | for (Tag tag : test) { |
|---|
| 148 | String key = tag.getKey(); |
|---|
| 149 | String value = tag.getValue(); |
|---|
| 150 | if (value.isEmpty() && !p.hasKey(key)) |
|---|
| 151 | return false; |
|---|
| 152 | if (!value.isEmpty() && !value.equals(p.get(key))) |
|---|
| 153 | return false; |
|---|
| 154 | } |
|---|
| 155 | return true; |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | Command fixPrimitive(OsmPrimitive p) { |
|---|
| 159 | Collection<Command> cmds = new LinkedList<Command>(); |
|---|
| 160 | for (Tag tag : change) { |
|---|
| 161 | cmds.add(new ChangePropertyCommand(p, tag.getKey(), tag.getValue())); |
|---|
| 162 | } |
|---|
| 163 | return new SequenceCommand(tr("Deprecation fix of {0}", Utils.join(", ", test)), cmds); |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | String getDescription() { |
|---|
| 167 | if (alternatives.isEmpty()) |
|---|
| 168 | return tr("{0} is deprecated", Utils.join(", ", test)); |
|---|
| 169 | else |
|---|
| 170 | return tr("{0} is deprecated, use {1} instead", Utils.join(", ", test), Utils.join(tr(" or "), alternatives)); |
|---|
| 171 | } |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | private class DeprecationError extends TestError { |
|---|
| 175 | |
|---|
| 176 | OsmPrimitive p; |
|---|
| 177 | DeprecationCheck check; |
|---|
| 178 | |
|---|
| 179 | DeprecationError(OsmPrimitive p, DeprecationCheck check) { |
|---|
| 180 | super(DeprecatedTags.this, Severity.WARNING, check.getDescription(), check.code, p); |
|---|
| 181 | this.p = p; |
|---|
| 182 | this.check = check; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | @Override |
|---|
| 186 | public boolean isFixable() { |
|---|
| 187 | return !check.change.isEmpty(); |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | @Override |
|---|
| 191 | public Command getFix() { |
|---|
| 192 | return check.fixPrimitive(p); |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | } |
|---|