source: josm/trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/KeyedItem.java@ 14634

Last change on this file since 14634 was 14634, checked in by simon04, 5 years ago

fix #17170 - Migrate TagInfoExtract.groovy to Java

File size: 7.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.tagging.presets.items;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.Collection;
7import java.util.EnumSet;
8import java.util.HashMap;
9import java.util.Map;
10import java.util.NoSuchElementException;
11import java.util.SortedSet;
12import java.util.TreeSet;
13
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.OsmUtils;
16import org.openstreetmap.josm.data.preferences.BooleanProperty;
17import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
18
19/**
20 * Preset item associated to an OSM key.
21 */
22public abstract class KeyedItem extends TaggingPresetItem {
23
24 /** Translatation of "<different>". Use in combo boxes to display an entry matching several different values. */
25 protected static final String DIFFERENT = tr("<different>");
26
27 protected static final BooleanProperty PROP_FILL_DEFAULT = new BooleanProperty("taggingpreset.fill-default-for-tagged-primitives", false);
28
29 /** Last value of each key used in presets, used for prefilling corresponding fields */
30 static final Map<String, String> LAST_VALUES = new HashMap<>();
31
32 /** This specifies the property key that will be modified by the item. */
33 public String key; // NOSONAR
34 /** The text to display */
35 public String text; // NOSONAR
36 /** The context used for translating {@link #text} */
37 public String text_context; // NOSONAR
38 /**
39 * Allows to change the matching process, i.e., determining whether the tags of an OSM object fit into this preset.
40 * If a preset fits then it is linked in the Tags/Membership dialog.<ul>
41 * <li>none: neutral, i.e., do not consider this item for matching</li>
42 * <li>key: positive if key matches, neutral otherwise</li>
43 * <li>key!: positive if key matches, negative otherwise</li>
44 * <li>keyvalue: positive if key and value matches, neutral otherwise</li>
45 * <li>keyvalue!: positive if key and value matches, negative otherwise</li></ul>
46 * Note that for a match, at least one positive and no negative is required.
47 * Default is "keyvalue!" for {@link Key} and "none" for {@link Text}, {@link Combo}, {@link MultiSelect} and {@link Check}.
48 */
49 public String match = getDefaultMatch().getValue(); // NOSONAR
50
51 /**
52 * Enum denoting how a match (see {@link TaggingPresetItem#matches}) is performed.
53 */
54 protected enum MatchType {
55
56 /** Neutral, i.e., do not consider this item for matching. */
57 NONE("none"),
58 /** Positive if key matches, neutral otherwise. */
59 KEY("key"),
60 /** Positive if key matches, negative otherwise. */
61 KEY_REQUIRED("key!"),
62 /** Positive if key and value matches, neutral otherwise. */
63 KEY_VALUE("keyvalue"),
64 /** Positive if key and value matches, negative otherwise. */
65 KEY_VALUE_REQUIRED("keyvalue!");
66
67 private final String value;
68
69 MatchType(String value) {
70 this.value = value;
71 }
72
73 /**
74 * Replies the associated textual value.
75 * @return the associated textual value
76 */
77 public String getValue() {
78 return value;
79 }
80
81 /**
82 * Determines the {@code MatchType} for the given textual value.
83 * @param type the textual value
84 * @return the {@code MatchType} for the given textual value
85 */
86 public static MatchType ofString(String type) {
87 for (MatchType i : EnumSet.allOf(MatchType.class)) {
88 if (i.getValue().equals(type))
89 return i;
90 }
91 throw new IllegalArgumentException(type + " is not allowed");
92 }
93 }
94
95 /**
96 * Usage information on a key
97 */
98 protected static class Usage {
99 /**
100 * A set of values that were used for this key.
101 */
102 public final SortedSet<String> values = new TreeSet<>(); // NOSONAR
103 private boolean hadKeys;
104 private boolean hadEmpty;
105
106 /**
107 * Check if there is exactly one value for this key.
108 * @return <code>true</code> if there was exactly one value.
109 */
110 public boolean hasUniqueValue() {
111 return values.size() == 1 && !hadEmpty;
112 }
113
114 /**
115 * Check if this key was not used in any primitive
116 * @return <code>true</code> if it was unused.
117 */
118 public boolean unused() {
119 return values.isEmpty();
120 }
121
122 /**
123 * Get the first value available.
124 * @return The first value
125 * @throws NoSuchElementException if there is no such value.
126 */
127 public String getFirst() {
128 return values.first();
129 }
130
131 /**
132 * Check if we encountered any primitive that had any keys
133 * @return <code>true</code> if any of the primtives had any tags.
134 */
135 public boolean hadKeys() {
136 return hadKeys;
137 }
138 }
139
140 protected static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
141 Usage returnValue = new Usage();
142 for (OsmPrimitive s : sel) {
143 String v = s.get(key);
144 if (v != null) {
145 returnValue.values.add(v);
146 } else {
147 returnValue.hadEmpty = true;
148 }
149 if (s.hasKeys()) {
150 returnValue.hadKeys = true;
151 }
152 }
153 return returnValue;
154 }
155
156 protected static Usage determineBooleanUsage(Collection<OsmPrimitive> sel, String key) {
157 Usage returnValue = new Usage();
158 for (OsmPrimitive s : sel) {
159 String booleanValue = OsmUtils.getNamedOsmBoolean(s.get(key));
160 if (booleanValue != null) {
161 returnValue.values.add(booleanValue);
162 }
163 }
164 return returnValue;
165 }
166
167 /**
168 * Determines whether key or key+value are required.
169 * @return whether key or key+value are required
170 */
171 public boolean isKeyRequired() {
172 final MatchType type = MatchType.ofString(match);
173 return MatchType.KEY_REQUIRED.equals(type) || MatchType.KEY_VALUE_REQUIRED.equals(type);
174 }
175
176 /**
177 * Returns the default match.
178 * @return the default match
179 */
180 public abstract MatchType getDefaultMatch();
181
182 /**
183 * Returns the list of values.
184 * @return the list of values
185 */
186 public abstract Collection<String> getValues();
187
188 protected String getKeyTooltipText() {
189 return tr("This corresponds to the key ''{0}''", key);
190 }
191
192 @Override
193 protected Boolean matches(Map<String, String> tags) {
194 switch (MatchType.ofString(match)) {
195 case NONE:
196 return null;
197 case KEY:
198 return tags.containsKey(key) ? Boolean.TRUE : null;
199 case KEY_REQUIRED:
200 return tags.containsKey(key);
201 case KEY_VALUE:
202 return tags.containsKey(key) && getValues().contains(tags.get(key)) ? Boolean.TRUE : null;
203 case KEY_VALUE_REQUIRED:
204 return tags.containsKey(key) && getValues().contains(tags.get(key));
205 default:
206 throw new IllegalStateException();
207 }
208 }
209
210 @Override
211 public String toString() {
212 return "KeyedItem [key=" + key + ", text=" + text
213 + ", text_context=" + text_context + ", match=" + match
214 + ']';
215 }
216}
Note: See TracBrowser for help on using the repository browser.