source: josm/trunk/src/org/openstreetmap/josm/gui/conflict/tags/MultiValueResolutionDecision.java@ 17333

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

see #20129 - Fix typos and misspellings in the code (patch by gaben)

  • Property svn:eol-style set to native
File size: 9.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.conflict.tags;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7import java.util.ArrayList;
8import java.util.Arrays;
9import java.util.Collection;
10import java.util.Collections;
11import java.util.List;
12import java.util.Optional;
13
14import org.openstreetmap.josm.command.ChangePropertyCommand;
15import org.openstreetmap.josm.command.Command;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.Tag;
18import org.openstreetmap.josm.data.osm.TagCollection;
19import org.openstreetmap.josm.tools.CheckParameterUtil;
20
21/**
22 * Represents a decision for a conflict due to multiple possible value for a tag.
23 * @since 2008
24 */
25public class MultiValueResolutionDecision {
26
27 /** the type of decision */
28 private MultiValueDecisionType type;
29 /** the collection of tags for which a decision is needed */
30 private final TagCollection tags;
31 /** the selected value if {@link #type} is {@link MultiValueDecisionType#KEEP_ONE} */
32 private String value;
33
34 private static final String[] SUMMABLE_KEYS = {
35 "capacity(:.+)?", "step_count"
36 };
37
38 /**
39 * constructor
40 */
41 public MultiValueResolutionDecision() {
42 type = MultiValueDecisionType.UNDECIDED;
43 tags = new TagCollection();
44 autoDecide();
45 }
46
47 /**
48 * Creates a new decision for the tag collection <code>tags</code>.
49 * All tags must have the same key.
50 *
51 * @param tags the tags. Must not be null.
52 * @throws IllegalArgumentException if tags is null
53 * @throws IllegalArgumentException if there are more than one keys
54 * @throws IllegalArgumentException if tags is empty
55 */
56 public MultiValueResolutionDecision(TagCollection tags) {
57 CheckParameterUtil.ensureParameterNotNull(tags, "tags");
58 if (tags.isEmpty())
59 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' must not be empty.", "tags"));
60 if (tags.getKeys().size() != 1)
61 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' with tags for exactly one key expected. Got {1}.",
62 "tags", tags.getKeys().size()));
63 this.tags = tags;
64 autoDecide();
65 }
66
67 /**
68 * Tries to find the best decision based on the current values.
69 */
70 protected final void autoDecide() {
71 this.type = MultiValueDecisionType.UNDECIDED;
72 // exactly one empty value ? -> delete the tag
73 if (tags.size() == 1 && tags.getValues().contains("")) {
74 this.type = MultiValueDecisionType.KEEP_NONE;
75
76 // exactly one non empty value? -> keep this value
77 } else if (tags.size() == 1) {
78 this.type = MultiValueDecisionType.KEEP_ONE;
79 this.value = tags.getValues().iterator().next();
80 }
81 }
82
83 /**
84 * Apply the decision to keep no value
85 */
86 public void keepNone() {
87 this.type = MultiValueDecisionType.KEEP_NONE;
88 }
89
90 /**
91 * Apply the decision to keep all values
92 */
93 public void keepAll() {
94 this.type = MultiValueDecisionType.KEEP_ALL;
95 }
96
97 /**
98 * Apply the decision to sum all numeric values
99 * @since 7743
100 */
101 public void sumAllNumeric() {
102 this.type = MultiValueDecisionType.SUM_ALL_NUMERIC;
103 }
104
105 /**
106 * Apply the decision to keep exactly one value
107 *
108 * @param value the value to keep
109 * @throws IllegalArgumentException if value is null
110 * @throws IllegalStateException if value is not in the list of known values for this tag
111 */
112 public void keepOne(String value) {
113 CheckParameterUtil.ensureParameterNotNull(value, "value");
114 if (!tags.getValues().contains(value))
115 throw new IllegalStateException(tr("Tag collection does not include the selected value ''{0}''.", value));
116 this.value = value;
117 this.type = MultiValueDecisionType.KEEP_ONE;
118 }
119
120 /**
121 * sets a new value for this
122 *
123 * @param value the new value
124 */
125 public void setNew(String value) {
126 this.value = Optional.ofNullable(value).orElse("");
127 this.type = MultiValueDecisionType.KEEP_ONE;
128 }
129
130 /**
131 * marks this as undecided
132 *
133 */
134 public void undecide() {
135 this.type = MultiValueDecisionType.UNDECIDED;
136 }
137
138 /**
139 * Replies the chosen value
140 *
141 * @return the chosen value
142 * @throws IllegalStateException if this resolution is not yet decided
143 */
144 public String getChosenValue() {
145 switch(type) {
146 case UNDECIDED: throw new IllegalStateException(tr("Not decided yet"));
147 case KEEP_ONE: return value;
148 case SUM_ALL_NUMERIC: return tags.getSummedValues(getKey());
149 case KEEP_ALL: return tags.getJoinedValues(getKey());
150 case KEEP_NONE:
151 default: return null;
152 }
153 }
154
155 /**
156 * Replies the list of possible, non empty values
157 *
158 * @return the list of possible, non empty values
159 */
160 public List<String> getValues() {
161 List<String> ret = new ArrayList<>(tags.getValues());
162 ret.remove("");
163 ret.remove(null);
164 Collections.sort(ret);
165 return ret;
166 }
167
168 /**
169 * Replies the key of the tag to be resolved by this resolution
170 *
171 * @return the key of the tag to be resolved by this resolution
172 */
173 public String getKey() {
174 return tags.getKeys().iterator().next();
175 }
176
177 /**
178 * Replies true if the empty value is a possible value in this resolution
179 *
180 * @return true if the empty value is a possible value in this resolution
181 */
182 public boolean canKeepNone() {
183 return tags.getValues().contains("");
184 }
185
186 /**
187 * Replies true, if this resolution has more than 1 possible non-empty values
188 *
189 * @return true, if this resolution has more than 1 possible non-empty values
190 */
191 public boolean canKeepAll() {
192 return getValues().size() > 1;
193 }
194
195 /**
196 * Replies true, if summing all numeric values is a possible value in this resolution
197 *
198 * @return true, if summing all numeric values is a possible value in this resolution
199 * @since 7743
200 */
201 public boolean canSumAllNumeric() {
202 return canKeepAll() && Arrays.stream(SUMMABLE_KEYS).anyMatch(key -> getKey().matches(key));
203 }
204
205 /**
206 * Replies true if this resolution is decided
207 *
208 * @return true if this resolution is decided
209 */
210 public boolean isDecided() {
211 return type != MultiValueDecisionType.UNDECIDED;
212 }
213
214 /**
215 * Replies the type of the resolution
216 *
217 * @return the type of the resolution
218 */
219 public MultiValueDecisionType getDecisionType() {
220 return type;
221 }
222
223 /**
224 * Applies the resolution to an {@link OsmPrimitive}
225 *
226 * @param primitive the primitive
227 * @throws IllegalStateException if this resolution is not resolved yet
228 *
229 */
230 public void applyTo(OsmPrimitive primitive) {
231 if (primitive == null) return;
232 if (!isDecided())
233 throw new IllegalStateException(tr("Not decided yet"));
234 String key = tags.getKeys().iterator().next();
235 if (type == MultiValueDecisionType.KEEP_NONE) {
236 primitive.remove(key);
237 } else {
238 primitive.put(key, getChosenValue());
239 }
240 }
241
242 /**
243 * Applies this resolution to a collection of primitives
244 *
245 * @param primitives the collection of primitives
246 * @throws IllegalStateException if this resolution is not resolved yet
247 */
248 public void applyTo(Collection<? extends OsmPrimitive> primitives) {
249 if (primitives == null) return;
250 for (OsmPrimitive primitive: primitives) {
251 if (primitive == null) {
252 continue;
253 }
254 applyTo(primitive);
255 }
256 }
257
258 /**
259 * Builds a change command for applying this resolution to a primitive
260 *
261 * @param primitive the primitive
262 * @return the change command
263 * @throws IllegalArgumentException if primitive is null
264 * @throws IllegalStateException if this resolution is not resolved yet
265 */
266 public Command buildChangeCommand(OsmPrimitive primitive) {
267 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
268 if (!isDecided())
269 throw new IllegalStateException(tr("Not decided yet"));
270 String key = tags.getKeys().iterator().next();
271 return new ChangePropertyCommand(primitive, key, getChosenValue());
272 }
273
274 /**
275 * Builds a change command for applying this resolution to a collection of primitives
276 *
277 * @param primitives the collection of primitives
278 * @return the change command
279 * @throws IllegalArgumentException if primitives is null
280 * @throws IllegalStateException if this resolution is not resolved yet
281 */
282 public Command buildChangeCommand(Collection<? extends OsmPrimitive> primitives) {
283 CheckParameterUtil.ensureParameterNotNull(primitives, "primitives");
284 if (!isDecided())
285 throw new IllegalStateException(tr("Not decided yet"));
286 String key = tags.getKeys().iterator().next();
287 return new ChangePropertyCommand(primitives, key, getChosenValue());
288 }
289
290 /**
291 * Replies a tag representing the current resolution. Null, if this resolution is not resolved yet.
292 *
293 * @return a tag representing the current resolution. Null, if this resolution is not resolved yet
294 */
295 public Tag getResolution() {
296 switch(type) {
297 case SUM_ALL_NUMERIC: return new Tag(getKey(), tags.getSummedValues(getKey()));
298 case KEEP_ALL: return new Tag(getKey(), tags.getJoinedValues(getKey()));
299 case KEEP_ONE: return new Tag(getKey(), value);
300 case KEEP_NONE: return new Tag(getKey(), "");
301 case UNDECIDED:
302 default: return null;
303 }
304 }
305}
Note: See TracBrowser for help on using the repository browser.