Ticket #13271: patch-tagcollection-counting.patch

File patch-tagcollection-counting.patch, 46.5 KB (added by michael2402, 9 years ago)
  • src/org/openstreetmap/josm/data/osm/TagCollection.java

    diff --git a/src/org/openstreetmap/josm/data/osm/TagCollection.java b/src/org/openstreetmap/josm/data/osm/TagCollection.java
    index b8324ae..5118c52 100644
    a b package org.openstreetmap.josm.data.osm;  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.io.Serializable;
    67import java.util.ArrayList;
    78import java.util.Arrays;
    89import java.util.Collection;
    import java.util.LinkedHashSet;  
    1415import java.util.List;
    1516import java.util.Map;
    1617import java.util.Map.Entry;
     18import java.util.Objects;
    1719import java.util.Set;
    1820import java.util.regex.Pattern;
     21import java.util.stream.Collectors;
     22import java.util.stream.Stream;
    1923
    2024import org.openstreetmap.josm.Main;
    2125import org.openstreetmap.josm.tools.Utils;
    import org.openstreetmap.josm.tools.Utils;  
    4448 *
    4549 * @since 2008
    4650 */
    47 public class TagCollection implements Iterable<Tag> {
     51public class TagCollection implements Iterable<Tag>, Serializable {
     52
     53    private static final long serialVersionUID = 1;
    4854
    4955    /**
    5056     * Creates a tag collection from the tags managed by a specific
    public class TagCollection implements Iterable<Tag> {  
    145151        return tags;
    146152    }
    147153
    148     private final Set<Tag> tags = new HashSet<>();
     154    private final Map<Tag, Integer> tags = new HashMap<>();
    149155
    150156    /**
    151157     * Creates an empty tag collection.
    public class TagCollection implements Iterable<Tag> {  
    162168     */
    163169    public TagCollection(TagCollection other) {
    164170        if (other != null) {
    165             tags.addAll(other.tags);
     171            tags.putAll(other.tags);
    166172        }
    167173    }
    168174
    public class TagCollection implements Iterable<Tag> {  
    199205     * @param tag the tag to add
    200206     */
    201207    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     */
     218    public int getTagOccurence(Tag tag) {
     219        return tags.getOrDefault(tag, 0);
    205220    }
    206221
    207222    /**
    public class TagCollection implements Iterable<Tag> {  
    224239     * @param tags the other tag collection
    225240     */
    226241    public final void add(TagCollection tags) {
    227         if (tags == null) return;
    228         this.tags.addAll(tags.tags);
     242        if (tags != null) {
     243            for (Entry<Tag, Integer> entry : tags.tags.entrySet()) {
     244                this.tags.merge(entry.getKey(), entry.getValue(), (i, j) -> i + j);
     245            }
     246        }
    229247    }
    230248
    231249    /**
    public class TagCollection implements Iterable<Tag> {  
    246264     * @param tags the tags to be removed
    247265     */
    248266    public void remove(Collection<Tag> tags) {
    249         if (tags == null) return;
    250         this.tags.removeAll(tags);
     267        if (tags != null) {
     268            tags.stream().forEach(this::remove);
     269        }
    251270    }
    252271
    253272    /**
    public class TagCollection implements Iterable<Tag> {  
    257276     * @param tags the tag collection to be removed.
    258277     */
    259278    public void remove(TagCollection tags) {
    260         if (tags == null) return;
    261         this.tags.removeAll(tags.tags);
     279        if (tags != null) {
     280            tags.tags.keySet().stream().forEach(this::remove);
     281        }
    262282    }
    263283
    264284    /**
    public class TagCollection implements Iterable<Tag> {  
    268288     * @param key the key to be removed
    269289     */
    270290    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();
     291        if (key != null) {
     292            Iterator<Tag> it = tags.keySet().iterator();
     293            while (it.hasNext()) {
     294                if (it.next().matchesKey(key)) {
     295                    it.remove();
     296                }
    276297            }
    277298        }
    278299    }
    public class TagCollection implements Iterable<Tag> {  
    297318     * @return true if the this tag collection contains <code>tag</code>; false, otherwise
    298319     */
    299320    public boolean contains(Tag tag) {
    300         return tags.contains(tag);
     321        return tags.containsKey(tag);
    301322    }
    302323
    303324    /**
    public class TagCollection implements Iterable<Tag> {  
    305326     *
    306327     * @param key the key to look up
    307328     * @return true if this tag collection contains at least one tag with key <code>key</code>; false, otherwise
     329     * @deprecated Use {@link #hasTagsFor(String)} instead.
    308330     */
     331    @Deprecated
    309332    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;
     333        return generateStreamForKey(key).findAny().isPresent();
    315334    }
    316335
    317336    /**
    public class TagCollection implements Iterable<Tag> {  
    323342     * false, if tags is null.
    324343     */
    325344    public boolean containsAll(Collection<Tag> tags) {
    326         if (tags == null) return false;
    327         return this.tags.containsAll(tags);
     345        if (tags == null) {
     346            return false;
     347        } else {
     348            return this.tags.keySet().containsAll(tags);
     349        }
    328350    }
    329351
    330352    /**
    public class TagCollection implements Iterable<Tag> {  
    335357     * @return true if this tag collection at least one tag for every key in <code>keys</code>.
    336358     */
    337359    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;
     360        if (keys == null) {
     361            return false;
     362        } else {
     363            return keys.stream().filter(Objects::nonNull).allMatch(this::hasTagsFor);
    344364        }
    345         return true;
    346365    }
    347366
    348367    /**
    349368     * Replies the number of tags with key <code>key</code>
    350369     *
    351370     * @param key the key to look up
    352      * @return the number of tags with key <code>key</code>. 0, if key is null.
     371     * @return the number of tags with key <code>key</code>, including the empty "" value. 0, if key is null.
    353372     */
    354373    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;
     374        return (int) generateStreamForKey(key).count();
    363375    }
    364376
    365377    /**
    public class TagCollection implements Iterable<Tag> {  
    380392     * @return true it there is at least one tag with a non empty value for key.
    381393     */
    382394    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();
     395        return generateStreamForKey(key).filter(t -> !t.getValue().isEmpty()).findAny().isPresent();
    387396    }
    388397
    389398    /**
    public class TagCollection implements Iterable<Tag> {  
    396405     * if the value of this tag is not empty
    397406     */
    398407    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("");
     408        return generateStreamForKey(key).filter(t -> !t.getValue().isEmpty()).count() == 1;
    402409    }
    403410
    404411    /**
    public class TagCollection implements Iterable<Tag> {  
    409416     * @return true if there is a tag with an empty value for <code>key</code>
    410417     */
    411418    public boolean hasEmptyValue(String key) {
    412         if (key == null) return false;
    413         Set<String> values = getTagsFor(key).getValues();
    414         return values.contains("");
     419        return generateStreamForKey(key).anyMatch(t -> t.getValue().isEmpty());
    415420    }
    416421
    417422    /**
    public class TagCollection implements Iterable<Tag> {  
    423428     * the value for this tag is empty
    424429     */
    425430    public boolean hasUniqueEmptyValue(String key) {
    426         if (key == null) return false;
    427         Set<String> values = getTagsFor(key).getValues();
     431        Set<String> values = getValues(key);
    428432        return values.size() == 1 && values.contains("");
    429433    }
    430434
    public class TagCollection implements Iterable<Tag> {  
    438442     */
    439443    public TagCollection getTagsFor(String key) {
    440444        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         }
     445        generateStreamForKey(key).forEach(ret::add);
    448446        return ret;
    449447    }
    450448
    public class TagCollection implements Iterable<Tag> {  
    474472     * @return the tags of this tag collection as set
    475473     */
    476474    public Set<Tag> asSet() {
    477         return new HashSet<>(tags);
     475        return new HashSet<>(tags.keySet());
    478476    }
    479477
    480478    /**
    481479     * Replies the tags of this tag collection as list.
    482480     * Note that the order of the list is not preserved between method invocations.
    483481     *
    484      * @return the tags of this tag collection as list.
     482     * @return the tags of this tag collection as list. There are no dupplicate values.
    485483     */
    486484    public List<Tag> asList() {
    487         return new ArrayList<>(tags);
     485        return new ArrayList<>(tags.keySet());
    488486    }
    489487
    490488    /**
    public class TagCollection implements Iterable<Tag> {  
    494492     */
    495493    @Override
    496494    public Iterator<Tag> iterator() {
    497         return tags.iterator();
     495        return tags.keySet().iterator();
    498496    }
    499497
    500498    /**
    public class TagCollection implements Iterable<Tag> {  
    503501     * @return the set of keys of this tag collection
    504502     */
    505503    public Set<String> getKeys() {
    506         Set<String> ret = new HashSet<>();
    507         for (Tag tag: tags) {
    508             ret.add(tag.getKey());
    509         }
    510         return ret;
     504        return generateKeyStream().collect(Collectors.toCollection(HashSet::new));
    511505    }
    512506
    513507    /**
    public class TagCollection implements Iterable<Tag> {  
    516510     * @return the set of keys which have at least 2 matching tags.
    517511     */
    518512    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;
     513        HashSet<String> singleKeys = new HashSet<>();
     514        return generateKeyStream().filter(key -> !singleKeys.add(key)).collect(Collectors.toSet());
    531515    }
    532516
    533517    /**
    public class TagCollection implements Iterable<Tag> {  
    561545     * @return the set of values
    562546     */
    563547    public Set<String> getValues() {
    564         Set<String> ret = new HashSet<>();
    565         for (Tag tag: tags) {
    566             ret.add(tag.getValue());
    567         }
    568         return ret;
     548        return tags.keySet().stream().map(e -> e.getValue()).collect(Collectors.toSet());
    569549    }
    570550
    571551    /**
    public class TagCollection implements Iterable<Tag> {  
    577557     * are no values for the given key
    578558     */
    579559    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;
     560        // null-safe
     561        return generateStreamForKey(key).map(e -> e.getValue()).collect(Collectors.toSet());
    588562    }
    589563
    590564    /**
    public class TagCollection implements Iterable<Tag> {  
    593567     * @return {@code true} if for every key there is one tag only
    594568     */
    595569    public boolean isApplicableToPrimitive() {
    596         return size() == getKeys().size();
     570        return getKeysWithMultipleValues().isEmpty();
    597571    }
    598572
    599573    /**
    public class TagCollection implements Iterable<Tag> {  
    606580     */
    607581    public void applyTo(Tagged primitive) {
    608582        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) {
     583        ensureApplicableToPrimitive();
     584        for (Tag tag: tags.keySet()) {
    612585            if (tag.getValue() == null || tag.getValue().isEmpty()) {
    613586                primitive.remove(tag.getKey());
    614587            } else {
    public class TagCollection implements Iterable<Tag> {  
    627600     */
    628601    public void applyTo(Collection<? extends Tagged> primitives) {
    629602        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."));
     603        ensureApplicableToPrimitive();
    632604        for (Tagged primitive: primitives) {
    633605            applyTo(primitive);
    634606        }
    public class TagCollection implements Iterable<Tag> {  
    644616     */
    645617    public void replaceTagsOf(Tagged primitive) {
    646618        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."));
     619        ensureApplicableToPrimitive();
    649620        primitive.removeAll();
    650         for (Tag tag: tags) {
     621        for (Tag tag: tags.keySet()) {
    651622            primitive.put(tag.getKey(), tag.getValue());
    652623        }
    653624    }
    public class TagCollection implements Iterable<Tag> {  
    662633     */
    663634    public void replaceTagsOf(Collection<? extends Tagged> primitives) {
    664635        if (primitives == null) return;
    665         if (!isApplicableToPrimitive())
    666             throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values."));
     636        ensureApplicableToPrimitive();
    667637        for (Tagged primitive: primitives) {
    668638            replaceTagsOf(primitive);
    669639        }
    670640    }
    671641
     642    private void ensureApplicableToPrimitive() {
     643        if (!isApplicableToPrimitive())
     644            throw new IllegalStateException(tr("Tag collection cannot be applied to a primitive because there are keys with multiple values."));
     645    }
     646
    672647    /**
    673648     * Builds the intersection of this tag collection and another tag collection
    674649     *
    675650     * @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
     651     * @return the intersection of this tag collection and another tag collection. All counts are set to 1.
    677652     */
    678653    public TagCollection intersect(TagCollection other) {
    679654        TagCollection ret = new TagCollection();
    680655        if (other != null) {
    681             for (Tag tag: tags) {
    682                 if (other.contains(tag)) {
    683                     ret.add(tag);
    684                 }
    685             }
     656            tags.keySet().stream().filter(other::contains).forEach(ret::add);
    686657        }
    687658        return ret;
    688659    }
    public class TagCollection implements Iterable<Tag> {  
    705676     * Replies the union of this tag collection and another tag collection
    706677     *
    707678     * @param other the other tag collection. May be null.
    708      * @return the union of this tag collection and another tag collection
     679     * @return the union of this tag collection and another tag collection. The tag count is summed.
    709680     */
    710681    public TagCollection union(TagCollection other) {
    711682        TagCollection ret = new TagCollection(this);
    public class TagCollection implements Iterable<Tag> {  
    757728    }
    758729
    759730    /**
    760      * Replies the sum of all numeric tag values.
     731     * Replies the sum of all numeric tag values. Ignores dupplicates.
    761732     * @param key the key to look up
    762733     *
    763      * @return the sum of all numeric tag values, as string
     734     * @return the sum of all numeric tag values, as string.
    764735     * @since 7743
    765736     */
    766737    public String getSummedValues(String key) {
    public class TagCollection implements Iterable<Tag> {  
    775746        return Integer.toString(result);
    776747    }
    777748
     749    private Stream<String> generateKeyStream() {
     750        return tags.keySet().stream().map(tag -> tag.getKey());
     751    }
     752
     753    /**
     754     * Get a stram for the given key.
     755     * @param key The key
     756     * @return The stream. An empty stream if key is <code>null</code>
     757     */
     758    private Stream<Tag> generateStreamForKey(String key) {
     759        return tags.keySet().stream().filter(e -> e.matchesKey(key));
     760    }
     761
    778762    @Override
    779763    public String toString() {
    780764        return tags.toString();
  • src/org/openstreetmap/josm/data/osm/TagMap.java

    diff --git a/src/org/openstreetmap/josm/data/osm/TagMap.java b/src/org/openstreetmap/josm/data/osm/TagMap.java
    index 12a1dd6..c658333 100644
    a b import java.util.AbstractMap;  
    66import java.util.AbstractSet;
    77import java.util.ArrayList;
    88import java.util.Arrays;
     9import java.util.Collection;
    910import java.util.ConcurrentModificationException;
    1011import java.util.Iterator;
    1112import java.util.List;
    public class TagMap extends AbstractMap<String, String> implements Serializable  
    150151        }
    151152    }
    152153
     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     */
     158    public TagMap(Collection<Tag> tags) {
     159        for(Tag tag : tags) {
     160            put(tag.getKey(), tag.getValue());
     161        }
     162    }
     163
    153164    @Override
    154165    public Set<Entry<String, String>> entrySet() {
    155166        return new TagEntrySet(tags);
  • src/org/openstreetmap/josm/data/osm/Tagged.java

    diff --git a/src/org/openstreetmap/josm/data/osm/Tagged.java b/src/org/openstreetmap/josm/data/osm/Tagged.java
    index fb9cf44..5cf94a2 100644
    a b public interface Tagged {  
    3434    void put(String key, String value);
    3535
    3636    /**
     37     * Sets a key/value pairs
     38     *
     39     * @param tag The tag to set.
     40     */
     41    default void put(Tag tag) {
     42        put(tag.getKey(), tag.getValue());
     43    }
     44
     45    /**
    3746     * Replies the value of the given key; null, if there is no value for this key
    3847     *
    3948     * @param key the key
  • new file test/unit/org/openstreetmap/josm/data/osm/TagCollectionTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/TagCollectionTest.java b/test/unit/org/openstreetmap/josm/data/osm/TagCollectionTest.java
    new file mode 100644
    index 0000000..db8c5ed
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.osm;
     3
     4import static org.junit.Assert.assertEquals;
     5import static org.junit.Assert.assertFalse;
     6import static org.junit.Assert.assertTrue;
     7import static org.junit.Assert.fail;
     8
     9import java.util.Arrays;
     10import java.util.Collection;
     11import java.util.Collections;
     12import java.util.HashMap;
     13import java.util.Iterator;
     14import java.util.List;
     15import java.util.Map;
     16import java.util.Set;
     17import java.util.stream.Collectors;
     18import java.util.stream.Stream;
     19
     20import org.junit.Ignore;
     21import org.junit.Rule;
     22import org.junit.Test;
     23import org.openstreetmap.josm.testutils.JOSMTestRules;
     24
     25import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     26
     27/**
     28 * Tests of {@link TagCollection}.
     29 * @author Michael Zangl
     30 * @since xxx
     31 */
     32public class TagCollectionTest {
     33    private final Tag tagA = new Tag("k", "v");
     34    private final Tag tagB = new Tag("k", "b");
     35    private final Tag tagC = new Tag("k2", "b");
     36    private final Tag tagD = new Tag("k3", "c");
     37    private final Tag tagEmpty = new Tag("k", "");
     38    private final Tag tagNullKey = new Tag(null, "b");
     39    private final Tag tagNullValue = new Tag("k2", null);
     40
     41    /**
     42     * We need prefs for using primitives
     43     */
     44    @Rule
     45    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     46    public JOSMTestRules test = new JOSMTestRules().preferences();
     47
     48    private void assertTagCounts(TagCollection collection, int a, int b, int c, int d) {
     49        assertEquals(a, collection.getTagOccurence(tagA));
     50        assertEquals(b, collection.getTagOccurence(tagB));
     51        assertEquals(c, collection.getTagOccurence(tagC));
     52        assertEquals(d, collection.getTagOccurence(tagD));
     53    }
     54
     55    /**
     56     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#from(org.openstreetmap.josm.data.osm.Tagged)}.
     57     */
     58    @Test
     59    public void testFromTagged() {
     60        TagCollection c = TagCollection.from(tagA);
     61        assertTagCounts(c, 1, 0, 0, 0);
     62
     63        NodeData p1 = new NodeData();
     64        p1.put(tagA);
     65        p1.put(tagC);
     66        TagCollection d = TagCollection.from(p1);
     67        assertTagCounts(d, 1, 0, 1, 0);
     68
     69        TagCollection e = TagCollection.from((Tagged) null);
     70        assertTagCounts(e, 0, 0, 0, 0);
     71    }
     72
     73    /**
     74     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#from(java.util.Map)}.
     75     */
     76    @Test
     77    public void testFromMapOfStringString() {
     78        TagCollection c = TagCollection.from(tagA.getKeys());
     79        assertTagCounts(c, 1, 0, 0, 0);
     80
     81        HashMap<String, String> map = new HashMap<>();
     82        map.putAll(tagA.getKeys());
     83        map.putAll(tagC.getKeys());
     84        TagCollection d = TagCollection.from(map);
     85        assertTagCounts(d, 1, 0, 1, 0);
     86
     87        TagCollection e = TagCollection.from((Map<String, String>) null);
     88        assertTagCounts(e, 0, 0, 0, 0);
     89    }
     90
     91    /**
     92     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#unionOfAllPrimitives(java.util.Collection)}.
     93     */
     94    @Test
     95    public void testUnionOfAllPrimitivesCollectionOfQextendsTagged() {
     96        TagCollection c = TagCollection.unionOfAllPrimitives(Arrays.asList(tagA));
     97        assertEquals(1, c.getTagOccurence(tagA));
     98
     99        TagCollection d = TagCollection.unionOfAllPrimitives(Arrays.asList(tagA, tagC));
     100        assertTagCounts(d, 1, 0, 1, 0);
     101
     102        TagCollection e = TagCollection.unionOfAllPrimitives((Collection<? extends Tagged>) null);
     103        assertTagCounts(e, 0, 0, 0, 0);
     104
     105        TagCollection f = TagCollection.unionOfAllPrimitives(Arrays.<Tagged>asList());
     106        assertTagCounts(f, 0, 0, 0, 0);
     107
     108        TagCollection g = TagCollection.unionOfAllPrimitives(Arrays.asList(tagA, tagC, tagC, null));
     109        assertTagCounts(g, 1, 0, 2, 0);
     110    }
     111
     112    /**
     113     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#commonToAllPrimitives(java.util.Collection)}.
     114     */
     115    @Test
     116    @Ignore("TODO")
     117    public void testCommonToAllPrimitives() {
     118        fail("Not yet implemented");
     119    }
     120
     121    /**
     122     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#unionOfAllPrimitives(org.openstreetmap.josm.data.osm.DataSet)}.
     123     */
     124    @Test
     125    @Ignore("TODO")
     126    public void testUnionOfAllPrimitivesDataSet() {
     127        fail("Not yet implemented");
     128    }
     129
     130    /**
     131     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#TagCollection()}.
     132     */
     133    @Test
     134    public void testTagCollection() {
     135        TagCollection c = new TagCollection();
     136        assertTagCounts(c, 0, 0, 0, 0);
     137    }
     138
     139    /**
     140     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#TagCollection(org.openstreetmap.josm.data.osm.TagCollection)}.
     141     */
     142    @Test
     143    public void testTagCollectionTagCollection() {
     144        TagCollection blueprint = TagCollection.unionOfAllPrimitives(Arrays.asList(tagA, tagC, tagC));
     145        TagCollection c = new TagCollection(blueprint);
     146        assertTagCounts(c, 1, 0, 2, 0);
     147
     148        TagCollection d = new TagCollection((TagCollection) null);
     149        assertTagCounts(d, 0, 0, 0, 0);
     150    }
     151
     152    /**
     153     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#TagCollection(java.util.Collection)}.
     154     */
     155    @Test
     156    public void testTagCollectionCollectionOfTag() {
     157        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     158        assertTagCounts(c, 1, 0, 2, 0);
     159
     160        TagCollection d = new TagCollection((Collection<Tag>) null);
     161        assertTagCounts(d, 0, 0, 0, 0);
     162    }
     163
     164    /**
     165     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#size()}.
     166     */
     167    @Test
     168    public void testSize() {
     169        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     170        assertEquals(2, c.size());
     171
     172        TagCollection d = new TagCollection();
     173        assertEquals(0, d.size());
     174    }
     175
     176    /**
     177     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#isEmpty()}.
     178     */
     179    @Test
     180    public void testIsEmpty() {
     181        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     182        assertFalse(c.isEmpty());
     183
     184        TagCollection d = new TagCollection();
     185        assertTrue(d.isEmpty());
     186    }
     187
     188    /**
     189     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#add(org.openstreetmap.josm.data.osm.Tag)}.
     190     */
     191    @Test
     192    public void testAddTag() {
     193        TagCollection c = new TagCollection();
     194        assertTagCounts(c, 0, 0, 0, 0);
     195        c.add(tagC);
     196        assertTagCounts(c, 0, 0, 1, 0);
     197        c.add(tagA);
     198        c.add(tagC);
     199        assertTagCounts(c, 1, 0, 2, 0);
     200        c.add((Tag) null);
     201        assertTagCounts(c, 1, 0, 2, 0);
     202    }
     203
     204    /**
     205     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getTagOccurence(org.openstreetmap.josm.data.osm.Tag)}.
     206     */
     207    @Test
     208    public void testGetTagCount() {
     209        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     210        assertEquals(2, c.getTagOccurence(tagC));
     211        assertEquals(0, c.getTagOccurence(tagB));
     212        assertEquals(0, c.getTagOccurence(tagNullKey));
     213        assertEquals(0, c.getTagOccurence(tagNullValue));
     214    }
     215
     216    /**
     217     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#add(java.util.Collection)}.
     218     */
     219    @Test
     220    public void testAddCollectionOfTag() {
     221        TagCollection c = new TagCollection();
     222        assertTagCounts(c, 0, 0, 0, 0);
     223        c.add(Arrays.asList(tagC));
     224        assertTagCounts(c, 0, 0, 1, 0);
     225        c.add(Arrays.asList(tagA, tagC));
     226        assertTagCounts(c, 1, 0, 2, 0);
     227        c.add(Collections.emptyList());
     228        assertTagCounts(c, 1, 0, 2, 0);
     229        c.add((Collection<Tag>) null);
     230        assertTagCounts(c, 1, 0, 2, 0);
     231    }
     232
     233    /**
     234     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#add(org.openstreetmap.josm.data.osm.TagCollection)}.
     235     */
     236    @Test
     237    public void testAddTagCollection() {
     238        TagCollection c = new TagCollection();
     239        assertTagCounts(c, 0, 0, 0, 0);
     240        c.add(new TagCollection(Arrays.asList(tagC)));
     241        assertTagCounts(c, 0, 0, 1, 0);
     242        c.add(new TagCollection(Arrays.asList(tagA, tagC)));
     243        assertTagCounts(c, 1, 0, 2, 0);
     244        c.add(new TagCollection());
     245        assertTagCounts(c, 1, 0, 2, 0);
     246        c.add((TagCollection) null);
     247        assertTagCounts(c, 1, 0, 2, 0);
     248    }
     249
     250    /**
     251     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#remove(org.openstreetmap.josm.data.osm.Tag)}.
     252     */
     253    @Test
     254    public void testRemoveTag() {
     255        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     256        assertTagCounts(c, 1, 0, 2, 0);
     257        c.remove(tagC);
     258        assertTagCounts(c, 1, 0, 0, 0);
     259        c.remove(tagB);
     260        assertTagCounts(c, 1, 0, 0, 0);
     261        c.remove((Tag) null);
     262        assertTagCounts(c, 1, 0, 0, 0);
     263    }
     264
     265    /**
     266     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#remove(java.util.Collection)}.
     267     */
     268    @Test
     269    public void testRemoveCollectionOfTag() {
     270        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     271        assertTagCounts(c, 1, 0, 2, 0);
     272        c.remove(Arrays.asList(tagC, tagB));
     273        assertTagCounts(c, 1, 0, 0, 0);
     274        c.remove((Collection<Tag>) null);
     275        assertTagCounts(c, 1, 0, 0, 0);
     276    }
     277
     278    /**
     279     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#remove(org.openstreetmap.josm.data.osm.TagCollection)}.
     280     */
     281    @Test
     282    public void testRemoveTagCollection() {
     283        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagC));
     284        assertTagCounts(c, 1, 0, 2, 0);
     285        c.remove(new TagCollection(Arrays.asList(tagC, tagB)));
     286        assertTagCounts(c, 1, 0, 0, 0);
     287        c.remove(new TagCollection());
     288        assertTagCounts(c, 1, 0, 0, 0);
     289        c.remove((TagCollection) null);
     290        assertTagCounts(c, 1, 0, 0, 0);
     291    }
     292
     293    /**
     294     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#removeByKey(java.lang.String)}.
     295     */
     296    @Test
     297    public void testRemoveByKeyString() {
     298        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagB, tagC));
     299        assertTagCounts(c, 1, 2, 1, 0);
     300        c.removeByKey("k");
     301        assertTagCounts(c, 0, 0, 1, 0);
     302        c.removeByKey((String) null);
     303        assertTagCounts(c, 0, 0, 1, 0);
     304    }
     305
     306    /**
     307     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#removeByKey(java.util.Collection)}.
     308     */
     309    @Test
     310    public void testRemoveByKeyCollectionOfString() {
     311        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagB, tagC, tagD));
     312        assertTagCounts(c, 1, 2, 1, 1);
     313        c.removeByKey(Arrays.asList("k", "k2", null));
     314        assertTagCounts(c, 0, 0, 0, 1);
     315        c.removeByKey((Collection<String>) null);
     316        assertTagCounts(c, 0, 0, 0, 1);
     317    }
     318
     319    /**
     320     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#contains(org.openstreetmap.josm.data.osm.Tag)}.
     321     */
     322    @Test
     323    public void testContains() {
     324        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagB));
     325        assertTrue(c.contains(tagA));
     326        assertTrue(c.contains(tagB));
     327        assertFalse(c.contains(tagC));
     328    }
     329
     330    /**
     331     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#containsAll(java.util.Collection)}.
     332     */
     333    @Test
     334    public void testContainsAll() {
     335        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagB));
     336        assertTrue(c.containsAll(Arrays.asList(tagA, tagB)));
     337        assertFalse(c.containsAll(Arrays.asList(tagA, tagC)));
     338        assertTrue(c.containsAll(Arrays.asList()));
     339        assertFalse(c.containsAll(null));
     340    }
     341
     342    /**
     343     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#containsAllKeys(java.util.Collection)}.
     344     */
     345    @Test
     346    public void testContainsAllKeys() {
     347        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagC));
     348        assertTrue(c.containsAllKeys(Arrays.asList("k", "k2")));
     349        assertFalse(c.containsAllKeys(Arrays.asList("k", "k3")));
     350        assertTrue(c.containsAllKeys(Arrays.asList()));
     351        assertFalse(c.containsAllKeys(null));
     352    }
     353
     354    /**
     355     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getNumTagsFor(java.lang.String)}.
     356     */
     357    @Test
     358    public void testGetNumTagsFor() {
     359        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagC));
     360        assertEquals(2, c.getNumTagsFor("k"));
     361        assertEquals(1, c.getNumTagsFor("k2"));
     362        assertEquals(0, c.getNumTagsFor("k3"));
     363    }
     364
     365    /**
     366     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#hasTagsFor(java.lang.String)}.
     367     */
     368    @Test
     369    public void testHasTagsFor() {
     370        TagCollection c = new TagCollection(Arrays.asList(tagA, tagB, tagC));
     371        assertTrue(c.hasTagsFor("k"));
     372        assertTrue(c.hasTagsFor("k2"));
     373        assertFalse(c.hasTagsFor("k3"));
     374    }
     375
     376    /**
     377     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#hasValuesFor(java.lang.String)}.
     378     */
     379    @Test
     380    public void testHasValuesFor() {
     381        TagCollection c = new TagCollection(Arrays.asList(tagC, tagEmpty));
     382        assertFalse(c.hasValuesFor("k"));
     383        assertTrue(c.hasValuesFor("k2"));
     384        assertFalse(c.hasValuesFor("k3"));
     385    }
     386
     387    /**
     388     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#hasUniqueNonEmptyValue(java.lang.String)}.
     389     */
     390    @Test
     391    public void testHasUniqueNonEmptyValue() {
     392        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagEmpty));
     393        assertTrue(c.hasUniqueNonEmptyValue("k"));
     394        assertTrue(c.hasUniqueNonEmptyValue("k2"));
     395        assertFalse(c.hasUniqueNonEmptyValue("k3"));
     396
     397        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagEmpty));
     398        assertFalse(d.hasUniqueNonEmptyValue("k"));
     399        assertTrue(d.hasUniqueNonEmptyValue("k2"));
     400        assertFalse(d.hasUniqueNonEmptyValue("k3"));
     401    }
     402
     403    /**
     404     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#hasEmptyValue(java.lang.String)}.
     405     */
     406    @Test
     407    public void testHasEmptyValue() {
     408        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC, tagEmpty));
     409        assertTrue(c.hasEmptyValue("k"));
     410        assertFalse(c.hasEmptyValue("k2"));
     411        assertFalse(c.hasEmptyValue("k3"));
     412    }
     413
     414    /**
     415     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#hasUniqueEmptyValue(java.lang.String)}.
     416     */
     417    @Test
     418    public void testHasUniqueEmptyValue() {
     419        TagCollection c = new TagCollection(Arrays.asList(tagC, tagEmpty));
     420        assertTrue(c.hasUniqueEmptyValue("k"));
     421        assertFalse(c.hasUniqueEmptyValue("k2"));
     422        assertFalse(c.hasUniqueEmptyValue("k3"));
     423
     424        TagCollection d = new TagCollection(Arrays.asList());
     425        assertFalse(d.hasUniqueEmptyValue("k"));
     426        assertFalse(d.hasUniqueEmptyValue("k2"));
     427        assertFalse(d.hasUniqueEmptyValue("k3"));
     428    }
     429
     430    /**
     431     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getTagsFor(java.lang.String)}.
     432     */
     433    @Test
     434    public void testGetTagsForString() {
     435        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagEmpty));
     436        TagCollection collection = d.getTagsFor("k");
     437        assertTagCounts(collection, 1, 1, 0, 0);
     438        assertEquals(1, collection.getTagOccurence(tagEmpty));
     439    }
     440
     441    /**
     442     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getTagsFor(java.util.Collection)}.
     443     */
     444    @Test
     445    public void testGetTagsForCollectionOfString() {
     446        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagEmpty));
     447        TagCollection collection = d.getTagsFor(Arrays.asList("k", "k2"));
     448        assertTagCounts(collection, 1, 1, 1, 0);
     449        assertEquals(1, collection.getTagOccurence(tagEmpty));
     450    }
     451
     452    /**
     453     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#asSet()}.
     454     */
     455    @Test
     456    public void testAsSet() {
     457        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagC));
     458        Set<Tag> set = d.asSet();
     459        assertEquals(3, set.size());
     460        assertTrue(set.contains(tagA));
     461        assertTrue(set.contains(tagB));
     462        assertTrue(set.contains(tagC));
     463    }
     464
     465    /**
     466     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#asList()}.
     467     */
     468    @Test
     469    public void testAsList() {
     470        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagC));
     471        List<Tag> set = d.asList();
     472        assertEquals(3, set.size());
     473        assertTrue(set.contains(tagA));
     474        assertTrue(set.contains(tagB));
     475        assertTrue(set.contains(tagC));
     476    }
     477
     478    /**
     479     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#iterator()}.
     480     */
     481    @Test
     482    public void testIterator() {
     483        TagCollection d = new TagCollection(Arrays.asList(tagA));
     484        Iterator<Tag> it = d.iterator();
     485        assertTrue(it.hasNext());
     486        assertEquals(tagA, it.next());
     487        assertFalse(it.hasNext());
     488    }
     489
     490    /**
     491     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getKeys()}.
     492     */
     493    @Test
     494    public void testGetKeys() {
     495        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagC));
     496        Set<String> set = d.getKeys();
     497        assertEquals(2, set.size());
     498        assertTrue(set.contains("k"));
     499        assertTrue(set.contains("k2"));
     500    }
     501
     502    /**
     503     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getKeysWithMultipleValues()}.
     504     */
     505    @Test
     506    public void testGetKeysWithMultipleValues() {
     507        TagCollection d = new TagCollection(Arrays.asList(tagA, tagB, tagC, tagC));
     508        Set<String> set = d.getKeysWithMultipleValues();
     509        assertEquals(1, set.size());
     510        assertTrue(set.contains("k"));
     511    }
     512
     513    /**
     514     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#setUniqueForKey(org.openstreetmap.josm.data.osm.Tag)}.
     515     */
     516    @Test
     517    public void testSetUniqueForKeyTag() {
     518        TagCollection d = new TagCollection(Arrays.asList(tagA, tagA, tagB, tagC, tagC));
     519        assertTagCounts(d, 2, 1, 2, 0);
     520        d.setUniqueForKey(tagA);
     521        assertTagCounts(d, 1, 0, 2, 0);
     522    }
     523
     524    /**
     525     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#setUniqueForKey(java.lang.String, java.lang.String)}.
     526     */
     527    @Test
     528    public void testSetUniqueForKeyStringString() {
     529        TagCollection d = new TagCollection(Arrays.asList(tagA, tagA, tagB, tagC, tagC));
     530        assertTagCounts(d, 2, 1, 2, 0);
     531        d.setUniqueForKey(tagA.getKey(), tagA.getValue());
     532        assertTagCounts(d, 1, 0, 2, 0);
     533    }
     534
     535    /**
     536     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getValues()}.
     537     */
     538    @Test
     539    public void testGetValues() {
     540        TagCollection d = new TagCollection(Arrays.asList(tagA, tagA, tagB, tagC, tagEmpty));
     541        Set<String> set = d.getValues();
     542        assertEquals(3, set.size());
     543        assertTrue(set.contains("v"));
     544        assertTrue(set.contains("b"));
     545        assertTrue(set.contains(""));
     546    }
     547
     548    /**
     549     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getValues(java.lang.String)}.
     550     */
     551    @Test
     552    public void testGetValuesString() {
     553        TagCollection d = new TagCollection(Arrays.asList(tagA, tagA, tagC, tagEmpty));
     554        Set<String> set = d.getValues("k");
     555        assertEquals(2, set.size());
     556        assertTrue(set.contains("v"));
     557        assertTrue(set.contains(""));
     558    }
     559
     560    /**
     561     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#isApplicableToPrimitive()}.
     562     */
     563    @Test
     564    public void testIsApplicableToPrimitive() {
     565        TagCollection c = new TagCollection();
     566        assertTrue(c.isApplicableToPrimitive());
     567        TagCollection d = new TagCollection(Arrays.asList(tagA, tagA, tagC, tagEmpty));
     568        assertFalse(d.isApplicableToPrimitive());
     569        TagCollection e = new TagCollection(Arrays.asList(tagA, tagC));
     570        assertTrue(e.isApplicableToPrimitive());
     571    }
     572
     573    /**
     574     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#applyTo(org.openstreetmap.josm.data.osm.Tagged)}.
     575     */
     576    @Test
     577    public void testApplyToTagged() {
     578        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC));
     579        NodeData tagged = new NodeData();
     580        tagged.put("k", "x");
     581        tagged.put("k3", "x");
     582        c.applyTo(tagged);
     583        assertEquals("v", tagged.get("k"));
     584        assertEquals("b", tagged.get("k2"));
     585        assertEquals("x", tagged.get("k3"));
     586        TagCollection d = new TagCollection(Arrays.asList(tagEmpty));
     587        d.applyTo(tagged);
     588        assertEquals(null, tagged.get("k"));
     589    }
     590
     591    /**
     592     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#applyTo(java.util.Collection)}.
     593     */
     594    @Test
     595    public void testApplyToCollectionOfQextendsTagged() {
     596        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC));
     597        NodeData tagged = new NodeData();
     598        NodeData tagged2 = new NodeData();
     599        tagged2.put("k", "x");
     600        tagged2.put("k3", "x");
     601        c.applyTo(Arrays.asList(tagged, tagged2));
     602        assertEquals("v", tagged.get("k"));
     603        assertEquals("b", tagged.get("k2"));
     604        assertEquals("v", tagged2.get("k"));
     605        assertEquals("b", tagged2.get("k2"));
     606        assertEquals("x", tagged2.get("k3"));
     607    }
     608
     609    /**
     610     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#replaceTagsOf(org.openstreetmap.josm.data.osm.Tagged)}.
     611     */
     612    @Test
     613    public void testReplaceTagsOfTagged() {
     614        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC));
     615        NodeData tagged = new NodeData();
     616        tagged.put("k", "x");
     617        tagged.put("k3", "x");
     618        c.replaceTagsOf(tagged);
     619        assertEquals("v", tagged.get("k"));
     620        assertEquals("b", tagged.get("k2"));
     621        assertEquals(null, tagged.get("k3"));
     622    }
     623
     624    /**
     625     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#replaceTagsOf(java.util.Collection)}.
     626     */
     627    @Test
     628    public void testReplaceTagsOfCollectionOfQextendsTagged() {
     629        TagCollection c = new TagCollection(Arrays.asList(tagA, tagC));
     630        NodeData tagged = new NodeData();
     631        NodeData tagged2 = new NodeData();
     632        tagged2.put("k", "x");
     633        tagged2.put("k3", "x");
     634        c.replaceTagsOf(Arrays.asList(tagged, tagged2));
     635        assertEquals("v", tagged.get("k"));
     636        assertEquals("b", tagged.get("k2"));
     637        assertEquals("v", tagged2.get("k"));
     638        assertEquals("b", tagged2.get("k2"));
     639        assertEquals(null, tagged2.get("k3"));
     640    }
     641
     642    /**
     643     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#intersect(org.openstreetmap.josm.data.osm.TagCollection)}.
     644     */
     645    @Test
     646    public void testIntersect() {
     647        TagCollection c1 = new TagCollection(Arrays.asList(tagA, tagC, tagD, tagEmpty));
     648        TagCollection c2 = new TagCollection(Arrays.asList(tagA, tagB, tagD));
     649        TagCollection c = c1.intersect(c2);
     650        assertEquals(2, c.getKeys().size());
     651        assertEquals(1, c.getTagOccurence(tagA));
     652        assertEquals(1, c.getTagOccurence(tagD));
     653    }
     654
     655    /**
     656     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#minus(org.openstreetmap.josm.data.osm.TagCollection)}.
     657     */
     658    @Test
     659    public void testMinus() {
     660        TagCollection c1 = new TagCollection(Arrays.asList(tagA, tagC, tagD, tagEmpty));
     661        TagCollection c2 = new TagCollection(Arrays.asList(tagA, tagB, tagD));
     662        TagCollection c = c1.minus(c2);
     663        assertEquals(2, c.getKeys().size());
     664        assertEquals(1, c.getTagOccurence(tagC));
     665        assertEquals(1, c.getTagOccurence(tagEmpty));
     666    }
     667
     668    /**
     669     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#union(org.openstreetmap.josm.data.osm.TagCollection)}.
     670     */
     671    @Test
     672    public void testUnion() {
     673        TagCollection c1 = new TagCollection(Arrays.asList(tagA, tagC, tagD, tagEmpty));
     674        TagCollection c2 = new TagCollection(Arrays.asList(tagA, tagB, tagD));
     675        TagCollection c = c1.union(c2);
     676        assertEquals(2, c.getTagOccurence(tagA));
     677        assertEquals(1, c.getTagOccurence(tagB));
     678        assertEquals(1, c.getTagOccurence(tagC));
     679        assertEquals(2, c.getTagOccurence(tagD));
     680        assertEquals(1, c.getTagOccurence(tagEmpty));
     681    }
     682
     683    /**
     684     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#emptyTagsForKeysMissingIn(org.openstreetmap.josm.data.osm.TagCollection)}.
     685     */
     686    @Test
     687    public void testEmptyTagsForKeysMissingIn() {
     688        TagCollection c1 = new TagCollection(Arrays.asList(tagA, tagC, tagD, tagEmpty));
     689        TagCollection c2 = new TagCollection(Arrays.asList(tagA, tagB, tagD));
     690        TagCollection c = c1.emptyTagsForKeysMissingIn(c2);
     691        assertEquals(2, c.getKeys().size());
     692        assertEquals(1, c.getTagOccurence(new Tag(tagC.getKey(), "")));
     693        assertEquals(1, c.getTagOccurence(tagEmpty));
     694    }
     695
     696    /**
     697     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getJoinedValues(java.lang.String)}.
     698     */
     699    @Test
     700    public void testGetJoinedValues() {
     701        TagCollection c = new TagCollection(Arrays.asList(new Tag("k", "a")));
     702        assertEquals("a", c.getJoinedValues("k"));
     703        TagCollection d = new TagCollection(Arrays.asList(new Tag("k", "a"), new Tag("k", "b")));
     704        assertEquals("a;b", d.getJoinedValues("k"));
     705        TagCollection e = new TagCollection(Arrays.asList(new Tag("k", "b"), new Tag("k", "a"), new Tag("k", "b;a")));
     706        assertEquals("b;a", e.getJoinedValues("k"));
     707        TagCollection f = new TagCollection(Arrays.asList(new Tag("k", "b"), new Tag("k", "a"), new Tag("k", "b"), new Tag("k", "c"), new Tag("k", "d"), new Tag("k", "a;b;c;d")));
     708        assertEquals("a;b;c;d", f.getJoinedValues("k"));
     709        TagCollection g = new TagCollection(Arrays.asList(new Tag("k", "b"), new Tag("k", "a"), new Tag("k", "b"), new Tag("k", "c"), new Tag("k", "d")));
     710        assertEquals("a;b;c;d", Stream.of(g.getJoinedValues("k").split(";")).sorted().collect(Collectors.joining(";")));
     711    }
     712
     713    /**
     714     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#getSummedValues(java.lang.String)}.
     715     */
     716    @Test
     717    public void testGetSummedValues() {
     718        TagCollection c = new TagCollection(Arrays.asList(new Tag("k", "10"), new Tag("k", "20")));
     719        assertEquals("30", c.getSummedValues("k"));
     720        TagCollection d = new TagCollection(Arrays.asList(new Tag("k", "10"), new Tag("k", "10")));
     721        assertEquals("10", d.getSummedValues("k"));
     722        TagCollection e = new TagCollection(Arrays.asList(new Tag("k", "10"), new Tag("k", "x")));
     723        assertEquals("10", e.getSummedValues("k"));
     724        TagCollection f = new TagCollection();
     725        assertEquals("0", f.getSummedValues("k"));
     726    }
     727
     728    /**
     729     * Test method for {@link org.openstreetmap.josm.data.osm.TagCollection#toString()}.
     730     */
     731    @Test
     732    @Ignore("TODO")
     733    public void testToString() {
     734        fail("Not yet implemented");
     735    }
     736}