source: josm/trunk/src/org/openstreetmap/josm/actions/corrector/ReverseWayNoTagCorrector.java@ 17029

Last change on this file since 17029 was 17029, checked in by Klumbumbus, 4 years ago
  • see #19726 - Unify changeset icon, use globe icon in history window version table popup menu, as it opens in the browser
  • see #19714 - Typo in comment
  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions.corrector;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.util.Arrays;
8import java.util.Map;
9
10import javax.swing.JOptionPane;
11
12import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
13import org.openstreetmap.josm.data.osm.Tag;
14import org.openstreetmap.josm.data.osm.TagCollection;
15import org.openstreetmap.josm.data.osm.Tagged;
16import org.openstreetmap.josm.data.osm.Way;
17import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
18import org.openstreetmap.josm.gui.MainApplication;
19import org.openstreetmap.josm.tools.UserCancelException;
20import org.openstreetmap.josm.tools.Utils;
21
22/**
23 * A ReverseWayNoTagCorrector warns about ways that should not be reversed
24 * because their semantic meaning cannot be preserved in that case.
25 * E.g. natural=coastline, natural=cliff, barrier=retaining_wall cannot be changed.
26 * @see ReverseWayTagCorrector for handling of tags that can be modified (oneway=yes, etc.)
27 * @since 5724
28 */
29public final class ReverseWayNoTagCorrector {
30
31 private ReverseWayNoTagCorrector() {
32 // Hide default constructor for utils classes
33 }
34
35 /**
36 * Tags that imply a semantic meaning from the way direction and cannot be changed.
37 */
38 private static final TagCollection DIRECTIONAL_TAGS = new TagCollection(Arrays.asList(
39 new Tag("natural", "coastline"),
40 new Tag("natural", "cliff"),
41 new Tag("barrier", "guard_rail"),
42 new Tag("barrier", "kerb"),
43 new Tag("barrier", "retaining_wall"),
44 new Tag("barrier", "city_wall"),
45 new Tag("man_made", "embankment")
46 ));
47
48 /**
49 * Replies the tags that imply a semantic meaning from <code>way</code> direction and cannot be changed.
50 * @param way The way to look for
51 * @return tags that imply a semantic meaning from <code>way</code> direction and cannot be changed
52 */
53 public static TagCollection getDirectionalTags(Tagged way) {
54 final TagCollection collection = new TagCollection();
55 for (Map.Entry<String, String> entry : way.getKeys().entrySet()) {
56 final Tag tag = new Tag(entry.getKey(), entry.getValue());
57 final boolean isDirectional = DIRECTIONAL_TAGS.contains(tag) || tag.isDirectionKey();
58 if (isDirectional) {
59 final boolean cannotBeCorrected = ReverseWayTagCorrector.getTagCorrections(tag).isEmpty();
60
61 if (cannotBeCorrected && !way.isKeyTrue("two_sided")) {
62 // two_sided=yes is a special (documented) barrier=city_wall attribute, see #19714
63 collection.add(tag);
64 }
65 }
66 }
67 return collection;
68 }
69
70 /**
71 * Tests whether way can be reversed without semantic change.
72 * Looks for tags like natural=cliff, barrier=retaining_wall.
73 * @param way The way to check
74 * @return false if the semantic meaning change if the way is reversed, true otherwise.
75 */
76 public static boolean isReversible(Tagged way) {
77 return getDirectionalTags(way).isEmpty();
78 }
79
80 private static boolean confirmReverseWay(Way way, TagCollection tags) {
81 String msg = trn(
82 // Singular, if a single tag is impacted
83 "<html>You are going to reverse the way ''{0}'',"
84 + "<br/> whose semantic meaning of its tag ''{1}'' is defined by its direction.<br/>"
85 + "Do you really want to change the way direction, thus its semantic meaning?</html>",
86 // Plural, if several tags are impacted
87 "<html>You are going to reverse the way ''{0}'',"
88 + "<br/> whose semantic meaning of these tags are defined by its direction:<br/>{1}"
89 + "Do you really want to change the way direction, thus its semantic meaning?</html>",
90 tags.size(),
91 Utils.escapeReservedCharactersHTML(way.getDisplayName(DefaultNameFormatter.getInstance())),
92 Utils.joinAsHtmlUnorderedList(tags)
93 );
94 int ret = ConditionalOptionPaneUtil.showOptionDialog(
95 "reverse_directional_way",
96 MainApplication.getMainFrame(),
97 msg,
98 tr("Reverse directional way."),
99 JOptionPane.YES_NO_CANCEL_OPTION,
100 JOptionPane.WARNING_MESSAGE,
101 null,
102 null
103 );
104 switch(ret) {
105 case ConditionalOptionPaneUtil.DIALOG_DISABLED_OPTION:
106 case JOptionPane.YES_OPTION:
107 return true;
108 default:
109 return false;
110 }
111 }
112
113 /**
114 * Checks the given way can be safely reversed and asks user to confirm the operation if it not the case.
115 * @param way The way to check
116 * @throws UserCancelException If the user cancels the operation
117 */
118 public static void checkAndConfirmReverseWay(Way way) throws UserCancelException {
119 TagCollection tags = getDirectionalTags(way);
120 if (!tags.isEmpty() && !confirmReverseWay(way, tags)) {
121 throw new UserCancelException();
122 }
123 }
124}
Note: See TracBrowser for help on using the repository browser.