/* * Copyright 2005, 2007, 2014 (C) Tom Parker <thpr@sourceforge.net> * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with * this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA */ package pcgen.cdom.util; import java.util.Collection; import java.util.List; import java.util.Set; import pcgen.base.util.HashMapToList; import pcgen.base.util.Indirect; import pcgen.base.util.ObjectContainer; import pcgen.cdom.enumeration.FactSetKey; /** * This encapsulates a MapToList in a typesafe and value-semantic way. * * Specifically, when Generics are properly used by a class using a * FactSetKeyMapToList, this class ensures that any FactSetKey will only return * a List of the same Generic type as the FactSetKey. Note this relationship is * only enforced with Generics, and could be violated if Generics are not * properly used. * * This Class also is reference-semantic with respect to the Map and the List. * In other words, the modification of any Collection returned by a * FactSetKeyMapToList will not impact the internal contents of the * FactSetKeyMapToList. Also, any Collection used as a parameter to a method is * not stored directly, the Collection can be modified after the method has * returned without impacting the internal contents of the FactSetKeyMapToList. * * **NOTE** This class is NOT thread safe. */ public class FactSetKeyMapToList { /* * This must remain generic, as far as I know. The challenge here is that * this really wants to be HashMapToList<FactSetKey<T>, T>, but the T needs * to change for each individual FactSetKey/List contained within the * HashMapToList. I don't believe it is possible with Generics in Java. * Thus, this entire class is filled with Generic warnings. * * The advantage of having this class is two-fold: 1) It is value-semantic * with respect to the Map and the List [but not the contents of the Lists]) * 2) It hides all of the generic warnings in once place where they can be * easily analysed as innocent. -- Tom Parker 1/15/07 */ /** * The internal storage of this FactSetKeyMapToList */ @SuppressWarnings("rawtypes") private final HashMapToList map = new HashMapToList(); /** * Adds all of the Lists in the given FactSetKeyMapToList to this * FactSetKeyMapToList. The resulting lists are independent (protecting the * internal structure of FactSetKeyMapToList), however, since * FactSetKeyMapToList is reference-semantic, the List keys and values in * each list are identical. * * This method is reference-semantic and this FactSetKeyMapToList will * maintain a strong reference to all key objects and objects in each list * of the given FactSetKeyMapToList. * * @param lcs * The FactSetKeyMapToList from which all of the Lists should be * imported * @throws NullPointerException * if the specified FactSetKeyMapToList is null. */ @SuppressWarnings("unchecked") public void addAllLists(FactSetKeyMapToList lcs) { map.addAllLists(lcs.map); } /** * Adds all of the Objects in the given list to the (internal) List for the * given FactSetKey. The null value cannot be used as a key in a * FactSetKeyMapToList. This method will automatically initialize the list * for the given key if there is not already a List for that key. * * This method is reference-semantic and this FactSetKeyMapToList will * maintain a strong reference to both the key object and the object in the * given list. * * @param key * The FactSetKey indicating which List the objects in the given * List should be added to. * @param values * A List containing the items to be added to the List for the * given key. */ @SuppressWarnings("unchecked") public <T> void addAllToListFor(FactSetKey<T> key, Collection<ObjectContainer<T>> values) { map.addAllToListFor(key, values); } /** * Adds the given value to the List for the given FactSetKey. The null value * cannot be used as a key in a FactSetKeyMapToList. This method will * automatically initialize the list for the given key if there is not * already a List for that key. * * This method is reference-semantic and this FactSetKeyMapToList will * maintain a strong reference to both the key object and the value object * given as arguments to this method. * * @param key * The FactSetKey indicating which List the given object should * be added to. * @param valueElement * The value to be added to the List for the given key. */ @SuppressWarnings("unchecked") public <T> void addToListFor(FactSetKey<T> key, Indirect<T> valueElement) { map.addToListFor(key, valueElement); } /** * Returns true if this FactSetKeyMapToList contains a List for the given * FactSetKey. This method returns false if the given key is not in this * FactSetKeyMapToList. * * This method is value-semantic in that no changes are made to the object * passed into the method. * * @param key * The FactSetKey being tested. * @return true if this FactSetKeyMapToList contains a List for the given * key; false otherwise. */ @SuppressWarnings("unchecked") public boolean containsListFor(FactSetKey<?> key) { return map.containsListFor(key); } /** * Returns a copy of the List contained in this FactSetKeyMapToList for the * given FactSetKey. This method returns null if the given key is not in * this FactSetKeyMapToList. * * This method is value-semantic in that no changes are made to the object * passed into the method and ownership of the returned List is transferred * to the class calling this method. * * @param key * The FactSetKey for which a copy of the list should be * returned. * @return a copy of the List contained in this FactSetKeyMapToList for the * given key; null if the given key is not a key in this * FactSetKeyMapToList. */ @SuppressWarnings("unchecked") public <T> List<Indirect<T>> getListFor(FactSetKey<T> key) { return map.getListFor(key); } /** * Initializes a List for the given FactSetKey. The null value cannot be * used as a key in a FactSetKeyMapToList. * * This method is reference-semantic and this FactSetKeyMapToList will * maintain a strong reference to the key object given as an argument to * this method. * * @param key * The FactSetKey for which a List should be initialized in this * FactSetKeyMapToList. */ @SuppressWarnings("unchecked") public <T> void initializeListFor(FactSetKey<T> key) { map.initializeListFor(key); } /** * Removes the given value from the list for the given FactSetKey. Returns * true if the value was successfully removed from the list for the given * FactSetKey. Returns false if there is not a list for the given FactSetKey * or if the list for the given FactSetKey did not contain the given value * object. * * @param key * The FactSetKey indicating which List the given object should * be removed from * @param valueElement * The value to be removed from the List for the given key * @return true if the value was successfully removed from the list for the * given key; false otherwise */ @SuppressWarnings("unchecked") public <T> boolean removeFromListFor(FactSetKey<T> key, Indirect<T> valueElement) { return map.removeFromListFor(key, valueElement); } /** * Removes the List for the given FactSetKey. Note there is no requirement * that the list for the given key be empty before this method is called. * * Ownership of the returned List is transferred to the object calling this * method. * * @param key * The FactSetKey indicating which List the given object should * be removed from * @return The List which this FactSetKeyMapToList previous mapped the given * key */ @SuppressWarnings("unchecked") public <T> List<ObjectContainer<T>> removeListFor(FactSetKey<T> key) { return map.removeListFor(key); } /** * Returns the number of objects in the List for the given FactSetKey. This * method will throw a NullPointerException if this FactSetKeyMapToList does * not contain a List for the given key. * * This method is value-semantic in that no changes are made to the object * passed into the method. * * @param key * The key being tested. * @return the number of objects in the List for the given key */ @SuppressWarnings("unchecked") public int sizeOfListFor(FactSetKey<?> key) { return map.sizeOfListFor(key); } /** * Returns true if this FactSetKeyMapToList contains a List for the given * FactSetKey and that list contains the given value. Note, this method * returns false if the given FactSetKey is not in this FactSetKeyMapToList. * * This method is value-semantic in that no changes are made to the objects * passed into the method. * * @param key * The key for the List being tested. * @param valueElement * The value to find in the List for the given key. * @return true if this FactSetKeyMapToList contains a List for the given * key AND that list contains the given value; false otherwise. */ @SuppressWarnings("unchecked") public <T> boolean containsInList(FactSetKey<T> key, ObjectContainer<T> valueElement) { return map.containsInList(key, valueElement); } /** * Returns true if this FactSetKeyMapToList contains a List for the given * key and that list contains one or more of the values in the given * collection. Note, this method returns false if the given key is not in * this FactSetKeyMapToList. * * This method is value-semantic in that no changes are made to the objects * passed into the method. * * @param key * The key for the List being tested. * @param values * The collection of values to find in the List for the given * key. * @return true if this FactSetKeyMapToList contains a List for the given * key AND that list contains one or more of the given values; false * otherwise. */ @SuppressWarnings("unchecked") public <T> boolean containsAnyInList(FactSetKey<T> key, Collection<ObjectContainer<T>> values) { return map.containsAnyInList(key, values); } /** * Returns a Set indicating the Keys of this FactSetKeyMapToList. Ownership * of the Set is transferred to the calling Object, no association is kept * between the Set and this FactSetKeyMapToList. (Thus, removal of a key * from the returned Set will not remove that key from this * FactSetKeyMapToList) * * NOTE: This method returns all of the keys this FactSetKeyMapToList * contains. It DOES NOT determine whether the Lists defined for the keys * are empty. Therefore, it is possible that this FactSetKeyMapToList * contains one or more keys, and all of the lists associated with those * keys are empty, yet this method will return a non-zero length Set. * * @return a Set containing the keys in this FactSetKeyMapToList */ @SuppressWarnings("unchecked") public Set<FactSetKey<?>> getKeySet() { return map.getKeySet(); } /** * Returns true if this structure contains no Lists. * * @return true if this structure contains no Lists; false otherwise */ public boolean isEmpty() { return map.isEmpty(); } /** * Returns the consistent-with-equals hashCode for this FactSetKeyMapToList * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return map.hashCode(); } /** * Returns true if this FactSetKeyMapToList is equal to the given Object. * * Note that equality as defined by this method is both a class of * FactSetKeyMapToList and equality of contents of the FactSetKeyMapToList. * * @see java.lang.Object#equals(Object) */ @Override public boolean equals(Object obj) { return obj instanceof FactSetKeyMapToList && map.equals(((FactSetKeyMapToList) obj).map); } }