/*
 * Copyright (K) 2012 Fabian Hirschmann <fabian@hirschm.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package com.github.fhirschmann.clozegen.lib.multiset;

import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.*;

/**
 * Object which maps a key to a {@link Multiset}. Additionally, it provides
 * the convenience function like
 * {@link MapMultiset#add(java.lang.Object, java.lang.Object, int)}.
 *
 * @author Fabian Hirschmann <fabian@hirschm.net>
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of values for {@link MultiSet}
 */
public class MapMultiset<K, V> extends ForwardingMap<K, Multiset<V>> {
    private Map<K, Multiset<V>> map;

    /**
     * Creates a new empty {@link MapMultiset}.
     *
     * @param <K> the type of keys maintained by this map
     * @param <V> the type of values for {@link MultiSet}
     * @return a new empty {@link MapMultiset}
     */
    public static <K, V> MapMultiset<K, V> create() {
        return new MapMultiset();
    }

    /**
     * Creates a new empty {@link MapMultiset}.
     */
    public MapMultiset() {
        super();
        map = Maps.newHashMap();
    }

    /**
     * Returns a copy of the {@link Multiset} identified by {@code key} as an
     * {@link ImmutableMultiset} whose order is highest count first, with ties broken by
     * the iteration order of the original multiset.
     *
     * @param key the key to identify the multiset by
     * @return a new {@link ImmutableMultiset} whose order is highest count first
     */
    public ImmutableMultiset<V> getSorted(final K key) {
        return Multisets.copyHighestCountFirst(checkNotNull(get(key)));
    }

    /**
     * Adds a value to the {@link Multiset} identified by {@code key}.
     *
     * <p>If the multiset does not exist yet, it will be created.
     *
     * @param key the key to identify the multiset by
     * @param value the value of the multiset to add
     * @param count the number to add
     */
    public void add(final K key, final V value, final int count) {
        Multiset<V> multiset;

        if (containsKey(key)) {
            multiset = get(key);
        } else {
            multiset = HashMultiset.create();
            map.put(key, multiset);
        }
        multiset.add(value, count);
    }

    /**
     * Returns to total number of entries in all {@link Multiset} objects
     * combined.
     *
     * @return total number of entries
     */
    public long total() {
        long total = 0;
        for (Entry<K, Multiset<V>> entry : this.entrySet()) {
            total += entry.getValue().size();
        }
        return total;
    }

    @Override
    protected Map<K, Multiset<V>> delegate() {
        return map;
    }
}

@@ -2800,28 +2800,527 @@
     
-Multiset%3CV%3E multiset
+get(key).add(checkNotNull(value), count);%0A    %7D%0A%0A    /**%0A     * Gets the %7B@link Multiset%7D identified by %7B@code key%7D.%0A     *%0A     * %3Cp%3EIf there is no multiset present which can be identified by a given key,%0A     * a new empty one is created and returned.%0A     *%0A     * @param key the key to identify the multiset by%0A     * @return the %7Blink Multiset%7D identified by key or a new empty one%0A     */%0A    @Override%0A    public Multiset%3CV%3E get(Object key) %7B%0A        Multiset%3CV%3E multiset;%0A%0A        K kKey = (K) checkNotNull(key)
 ;%0A%0A 
@@ -3343,16 +3343,17 @@
 insKey(k
+K
 ey)) %7B%0A 
@@ -3374,16 +3374,22 @@
 tiset = 
+super.
 get(key)
@@ -3469,16 +3469,16 @@
     
-map.
 put(
+(K) 
 key,
@@ -3507,24 +3507,31 @@
         
+return 
 multiset
 .add(val
@@ -3526,26 +3526,8 @@
 iset
-.add(value, count)
 ;%0A  

create a new multiset in get() instead of add()