001 package org.openstreetmap.josm.data.validation.tests;
002
003 import static org.openstreetmap.josm.tools.I18n.tr;
004
005 import java.util.Collection;
006 import java.util.LinkedList;
007 import java.util.List;
008
009 import org.openstreetmap.josm.command.ChangePropertyCommand;
010 import org.openstreetmap.josm.command.Command;
011 import org.openstreetmap.josm.command.SequenceCommand;
012 import org.openstreetmap.josm.data.osm.Node;
013 import org.openstreetmap.josm.data.osm.OsmPrimitive;
014 import org.openstreetmap.josm.data.osm.Relation;
015 import org.openstreetmap.josm.data.osm.Tag;
016 import org.openstreetmap.josm.data.osm.Way;
017 import org.openstreetmap.josm.data.validation.Severity;
018 import org.openstreetmap.josm.data.validation.Test;
019 import org.openstreetmap.josm.data.validation.TestError;
020 import org.openstreetmap.josm.tools.Utils;
021
022 public class DeprecatedTags extends Test {
023
024 private List<DeprecationCheck> checks = new LinkedList<DeprecationCheck>();
025
026 public DeprecatedTags() {
027 super(tr("Deprecated Tags"), tr("Checks and corrects deprecated tags."));
028 checks.add(new DeprecationCheck(2101).
029 testAndRemove("barrier", "wire_fence").
030 add("barrier", "fence").
031 add("fence_type", "chain"));
032 checks.add(new DeprecationCheck(2102).
033 testAndRemove("barrier", "wood_fence").
034 add("barrier", "fence").
035 add("fence_type", "wood"));
036 checks.add(new DeprecationCheck(2103).
037 testAndRemove("highway", "ford").
038 add("ford", "yes"));
039 // from http://wiki.openstreetmap.org/wiki/Deprecated_features
040 checks.add(new DeprecationCheck(2104).
041 test("class").
042 alternative("highway"));
043 checks.add(new DeprecationCheck(2105).
044 testAndRemove("highway", "stile").
045 add("barrier", "stile"));
046 checks.add(new DeprecationCheck(2106).
047 testAndRemove("highway", "incline").
048 add("highway", "road").
049 add("incline", "up"));
050 checks.add(new DeprecationCheck(2107).
051 testAndRemove("highway", "incline_steep").
052 add("highway", "road").
053 add("incline", "up"));
054 checks.add(new DeprecationCheck(2108).
055 testAndRemove("highway", "unsurfaced").
056 add("highway", "road").
057 add("incline", "unpaved"));
058 checks.add(new DeprecationCheck(2109).
059 test("landuse", "wood").
060 alternative("landuse", "forest").
061 alternative("natural", "wood"));
062 checks.add(new DeprecationCheck(2110).
063 testAndRemove("natural", "marsh").
064 add("natural", "wetland").
065 add("wetland", "marsh"));
066 checks.add(new DeprecationCheck(2111).
067 test("highway", "byway"));
068 checks.add(new DeprecationCheck(2112).
069 test("power_source").
070 alternative("generator:source"));
071 checks.add(new DeprecationCheck(2113).
072 test("power_rating").
073 alternative("generator:output"));
074 // from http://wiki.openstreetmap.org/wiki/Tag:shop%3Dorganic
075 checks.add(new DeprecationCheck(2114).
076 testAndRemove("shop", "organic").
077 add("shop", "supermarket").
078 add("organic", "only"));
079 // from http://wiki.openstreetmap.org/wiki/Key:bicycle_parking
080 checks.add(new DeprecationCheck(2115).
081 testAndRemove("bicycle_parking", "sheffield").
082 add("bicycle_parking", "stands"));
083 }
084
085 public void visit(OsmPrimitive p) {
086 for (DeprecationCheck check : checks) {
087 if (check.matchesPrimitive(p)) {
088 errors.add(new DeprecationError(p, check));
089 }
090 }
091 }
092
093 @Override
094 public void visit(Node n) {
095 visit((OsmPrimitive) n);
096 }
097
098 @Override
099 public void visit(Way w) {
100 visit((OsmPrimitive) w);
101 }
102
103 @Override
104 public void visit(Relation r) {
105 visit((OsmPrimitive) r);
106 }
107
108 private static class DeprecationCheck {
109
110 int code;
111 List<Tag> test = new LinkedList<Tag>();
112 List<Tag> change = new LinkedList<Tag>();
113 List<Tag> alternatives = new LinkedList<Tag>();
114
115 public DeprecationCheck(int code) {
116 this.code = code;
117 }
118
119 DeprecationCheck test(String key, String value) {
120 test.add(new Tag(key, value));
121 return this;
122 }
123
124 DeprecationCheck test(String key) {
125 return test(key, null);
126 }
127
128 DeprecationCheck add(String key, String value) {
129 change.add(new Tag(key, value));
130 return this;
131 }
132
133 DeprecationCheck remove(String key) {
134 change.add(new Tag(key));
135 return this;
136 }
137
138 DeprecationCheck testAndRemove(String key, String value) {
139 return test(key, value).remove(key);
140 }
141
142 DeprecationCheck testAndRemove(String key) {
143 return test(key).remove(key);
144 }
145
146 DeprecationCheck alternative(String key, String value) {
147 alternatives.add(new Tag(key, value));
148 return this;
149 }
150
151 DeprecationCheck alternative(String key) {
152 return alternative(key, null);
153 }
154
155 boolean matchesPrimitive(OsmPrimitive p) {
156 for (Tag tag : test) {
157 String key = tag.getKey();
158 String value = tag.getValue();
159 if (value.isEmpty() && !p.hasKey(key))
160 return false;
161 if (!value.isEmpty() && !value.equals(p.get(key)))
162 return false;
163 }
164 return true;
165 }
166
167 Command fixPrimitive(OsmPrimitive p) {
168 Collection<Command> cmds = new LinkedList<Command>();
169 for (Tag tag : change) {
170 cmds.add(new ChangePropertyCommand(p, tag.getKey(), tag.getValue()));
171 }
172 return new SequenceCommand(tr("Deprecation fix of {0}", Utils.join(", ", test)), cmds);
173 }
174
175 String getDescription() {
176 if (alternatives.isEmpty())
177 return tr("{0} is deprecated", Utils.join(", ", test));
178 else
179 return tr("{0} is deprecated, use {1} instead", Utils.join(", ", test), Utils.join(tr(" or "), alternatives));
180 }
181 }
182
183 private class DeprecationError extends TestError {
184
185 OsmPrimitive p;
186 DeprecationCheck check;
187
188 DeprecationError(OsmPrimitive p, DeprecationCheck check) {
189 super(DeprecatedTags.this, Severity.WARNING, check.getDescription(), check.code, p);
190 this.p = p;
191 this.check = check;
192 }
193
194 @Override
195 public boolean isFixable() {
196 return !check.change.isEmpty();
197 }
198
199 @Override
200 public Command getFix() {
201 return check.fixPrimitive(p);
202 }
203 }
204 }