source: josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java@ 2611

Last change on this file since 2611 was 2611, checked in by mjulius, 14 years ago

fixes #4104 - reversing of way does not update direction dependent roles

File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.corrector;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashMap;
9import java.util.List;
10import java.util.Map;
11import java.util.regex.Matcher;
12import java.util.regex.Pattern;
13
14import org.openstreetmap.josm.command.Command;
15import org.openstreetmap.josm.data.osm.OsmPrimitive;
16import org.openstreetmap.josm.data.osm.OsmUtils;
17import org.openstreetmap.josm.data.osm.Relation;
18import org.openstreetmap.josm.data.osm.RelationMember;
19import org.openstreetmap.josm.data.osm.Way;
20
21public class ReverseWayTagCorrector extends TagCorrector<Way> {
22
23 private static class PrefixSuffixSwitcher {
24
25 private final String a;
26 private final String b;
27 private final Pattern startPattern;
28 private final Pattern endPattern;
29
30 private final String SEPARATOR = "[:_]?";
31
32 public PrefixSuffixSwitcher(String a, String b) {
33 this.a = a;
34 this.b = b;
35 startPattern = Pattern.compile(
36 "^(" + a + "|" + b + ")(" + SEPARATOR + "|$)",
37 Pattern.CASE_INSENSITIVE);
38 endPattern = Pattern.compile("^.*" +
39 SEPARATOR + "(" + a + "|" + b + ")$",
40 Pattern.CASE_INSENSITIVE);
41 }
42
43 public String apply(String text) {
44 Matcher m = startPattern.matcher(text);
45 if (!m.lookingAt()) {
46 m = endPattern.matcher(text);
47 }
48
49 if (m.lookingAt()) {
50 String leftRight = m.group(1).toLowerCase();
51
52 StringBuilder result = new StringBuilder();
53 result.append(text.substring(0, m.start(1)));
54 result.append(leftRight.equals(a) ? b : a);
55 result.append(text.substring(m.end(1)));
56
57 return result.toString();
58 }
59 return text;
60 }
61 }
62
63 private static PrefixSuffixSwitcher[] prefixSuffixSwitchers =
64 new PrefixSuffixSwitcher[] {
65 new PrefixSuffixSwitcher("left", "right"),
66 new PrefixSuffixSwitcher("forward", "backward"),
67 new PrefixSuffixSwitcher("forwards", "backwards")
68 };
69
70 public static boolean isReversible(Way way) {
71 ArrayList<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
72 primitives.add(way);
73 primitives.addAll(way.getNodes());
74
75 for (OsmPrimitive primitive : primitives) {
76 for (String key : primitive.keySet()) {
77 if (key.equals("oneway")) return false;
78 for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
79 if (!key.equals(prefixSuffixSwitcher.apply(key))) return false;
80 }
81 }
82 }
83
84 return true;
85 }
86
87 public static List<Way> irreversibleWays(List<Way> ways) {
88 List<Way> newWays = new ArrayList<Way>(ways);
89 for (Way way : ways) {
90 if (isReversible(way)) {
91 newWays.remove(way);
92 }
93 }
94 return newWays;
95 }
96
97 @Override
98 public Collection<Command> execute(Way oldway, Way way) throws UserCancelException {
99 Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap =
100 new HashMap<OsmPrimitive, List<TagCorrection>>();
101
102 ArrayList<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
103 primitives.add(way);
104 primitives.addAll(way.getNodes());
105
106 for (OsmPrimitive primitive : primitives) {
107 tagCorrectionsMap.put(primitive, new ArrayList<TagCorrection>());
108
109 for (String key : primitive.keySet()) {
110 String newKey = key;
111 String value = primitive.get(key);
112 String newValue = value;
113
114 if (key.equals("oneway")) {
115 if (OsmUtils.isReversed(value)) {
116 newValue = OsmUtils.trueval;
117 } else {
118 Boolean boolValue = OsmUtils.getOsmBoolean(value);
119 if (boolValue != null && boolValue.booleanValue()) {
120 newValue = OsmUtils.reverseval;
121 }
122 }
123 } else {
124 for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
125 newKey = prefixSuffixSwitcher.apply(key);
126 if (!key.equals(newKey)) {
127 break;
128 }
129 }
130 }
131
132 if (!key.equals(newKey) || !value.equals(newValue)) {
133 tagCorrectionsMap.get(primitive).add(
134 new TagCorrection(key, value, newKey, newValue));
135 }
136 }
137 }
138
139 Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap =
140 new HashMap<OsmPrimitive, List<RoleCorrection>>();
141 roleCorrectionMap.put(way, new ArrayList<RoleCorrection>());
142
143 Collection<OsmPrimitive> referrers = oldway.getReferrers();
144 for (OsmPrimitive referrer: referrers) {
145 if (! (referrer instanceof Relation)) {
146 continue;
147 }
148 Relation relation = (Relation)referrer;
149 int position = 0;
150 for (RelationMember member : relation.getMembers()) {
151 if (!member.getMember().hasEqualSemanticAttributes(oldway)
152 || !member.hasRole()) {
153 position++;
154 continue;
155 }
156
157 boolean found = false;
158 String newRole = null;
159 for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
160 newRole = prefixSuffixSwitcher.apply(member.getRole());
161 if (!newRole.equals(member.getRole())) {
162 found = true;
163 break;
164 }
165 }
166
167 if (found) {
168 roleCorrectionMap.get(way).add(
169 new RoleCorrection(relation, position, member, newRole));
170 }
171
172 position++;
173 }
174 }
175
176 return applyCorrections(tagCorrectionsMap, roleCorrectionMap,
177 tr("When reversing this way, the following changes to properties "
178 + "of the way and its nodes are suggested in order "
179 + "to maintain data consistency."));
180 }
181}
Note: See TracBrowser for help on using the repository browser.