All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.vergne.collection.impl.AbstractMultiMap Maven / Gradle / Ivy

There is a newer version: 1.11
Show newest version
package fr.vergne.collection.impl;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import fr.vergne.collection.MultiMap;

/**
 * An {@link AbstractMultiMap} is a {@link MultiMap} which implements most of
 * the features. It is basically a {@link HashMap}, so a given key appears only
 * once. However, the type of collection used for values is not provided, which
 * leads to a method to implement in the classes which extend this
 * {@link AbstractMultiMap}.
 * 
 * @author Matthieu Vergne 
 * 
 * @param 
 * @param 
 */
@SuppressWarnings("serial")
public abstract class AbstractMultiMap extends
		HashMap> implements MultiMap {

	public AbstractMultiMap(MultiMap map) {
		for (Entry> entry : map.entrySet()) {
			populate(entry.getKey(), entry.getValue());
		}
	}

	public AbstractMultiMap() {
	}

	@Override
	public final boolean populate(Key key, Value... values) {
		return populate(key, Arrays.asList(values));
	}

	@Override
	public final boolean populate(Key key, Collection values) {
		Collection set = getContainerFor(key);
		return set.addAll(values);
	}

	@Override
	public final boolean depopulate(Key key, Value... values) {
		return depopulate(key, Arrays.asList(values));
	}

	@Override
	public final boolean depopulate(Key key, Collection values) {
		Collection set = getContainerFor(key);
		boolean changed = set.removeAll(values);
		if (set.isEmpty()) {
			remove(key);
		} else {
			// still have values, keep the key
		}
		return changed;
	}

	private Collection getContainerFor(Key key) {
		if (!containsKey(key)) {
			put(key, generateInnerCollection(key));
		} else {
			// use the already present collection
		}
		return get(key);
	}

	protected abstract Collection generateInnerCollection(Key key);

	@Override
	public boolean containsCouple(Key key, Value value) {
		return containsKey(key) && get(key).contains(value);
	}

	@Override
	public Iterator> iterator() {
		return new Iterator>() {

			private Iterator keysIterator = keySet().iterator();
			private Iterator valuesIterator;
			private Key key;
			private Value value;

			@Override
			public boolean hasNext() {
				return keysIterator.hasNext() || valuesIterator != null && valuesIterator.hasNext();
			}

			@Override
			public Entry next() {
				while (valuesIterator == null || !valuesIterator.hasNext()) {
					key = keysIterator.next();
					valuesIterator = AbstractMultiMap.this.get(key).iterator();
				}
				value = valuesIterator.next();
				return new SimpleImmutableEntry(key, value);
			}

			@SuppressWarnings("unchecked")
			@Override
			public void remove() {
				AbstractMultiMap.this.depopulate(key, value);
			}

		};
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy