/*
* Copyright 2005, 2007 (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
*
* Created on June 18, 2005.
*
* Current Ver: $Revision$
*/
package pcgen.cdom.util;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import pcgen.base.util.HashMapToList;
import pcgen.cdom.enumeration.ListKey;
/**
* @author Tom Parker <thpr@sourceforge.net>
*
* This encapsulates a MapToList in a typesafe and value-semantic way.
*
* Specifically, when Generics are properly used by a class using a
* ListKeyMapToList, this class ensures that any ListKey will only return a List
* of the same Generic type as the ListKey. 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
* ListKeyMapToList will not impact the internal contents of the
* ListKeyMapToList. 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 ListKeyMapToList.
*
* **NOTE** This class is NOT thread safe.
*/
public class ListKeyMapToList
{
/*
* This must remain generic, as far as I know. The challenge here is that
* this really wants to be HashMapToList<ListKey<T>, T>, but the T needs
* to change for each individual ListKey/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 ListKeyMapToList
*/
@SuppressWarnings("rawtypes")
private final HashMapToList map = new HashMapToList();
/**
* Adds all of the Lists in the given ListKeyMapToList to this
* ListKeyMapToList. The resulting lists are independent (protecting the
* internal structure of ListKeyMapToList), however, since ListKeyMapToList
* is reference-semantic, the List keys and values in each list are
* identical.
*
* This method is reference-semantic and this ListKeyMapToList will maintain
* a strong reference to all key objects and objects in each list of the
* given ListKeyMapToList.
*
* @param lcs
* The ListKeyMapToList from which all of the Lists should be
* imported
* @throws NullPointerException
* if the specified ListKeyMapToList is null.
*/
@SuppressWarnings("unchecked")
public void addAllLists(ListKeyMapToList lcs)
{
map.addAllLists(lcs.map);
}
/**
* Adds all of the Objects in the given list to the (internal) List for the
* given ListKey. The null value cannot be used as a key in a
* ListKeyMapToList. 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 ListKeyMapToList will maintain
* a strong reference to both the key object and the object in the given
* list.
*
* @param key
* The ListKey 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(ListKey<T> key, Collection<T> values)
{
map.addAllToListFor(key, values);
}
/**
* Adds the given value to the List for the given ListKey. The null value
* cannot be used as a key in a ListKeyMapToList. 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 ListKeyMapToList will maintain
* a strong reference to both the key object and the value object given as
* arguments to this method.
*
* @param key
* The ListKey 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(ListKey<T> key, T valueElement)
{
map.addToListFor(key, valueElement);
}
/**
* Returns true if this ListKeyMapToList contains a List for the given
* ListKey. This method returns false if the given key is not in this
* ListKeyMapToList.
*
* This method is value-semantic in that no changes are made to the object
* passed into the method.
*
* @param key
* The ListKey being tested.
* @return true if this ListKeyMapToList contains a List for the given key;
* false otherwise.
*/
@SuppressWarnings("unchecked")
public boolean containsListFor(ListKey<?> key)
{
return map.containsListFor(key);
}
/**
* Returns a copy of the List contained in this ListKeyMapToList for the
* given ListKey. This method returns null if the given key is not in this
* ListKeyMapToList.
*
* 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 ListKey for which a copy of the list should be returned.
* @return a copy of the List contained in this ListKeyMapToList for the
* given key; null if the given key is not a key in this
* ListKeyMapToList.
*/
@SuppressWarnings("unchecked")
public <T> List<T> getListFor(ListKey<T> key)
{
return map.getListFor(key);
}
/**
* Returns the Object at the given position within the List for the given
* ListKey. If a List for the given ListKey is not present in this
* ListKeyMapToList, null will be returned.
*
* @param key
* The ListKey indicating which List the given object should be
* returned from
* @param index
* The location of the Object to be returned within the List
* defined by the given key.
* @return The Object at the given position within the list for the given
* key.
*/
@SuppressWarnings("unchecked")
public <T> T getElementInList(ListKey<T> key, int index)
{
return (T) map.getElementInList(key, index);
}
/**
* Initializes a List for the given ListKey. The null value cannot be used
* as a key in a ListKeyMapToList.
*
* This method is reference-semantic and this ListKeyMapToList will maintain
* a strong reference to the key object given as an argument to this method.
*
* @param key
* The ListKey for which a List should be initialized in this
* ListKeyMapToList.
*/
@SuppressWarnings("unchecked")
public <T> void initializeListFor(ListKey<T> key)
{
map.initializeListFor(key);
}
/**
* Removes the given value from the list for the given ListKey. Returns true
* if the value was successfully removed from the list for the given
* ListKey. Returns false if there is not a list for the given ListKey or if
* the list for the given ListKey did not contain the given value object.
*
* @param key
* The ListKey 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(ListKey<T> key, T valueElement)
{
return map.removeFromListFor(key, valueElement);
}
/**
* Removes the List for the given ListKey. 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 ListKey indicating which List the given object should be
* removed from
* @return The List which this ListKeyMapToList previous mapped the given
* key
*/
@SuppressWarnings("unchecked")
public <T> List<T> removeListFor(ListKey<T> key)
{
return map.removeListFor(key);
}
/**
* Returns the number of objects in the List for the given ListKey. This
* method will throw a NullPointerException if this ListKeyMapToList 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(ListKey<?> key)
{
return map.sizeOfListFor(key);
}
/**
* Returns true if this ListKeyMapToList contains a List for the given
* ListKey and that list contains the given value. Note, this method returns
* false if the given ListKey is not in this ListKeyMapToList.
*
* 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 ListKeyMapToList contains a List for the given key
* AND that list contains the given value; false otherwise.
*/
@SuppressWarnings("unchecked")
public <T> boolean containsInList(ListKey<T> key, T valueElement)
{
return map.containsInList(key, valueElement);
}
/**
* Returns true if this ListKeyMapToList 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
* ListKeyMapToList.
*
* 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 ListKeyMapToList 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(ListKey<T> key, Collection<T> values)
{
return map.containsAnyInList(key, values);
}
/**
* Returns a Set indicating the Keys of this ListKeyMapToList. Ownership of
* the Set is transferred to the calling Object, no association is kept
* between the Set and this ListKeyMapToList. (Thus, removal of a key from
* the returned Set will not remove that key from this ListKeyMapToList)
*
* NOTE: This method returns all of the keys this ListKeyMapToList contains.
* It DOES NOT determine whether the Lists defined for the keys are empty.
* Therefore, it is possible that this ListKeyMapToList 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 ListKeyMapToList
*/
@SuppressWarnings("unchecked")
public Set<ListKey<?>> 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 ListKeyMapToList
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
return map.hashCode();
}
/**
* Returns true if this ListKeyMapToList is equal to the given Object.
*
* Note that equality as defined by this method is both a class of
* ListKeyMapToList and equality of contents of the ListKeyMapToList.
*
* @see java.lang.Object#equals(Object)
*/
@Override
public boolean equals(Object obj)
{
return obj instanceof ListKeyMapToList
&& map.equals(((ListKeyMapToList) obj).map);
}
@Override
public String toString()
{
return map.toString();
}
}