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

net.sf.javagimmicks.collections8.mapping.ValueMappings Maven / Gradle / Ivy

There is a newer version: 0.99-alpha1
Show newest version
package net.sf.javagimmicks.collections8.mapping;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.sf.javagimmicks.collections8.mapping.ValueMappings.Mapping;
import net.sf.javagimmicks.collections8.transformer.TransformerUtils;

/**
 * Represents a n:m relation between two sets of elements where each mapping can
 * carry an additional value (in contradiction to {@link Mappings}) providing a
 * backed {@link Map} view of each "side" of the relation as well as many
 * analytic and modification operations.
 * 

* Example: Assume you have a set of persons - e.g. Alice, * Bob and Charles as well as a set of hobbies - e.g. * Astrology, Biking and Chess and you want to model any * associations between persons and hobbies where each association should tell * how much the person likes the hobby (e.g. Little or Much), this * class is just the right thing for you: *

* The code below shows how to create an appropriate instance and fill it with * some mappings: * *

 * final ValueMappings<Person, Hobby, Likes> m = DualMapValueMappings.<Person, Hobby, Likes> createTreeTreeInstance();
 * 
 * // Alice has hobbies Biking and Chess
 * m.put(Person.Alice, Hobby.Biking, Likes.Little);
 * m.put(Person.Alice, Hobby.Chess, Likes.Much);
 * 
 * // Bob has hobbies Astrology and Chess
 * m.put(Person.Bob, Hobby.Astrology, Likes.Much);
 * m.put(Person.Bob, Hobby.Chess, Likes.Little);
 * 
 * // Charles has hobbies Astrology and Biking
 * m.put(Person.Charles, Hobby.Astrology, Likes.Little);
 * m.put(Person.Charles, Hobby.Biking, Likes.Much);
 * 
* * Now you can get a "left view" (showing the hobbies for each person and how * much the person likes the hobby) and a "right view" (showing the persons for * each hobby and how much the person likes the hobby) from the {@link Mappings} * object: * *
 * {@code
 * System.out.println(m.getLeftView());
 * // Prints {Alice={Biking=Little, Chess=Much}, Bob={Astrology=Much, Chess=Little}, Charles={Astrology=Little, Biking=Much}}
 * 
 * System.out.println(m.getRightView());
 * // Prints {Astrology={Bob=Much, Charles=Little}, Biking={Alice=Little, Charles=Much}, Chess={Alice=Much, Bob=Little}}
 * }
 * 
*

* For more things that you can do with {@link ValueMappings}, please consult * the method descriptions. *

* If you don't want to assign a value for each mapping but simply want to * associate left and right elements without additional information, * {@link Mappings} is the right choice for you. * * @see Mappings * @param * the type of left keys of the {@link ValueMappings} * @param * the type of right keys of the {@link ValueMappings} * @param * the type of values associated with the mappings */ public interface ValueMappings extends Iterable> { /** * Adds a new or replaces an existing mapping (or association) between a * given left key and right key with the given value. * * @param left * the left key of the new mapping * @param right * the right key of the new mapping * @param value * the value to associate with the new or existing mapping * @return the previous value associated with the mapping or {@code null} of * the mapping is new */ E put(L left, R right, E value); /** * Bulk-adds a bunch of left key-value associations for a single given right * key. * * @param right * the right key to add a bunch of left key-value associations for * @param map * a {@link Map} containing the left keys to add for the given * right key as well as the values to associate with the respective * new mappings */ default void putAllForRightKey(final R right, final Map map) { map.entrySet().forEach(leftEntry -> put(leftEntry.getKey(), right, leftEntry.getValue())); } /** * Bulk-adds a bunch of right key-value associations for a single given left * key. * * @param left * the left key to add a bunch of right key-value associations for * @param map * a {@link Map} containing the right keys to add for the given * left key as well as the values to associate with the respective * new mappings */ default void putAllForLeftKey(final L left, final Map map) { map.entrySet().forEach(rightEntry -> put(left, rightEntry.getKey(), rightEntry.getValue())); } /** * Removes a given mapping specified by left and right key from this * instance. * * @param left * the left key of the mapping to remove * @param right * the right key of the mapping to remove * @return the value that was associated with the removed mapping or * {@code null} if no such mapping was contained */ default E remove(final L left, final R right) { final Map mappedValuesLeft = getAllForLeftKey(left); return mappedValuesLeft != null ? mappedValuesLeft.remove(right) : null; } /** * Completely removes a given right key together with all it's mappings from * this instance. * * @param right * the right key to remove * @return the {@link Map} containing the left keys that were mapped to the * given right key as well as the associated values */ default Map removeRightKey(final R right) { return getRightView().remove(right); } /** * Completely removes a given left key together with all it's mappings from * this instance. * * @param left * the left key to remove * @return the {@link Map} containing the right keys that were mapped to with * the given left key as well as the associated values */ default Map removeLeftKey(final L left) { return getLeftView().remove(left); } /** * Removes all mappings from this instance */ default void clear() { getLeftView().clear(); } /** * Checks if a given mapping specified by left and right key is contained in * the current instance. * * @param left * the left key of the mapping to remove * @param right * the right key of the mapping to remove * @return if the specified mapping is contained in the current instance */ default boolean containsMapping(final L left, final R right) { final Map rightInnerMap = getAllForLeftKey(left); return rightInnerMap != null && rightInnerMap.containsKey(right); } /** * Check if any mappings are contained in this instance for a given left key. * * @param left * the left key to check for any existing mappings * @return if there is at least one mapping contained for the given left key */ default boolean containsLeftKey(final L left) { return getLeftView().containsKey(left); } /** * Check if any mappings are contained in this instance for a given right * key. * * @param right * the right key to check for any existing mappings * @return if there is at least one mapping contained for the given right key */ default boolean containsRightKey(final R right) { return getRightView().containsKey(right); } /** * Returns the number of mappings contained within the current instance. * * @return the number of mappings contained within the current instance */ default int size() { return getMappingSet().size(); } /** * Checks if the current instance contains no mappings. * * @return if the current instance contains no mappings */ boolean isEmpty(); /** * Retrieve the value associated with the mapping specified by left and right * key. * * @param left * the left key of the mapping whose value should be retrieved * @param right * the right key of the mapping whose value should be retrieved * @return the associated value or {@code null} if no such mapping was * contained */ default E get(final L left, final R right) { final Map rightInnerMap = getAllForLeftKey(left); return rightInnerMap != null ? rightInnerMap.get(right) : null; } /** * Returns all mappings contained within this instance as a {@link Set} of * {@link Mapping} instances. * * @return all mappings contained within this instance */ Set> getMappingSet(); /** * Returns a {@link Collection} of the values of all mappings contained * within this instance. * * @return a {@link Collection} of the values of all mappings */ default Collection getValues() { return TransformerUtils.decorate(getMappingSet(), Mapping::getValue); } /** * Return the "left view" of this instance - that is a {@link Map} that * contains on the key side the left mapping keys and on the value side * another {@link Map} which has on the key side the right mapping keys and * on the value side the associated values. *

* Have a look at the example with the {@link ValueMappings class * documentation} to get a better understanding. * * @return the left view of this instance as {@link Map} */ Map> getLeftView(); /** * Return the "right view" of this instance - that is a {@link Map} that * contains on the key side the right mapping keys and on the value side * another {@link Map} which has on the key side the left mapping keys and on * the value side the associated values. *

* Have a look at the example with the {@link ValueMappings class * documentation} to get a better understanding. * * @return the right view of this instance as {@link Map} */ Map> getRightView(); /** * Returns a {@link Map} of all left keys that are mapped to a given right * key and the associated values. * * @param right * the right key to get all mapped left keys for * @return the {@link Map} of left keys mapped to the given right key */ default Map getAllForRightKey(final R right) { return getRightView().get(right); } /** * Returns a {@link Map} of all right keys that are mapped to a given left * key and the associated values. * * @param left * the left key to get all mapped right keys for * @return the {@link Map} of right keys mapped to the given left key */ default Map getAllForLeftKey(final L left) { return getLeftView().get(left); } /** * Returns an inverted view of this instance (left and right keys are * exchanged). * * @return an inverted view of this instance */ ValueMappings invert(); /** * Returns an {@link Iterator} of all contained {@link Mapping}s. * * @see #getMappingSet() */ @Override default Iterator> iterator() { return getMappingSet().iterator(); } /** * Represents a single left-to-right mapping contained within a * {@link ValueMappings} object. * * @param * the type of left keys of the {@link Mapping} * @param * the type of right keys of the {@link Mapping} * @param * the type of values associated with the mappings */ interface Mapping { /** * Returns the left key of the mapping. * * @return the left key of the mapping */ L getLeftKey(); /** * Returns the right key of the mapping. * * @return the right key of the mapping */ R getRightKey(); /** * Returns the value associated with the mapping. * * @return the value associated with the mapping */ E getValue(); /** * Returns an inverted view of this instance (with exchanged left and * right key). * * @return an inverted view of this instance */ default Mapping invert() { return new Mapping() { @Override public Mapping invert() { return Mapping.this; } @Override public R getLeftKey() { return Mapping.this.getRightKey(); } @Override public L getRightKey() { return Mapping.this.getLeftKey(); } @Override public E getValue() { return Mapping.this.getValue(); } }; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy