source: josm/trunk/src/org/openstreetmap/josm/actions/upload/FixDataHook.java@ 10601

Last change on this file since 10601 was 10601, checked in by Don-vip, 8 years ago

see #11390 - sonar - squid:S1604 - Java 8: Anonymous inner classes containing only one method should become lambdas

  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions.upload;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.Collection;
7import java.util.Collections;
8import java.util.HashMap;
9import java.util.LinkedList;
10import java.util.List;
11import java.util.Map;
12import java.util.Map.Entry;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.command.ChangePropertyCommand;
16import org.openstreetmap.josm.command.Command;
17import org.openstreetmap.josm.command.SequenceCommand;
18import org.openstreetmap.josm.data.APIDataSet;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20import org.openstreetmap.josm.data.osm.Relation;
21import org.openstreetmap.josm.data.osm.Tag;
22
23/**
24 * Fixes defective data entries for all modified objects before upload
25 * @since 5621
26 */
27public class FixDataHook implements UploadHook {
28
29 /**
30 * List of checks to run on data
31 */
32 private final List<FixData> deprecated = new LinkedList<>();
33
34 /**
35 * Constructor for data initialization
36 */
37 public FixDataHook() {
38 // CHECKSTYLE.OFF: SingleSpaceSeparator
39 deprecated.add(new FixDataSpace());
40 deprecated.add(new FixDataKey("color", "colour"));
41 deprecated.add(new FixDataTag("highway", "ford", "ford", "yes"));
42 deprecated.add(new FixDataTag("oneway", "false", "oneway", "no"));
43 deprecated.add(new FixDataTag("oneway", "0", "oneway", "no"));
44 deprecated.add(new FixDataTag("oneway", "true", "oneway", "yes"));
45 deprecated.add(new FixDataTag("oneway", "1", "oneway", "yes"));
46 deprecated.add(new FixDataTag("highway", "stile", "barrier", "stile"));
47 // CHECKSTYLE.ON: SingleSpaceSeparator
48 deprecated.add((keys, osm) -> {
49 if (osm instanceof Relation && "multipolygon".equals(keys.get("type")) && "administrative".equals(keys.get("boundary"))) {
50 keys.put("type", "boundary");
51 return true;
52 }
53 return false;
54 });
55 }
56
57 /**
58 * Common set of commands for data fixing
59 * @since 10600 (functional interface)
60 */
61 @FunctionalInterface
62 public interface FixData {
63 /**
64 * Checks if data needs to be fixed and change keys
65 *
66 * @param keys list of keys to be modified
67 * @param osm the object for type validation, don't use keys of it!
68 * @return <code>true</code> if keys have been modified
69 */
70 boolean fixKeys(Map<String, String> keys, OsmPrimitive osm);
71 }
72
73 /**
74 * Data fix to remove spaces at begin or end of tags
75 */
76 public static class FixDataSpace implements FixData {
77 @Override
78 public boolean fixKeys(Map<String, String> keys, OsmPrimitive osm) {
79 Map<String, String> newKeys = new HashMap<>(keys);
80 for (Entry<String, String> e : keys.entrySet()) {
81 String v = Tag.removeWhiteSpaces(e.getValue());
82 String k = Tag.removeWhiteSpaces(e.getKey());
83 boolean drop = k.isEmpty() || v.isEmpty();
84 if (!e.getKey().equals(k)) {
85 if (drop || !keys.containsKey(k)) {
86 newKeys.put(e.getKey(), null);
87 if (!drop)
88 newKeys.put(k, v);
89 }
90 } else if (!e.getValue().equals(v)) {
91 newKeys.put(k, v.isEmpty() ? null : v);
92 } else if (drop) {
93 newKeys.put(e.getKey(), null);
94 }
95 }
96 boolean changed = !keys.equals(newKeys);
97 if (changed) {
98 keys.clear();
99 keys.putAll(newKeys);
100 }
101 return changed;
102 }
103 }
104
105 /**
106 * Data fix to cleanup wrong spelled keys
107 */
108 public static class FixDataKey implements FixData {
109 /** key of wrong data */
110 private final String oldKey;
111 /** key of correct data */
112 private final String newKey;
113
114 /**
115 * Setup key check for wrong spelled keys
116 *
117 * @param oldKey wrong spelled key
118 * @param newKey correct replacement
119 */
120 public FixDataKey(String oldKey, String newKey) {
121 this.oldKey = oldKey;
122 this.newKey = newKey;
123 }
124
125 @Override
126 public boolean fixKeys(Map<String, String> keys, OsmPrimitive osm) {
127 if (keys.containsKey(oldKey) && !keys.containsKey(newKey)) {
128 keys.put(newKey, keys.get(oldKey));
129 keys.put(oldKey, null);
130 return true;
131 } else if (keys.containsKey(oldKey) && keys.containsKey(newKey) && keys.get(oldKey).equals(keys.get(newKey))) {
132 keys.put(oldKey, null);
133 return true;
134 }
135 return false;
136 }
137 }
138
139 /**
140 * Data fix to cleanup wrong spelled tags
141 */
142 public static class FixDataTag implements FixData {
143 /** key of wrong data */
144 private final String oldKey;
145 /** value of wrong data */
146 private final String oldValue;
147 /** key of correct data */
148 private final String newKey;
149 /** value of correct data */
150 private final String newValue;
151
152 /**
153 * Setup key check for wrong spelled keys
154 *
155 * @param oldKey wrong or old key
156 * @param oldValue wrong or old value
157 * @param newKey correct key replacement
158 * @param newValue correct value replacement
159 */
160 public FixDataTag(String oldKey, String oldValue, String newKey, String newValue) {
161 this.oldKey = oldKey;
162 this.oldValue = oldValue;
163 this.newKey = newKey;
164 this.newValue = newValue;
165 }
166
167 @Override
168 public boolean fixKeys(Map<String, String> keys, OsmPrimitive osm) {
169 if (oldValue.equals(keys.get(oldKey)) && (newKey.equals(oldKey)
170 || !keys.containsKey(newKey) || keys.get(newKey).equals(newValue))) {
171 keys.put(newKey, newValue);
172 if (!newKey.equals(oldKey))
173 keys.put(oldKey, null);
174 return true;
175 }
176 return false;
177 }
178 }
179
180 /**
181 * Checks the upload for deprecated or wrong tags.
182 * @param apiDataSet the data to upload
183 */
184 @Override
185 public boolean checkUpload(APIDataSet apiDataSet) {
186 if (!Main.pref.getBoolean("fix.data.on.upload", true))
187 return true;
188
189 List<OsmPrimitive> objectsToUpload = apiDataSet.getPrimitives();
190 Collection<Command> cmds = new LinkedList<>();
191
192 for (OsmPrimitive osm : objectsToUpload) {
193 Map<String, String> keys = new HashMap<>(osm.getKeys());
194 if (!keys.isEmpty()) {
195 boolean modified = false;
196 for (FixData fix : deprecated) {
197 if (fix.fixKeys(keys, osm))
198 modified = true;
199 }
200 if (modified)
201 cmds.add(new ChangePropertyCommand(Collections.singleton(osm), keys));
202 }
203 }
204
205 if (!cmds.isEmpty())
206 Main.main.undoRedo.add(new SequenceCommand(tr("Fix deprecated tags"), cmds));
207 return true;
208 }
209}
Note: See TracBrowser for help on using the repository browser.