Changeset 10736 in josm for trunk/src/org
- Timestamp:
- 2016-08-05T20:02:23+02:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data/osm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/TagCollection.java
r10626 r10736 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.io.Serializable; 6 7 import java.util.ArrayList; 7 8 import java.util.Arrays; … … 15 16 import java.util.Map; 16 17 import java.util.Map.Entry; 18 import java.util.Objects; 17 19 import java.util.Set; 18 20 import java.util.regex.Pattern; 21 import java.util.stream.Collectors; 22 import java.util.stream.Stream; 19 23 20 24 import org.openstreetmap.josm.Main; … … 45 49 * @since 2008 46 50 */ 47 public class TagCollection implements Iterable<Tag> { 51 public class TagCollection implements Iterable<Tag>, Serializable { 52 53 private static final long serialVersionUID = 1; 48 54 49 55 /** … … 146 152 } 147 153 148 private final Set<Tag> tags = new HashSet<>();154 private final Map<Tag, Integer> tags = new HashMap<>(); 149 155 150 156 /** … … 163 169 public TagCollection(TagCollection other) { 164 170 if (other != null) { 165 tags. addAll(other.tags);171 tags.putAll(other.tags); 166 172 } 167 173 } … … 200 206 */ 201 207 public final void add(Tag tag) { 202 if (tag == null) return; 203 if (tags.contains(tag)) return; 204 tags.add(tag); 208 if (tag != null) { 209 tags.merge(tag, 1, (i, j) -> i + j); 210 } 211 } 212 213 /** 214 * Gets the number of this this tag was added to the collection. 215 * @param tag The tag 216 * @return The number of thimes this tag is used in this collection. 217 * @since 10736 218 */ 219 public int getTagOccurence(Tag tag) { 220 return tags.getOrDefault(tag, 0); 205 221 } 206 222 … … 225 241 */ 226 242 public final void add(TagCollection tags) { 227 if (tags == null) return; 228 this.tags.addAll(tags.tags); 243 if (tags != null) { 244 for (Entry<Tag, Integer> entry : tags.tags.entrySet()) { 245 this.tags.merge(entry.getKey(), entry.getValue(), (i, j) -> i + j); 246 } 247 } 229 248 } 230 249 … … 247 266 */ 248 267 public void remove(Collection<Tag> tags) { 249 if (tags == null) return; 250 this.tags.removeAll(tags); 268 if (tags != null) { 269 tags.stream().forEach(this::remove); 270 } 251 271 } 252 272 … … 258 278 */ 259 279 public void remove(TagCollection tags) { 260 if (tags == null) return; 261 this.tags.removeAll(tags.tags); 280 if (tags != null) { 281 tags.tags.keySet().stream().forEach(this::remove); 282 } 262 283 } 263 284 … … 269 290 */ 270 291 public void removeByKey(String key) { 271 if (key == null) return; 272 Iterator<Tag> it = tags.iterator(); 273 while (it.hasNext()) { 274 if (it.next().matchesKey(key)) { 275 it.remove(); 292 if (key != null) { 293 Iterator<Tag> it = tags.keySet().iterator(); 294 while (it.hasNext()) { 295 if (it.next().matchesKey(key)) { 296 it.remove(); 297 } 276 298 } 277 299 } … … 298 320 */ 299 321 public boolean contains(Tag tag) { 300 return tags.contains (tag);322 return tags.containsKey(tag); 301 323 } 302 324 … … 306 328 * @param key the key to look up 307 329 * @return true if this tag collection contains at least one tag with key <code>key</code>; false, otherwise 308 */ 330 * @deprecated Use {@link #hasTagsFor(String)} instead. 331 */ 332 @Deprecated 309 333 public boolean containsKey(String key) { 310 if (key == null) return false; 311 for (Tag tag: tags) { 312 if (tag.matchesKey(key)) return true; 313 } 314 return false; 334 return generateStreamForKey(key).findAny().isPresent(); 315 335 } 316 336 … … 324 344 */ 325 345 public boolean containsAll(Collection<Tag> tags) { 326 if (tags == null) return false; 327 return this.tags.containsAll(tags); 346 if (tags == null) { 347 return false; 348 } else { 349 return this.tags.keySet().containsAll(tags); 350 } 328 351 } 329 352 … … 336 359 */ 337 360 public boolean containsAllKeys(Collection<String> keys) { 338 if (keys == null) return false; 339 for (String key: keys) { 340 if (key == null) { 341 continue; 342 } 343 if (!containsKey(key)) return false; 344 } 345 return true; 361 if (keys == null) { 362 return false; 363 } else { 364 return keys.stream().filter(Objects::nonNull).allMatch(this::hasTagsFor); 365 } 346 366 } 347 367 … … 350 370 * 351 371 * @param key the key to look up 352 * @return the number of tags with key <code>key</code> . 0, if key is null.372 * @return the number of tags with key <code>key</code>, including the empty "" value. 0, if key is null. 353 373 */ 354 374 public int getNumTagsFor(String key) { 355 if (key == null) return 0; 356 int count = 0; 357 for (Tag tag: tags) { 358 if (tag.matchesKey(key)) { 359 count++; 360 } 361 } 362 return count; 375 return (int) generateStreamForKey(key).count(); 363 376 } 364 377 … … 381 394 */ 382 395 public boolean hasValuesFor(String key) { 383 if (key == null) return false; 384 Set<String> values = getTagsFor(key).getValues(); 385 values.remove(""); 386 return !values.isEmpty(); 396 return generateStreamForKey(key).filter(t -> !t.getValue().isEmpty()).findAny().isPresent(); 387 397 } 388 398 … … 397 407 */ 398 408 public boolean hasUniqueNonEmptyValue(String key) { 399 if (key == null) return false; 400 Set<String> values = getTagsFor(key).getValues(); 401 return values.size() == 1 && !values.contains(""); 409 return generateStreamForKey(key).filter(t -> !t.getValue().isEmpty()).count() == 1; 402 410 } 403 411 … … 410 418 */ 411 419 public boolean hasEmptyValue(String key) { 412 if (key == null) return false; 413 Set<String> values = getTagsFor(key).getValues(); 414 return values.contains(""); 420 return generateStreamForKey(key).anyMatch(t -> t.getValue().isEmpty()); 415 421 } 416 422 … … 424 430 */ 425 431 public boolean hasUniqueEmptyValue(String key) { 426 if (key == null) return false; 427 Set<String> values = getTagsFor(key).getValues(); 432 Set<String> values = getValues(key); 428 433 return values.size() == 1 && values.contains(""); 429 434 } … … 439 444 public TagCollection getTagsFor(String key) { 440 445 TagCollection ret = new TagCollection(); 441 if (key == null) 442 return ret; 443 for (Tag tag: tags) { 444 if (tag.matchesKey(key)) { 445 ret.add(tag); 446 } 447 } 446 generateStreamForKey(key).forEach(ret::add); 448 447 return ret; 449 448 } … … 475 474 */ 476 475 public Set<Tag> asSet() { 477 return new HashSet<>(tags );476 return new HashSet<>(tags.keySet()); 478 477 } 479 478 … … 482 481 * Note that the order of the list is not preserved between method invocations. 483 482 * 484 * @return the tags of this tag collection as list. 483 * @return the tags of this tag collection as list. There are no dupplicate values. 485 484 */ 486 485 public List<Tag> asList() { 487 return new ArrayList<>(tags );486 return new ArrayList<>(tags.keySet()); 488 487 } 489 488 … … 495 494 @Override 496 495 public Iterator<Tag> iterator() { 497 return tags. iterator();496 return tags.keySet().iterator(); 498 497 } 499 498 … … 504 503 */ 505 504 public Set<String> getKeys() { 506 Set<String> ret = new HashSet<>(); 507 for (Tag tag: tags) { 508 ret.add(tag.getKey()); 509 } 510 return ret; 505 return generateKeyStream().collect(Collectors.toCollection(HashSet::new)); 511 506 } 512 507 … … 517 512 */ 518 513 public Set<String> getKeysWithMultipleValues() { 519 Map<String, Integer> counters = new HashMap<>(); 520 for (Tag tag: tags) { 521 Integer v = counters.get(tag.getKey()); 522 counters.put(tag.getKey(), (v == null) ? 1 : v+1); 523 } 524 Set<String> ret = new HashSet<>(); 525 for (Entry<String, Integer> e : counters.entrySet()) { 526 if (e.getValue() > 1) { 527 ret.add(e.getKey()); 528 } 529 } 530 return ret; 514 HashSet<String> singleKeys = new HashSet<>(); 515 return generateKeyStream().filter(key -> !singleKeys.add(key)).collect(Collectors.toSet()); 531 516 } 532 517 … … 562 547 */ 563 548 public Set<String> getValues() { 564 Set<String> ret = new HashSet<>(); 565 for (Tag tag: tags) { 566 ret.add(tag.getValue()); 567 } 568 return ret; 549 return tags.keySet().stream().map(e -> e.getValue()).collect(Collectors.toSet()); 569 550 } 570 551 … … 578 559 */ 579 560 public Set<String> getValues(String key) { 580 Set<String> ret = new HashSet<>(); 581 if (key == null) return ret; 582 for (Tag tag: tags) { 583 if (tag.matchesKey(key)) { 584 ret.add(tag.getValue()); 585 } 586 } 587 return ret; 561 // null-safe 562 return generateStreamForKey(key).map(e -> e.getValue()).collect(Collectors.toSet()); 588 563 } 589 564 … … 594 569 */ 595 570 public boolean isApplicableToPrimitive() { 596 return size() == getKeys().size();571 return getKeysWithMultipleValues().isEmpty(); 597 572 } 598 573 … … 607 582 public void applyTo(Tagged primitive) { 608 583 if (primitive == null) return; 609 if (!isApplicableToPrimitive()) 610 throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values.")); 611 for (Tag tag: tags) { 584 ensureApplicableToPrimitive(); 585 for (Tag tag: tags.keySet()) { 612 586 if (tag.getValue() == null || tag.getValue().isEmpty()) { 613 587 primitive.remove(tag.getKey()); … … 628 602 public void applyTo(Collection<? extends Tagged> primitives) { 629 603 if (primitives == null) return; 630 if (!isApplicableToPrimitive()) 631 throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values.")); 604 ensureApplicableToPrimitive(); 632 605 for (Tagged primitive: primitives) { 633 606 applyTo(primitive); … … 645 618 public void replaceTagsOf(Tagged primitive) { 646 619 if (primitive == null) return; 647 if (!isApplicableToPrimitive()) 648 throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values.")); 620 ensureApplicableToPrimitive(); 649 621 primitive.removeAll(); 650 for (Tag tag: tags ) {622 for (Tag tag: tags.keySet()) { 651 623 primitive.put(tag.getKey(), tag.getValue()); 652 624 } … … 663 635 public void replaceTagsOf(Collection<? extends Tagged> primitives) { 664 636 if (primitives == null) return; 637 ensureApplicableToPrimitive(); 638 for (Tagged primitive: primitives) { 639 replaceTagsOf(primitive); 640 } 641 } 642 643 private void ensureApplicableToPrimitive() { 665 644 if (!isApplicableToPrimitive()) 666 645 throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values.")); 667 for (Tagged primitive: primitives) {668 replaceTagsOf(primitive);669 }670 646 } 671 647 … … 674 650 * 675 651 * @param other the other tag collection. If null, replies an empty tag collection. 676 * @return the intersection of this tag collection and another tag collection 652 * @return the intersection of this tag collection and another tag collection. All counts are set to 1. 677 653 */ 678 654 public TagCollection intersect(TagCollection other) { 679 655 TagCollection ret = new TagCollection(); 680 656 if (other != null) { 681 for (Tag tag: tags) { 682 if (other.contains(tag)) { 683 ret.add(tag); 684 } 685 } 657 tags.keySet().stream().filter(other::contains).forEach(ret::add); 686 658 } 687 659 return ret; … … 706 678 * 707 679 * @param other the other tag collection. May be null. 708 * @return the union of this tag collection and another tag collection 680 * @return the union of this tag collection and another tag collection. The tag count is summed. 709 681 */ 710 682 public TagCollection union(TagCollection other) { … … 758 730 759 731 /** 760 * Replies the sum of all numeric tag values. 732 * Replies the sum of all numeric tag values. Ignores dupplicates. 761 733 * @param key the key to look up 762 734 * 763 * @return the sum of all numeric tag values, as string 735 * @return the sum of all numeric tag values, as string. 764 736 * @since 7743 765 737 */ … … 776 748 } 777 749 750 private Stream<String> generateKeyStream() { 751 return tags.keySet().stream().map(tag -> tag.getKey()); 752 } 753 754 /** 755 * Get a stram for the given key. 756 * @param key The key 757 * @return The stream. An empty stream if key is <code>null</code> 758 */ 759 private Stream<Tag> generateStreamForKey(String key) { 760 return tags.keySet().stream().filter(e -> e.matchesKey(key)); 761 } 762 778 763 @Override 779 764 public String toString() { -
trunk/src/org/openstreetmap/josm/data/osm/TagMap.java
r10680 r10736 7 7 import java.util.ArrayList; 8 8 import java.util.Arrays; 9 import java.util.Collection; 9 10 import java.util.ConcurrentModificationException; 10 11 import java.util.Iterator; … … 151 152 } 152 153 154 /** 155 * Creates a new map using the given list of tags. For dupplicate keys the last value found is used. 156 * @param tags The tags 157 * @since 10736 158 */ 159 public TagMap(Collection<Tag> tags) { 160 for (Tag tag : tags) { 161 put(tag.getKey(), tag.getValue()); 162 } 163 } 164 153 165 @Override 154 166 public Set<Entry<String, String>> entrySet() { -
trunk/src/org/openstreetmap/josm/data/osm/Tagged.java
r8510 r10736 35 35 36 36 /** 37 * Sets a key/value pairs 38 * 39 * @param tag The tag to set. 40 * @since 10736 41 */ 42 default void put(Tag tag) { 43 put(tag.getKey(), tag.getValue()); 44 } 45 46 /** 37 47 * Replies the value of the given key; null, if there is no value for this key 38 48 *
Note:
See TracChangeset
for help on using the changeset viewer.