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

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

code cleanup

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