1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.corrector;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.util.ArrayList;
|
---|
7 | import java.util.Collection;
|
---|
8 | import java.util.HashMap;
|
---|
9 | import java.util.List;
|
---|
10 | import java.util.Map;
|
---|
11 | import java.util.regex.Matcher;
|
---|
12 | import java.util.regex.Pattern;
|
---|
13 |
|
---|
14 | import org.openstreetmap.josm.Main;
|
---|
15 | import org.openstreetmap.josm.command.Command;
|
---|
16 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
17 | import org.openstreetmap.josm.data.osm.OsmUtils;
|
---|
18 | import org.openstreetmap.josm.data.osm.Relation;
|
---|
19 | import org.openstreetmap.josm.data.osm.RelationMember;
|
---|
20 | import org.openstreetmap.josm.data.osm.Way;
|
---|
21 |
|
---|
22 | public class ReverseWayTagCorrector extends TagCorrector<Way> {
|
---|
23 |
|
---|
24 | private static class PrefixSuffixSwitcher {
|
---|
25 |
|
---|
26 | private final String a;
|
---|
27 | private final String b;
|
---|
28 | private final Pattern startPattern;
|
---|
29 | private final Pattern endPattern;
|
---|
30 |
|
---|
31 | private final String SEPARATOR = "[:_]?";
|
---|
32 |
|
---|
33 | public PrefixSuffixSwitcher(String a, String b) {
|
---|
34 | this.a = a;
|
---|
35 | this.b = b;
|
---|
36 | startPattern = Pattern.compile(
|
---|
37 | "^(" + a + "|" + b + ")(" + SEPARATOR + "|$)",
|
---|
38 | Pattern.CASE_INSENSITIVE);
|
---|
39 | endPattern = Pattern.compile(
|
---|
40 | SEPARATOR + "(" + a + "|" + b + ")$",
|
---|
41 | Pattern.CASE_INSENSITIVE);
|
---|
42 | }
|
---|
43 |
|
---|
44 | public String apply(String text) {
|
---|
45 | Matcher m = startPattern.matcher(text);
|
---|
46 | if (!m.lookingAt())
|
---|
47 | m = endPattern.matcher(text);
|
---|
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 | };
|
---|
68 |
|
---|
69 | @Override
|
---|
70 | public Collection<Command> execute(Way oldway, Way way) throws UserCancelException {
|
---|
71 | Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap =
|
---|
72 | new HashMap<OsmPrimitive, List<TagCorrection>>();
|
---|
73 |
|
---|
74 | ArrayList<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
|
---|
75 | primitives.add(way);
|
---|
76 | primitives.addAll(way.nodes);
|
---|
77 |
|
---|
78 | for (OsmPrimitive primitive : primitives) {
|
---|
79 | tagCorrectionsMap.put(primitive, new ArrayList<TagCorrection>());
|
---|
80 |
|
---|
81 | for (String key : primitive.keySet()) {
|
---|
82 | String newKey = key;
|
---|
83 | String value = primitive.get(key);
|
---|
84 | String newValue = value;
|
---|
85 |
|
---|
86 | if (key.equals("oneway")) {
|
---|
87 | if (value.equals("-1"))
|
---|
88 | newValue = OsmUtils.trueval;
|
---|
89 | else {
|
---|
90 | Boolean boolValue = OsmUtils.getOsmBoolean(value);
|
---|
91 | if (boolValue != null && boolValue.booleanValue()) {
|
---|
92 | newValue = "-1";
|
---|
93 | }
|
---|
94 | }
|
---|
95 | } else {
|
---|
96 | for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
|
---|
97 | newKey = prefixSuffixSwitcher.apply(key);
|
---|
98 | if (!key.equals(newKey))
|
---|
99 | break;
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 | if (!key.equals(newKey) || !value.equals(newValue))
|
---|
104 | tagCorrectionsMap.get(primitive).add(
|
---|
105 | new TagCorrection(key, value, newKey, newValue));
|
---|
106 | }
|
---|
107 | }
|
---|
108 |
|
---|
109 | Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap =
|
---|
110 | new HashMap<OsmPrimitive, List<RoleCorrection>>();
|
---|
111 | roleCorrectionMap.put(way, new ArrayList<RoleCorrection>());
|
---|
112 |
|
---|
113 | for (Relation relation : Main.ds.relations) {
|
---|
114 | for (RelationMember member : relation.members) {
|
---|
115 | if (!member.member.realEqual(oldway, true)
|
---|
116 | || member.role.length() == 0)
|
---|
117 | continue;
|
---|
118 |
|
---|
119 | boolean found = false;
|
---|
120 | String newRole = null;
|
---|
121 | for (PrefixSuffixSwitcher prefixSuffixSwitcher : prefixSuffixSwitchers) {
|
---|
122 | newRole = prefixSuffixSwitcher.apply(member.role);
|
---|
123 | if (!newRole.equals(member.role)) {
|
---|
124 | found = true;
|
---|
125 | break;
|
---|
126 | }
|
---|
127 | }
|
---|
128 |
|
---|
129 | if (found)
|
---|
130 | roleCorrectionMap.get(way).add(
|
---|
131 | new RoleCorrection(relation, member, newRole));
|
---|
132 | }
|
---|
133 | }
|
---|
134 |
|
---|
135 | return applyCorrections(tagCorrectionsMap, roleCorrectionMap,
|
---|
136 | tr("When reversing this way, the following changes to properties "
|
---|
137 | + "of the way and its nodes are suggested in order "
|
---|
138 | + "to maintain data consistency."));
|
---|
139 | }
|
---|
140 | }
|
---|