/*
* Copyright (c) 2007 Tom Parker <thpr@users.sourceforge.net>
*
* This program 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 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 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package pcgen.cdom.reference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import pcgen.cdom.base.CDOMReference;
import pcgen.cdom.base.Constants;
import pcgen.cdom.base.PrereqObject;
import pcgen.cdom.enumeration.GroupingState;
/**
* A CDOMCompoundOrReference is a CDOMReference which is intended to contain one
* or more CDOMReferences that this object "joins" in an "or" format. In other
* words, if any one of the underlying CDOMReference objects contains an object,
* then this CDOMCompoundOrReference will contain the object.
*
* @param <T>
* The Class of the underlying objects contained by this
* CDOMCompoundOrReference
*/
public class CDOMCompoundOrReference<T extends PrereqObject> extends
CDOMGroupRef<T>
{
/**
* The list of underlying references that this CDOMCompoundOrReference
* contains
*/
private final ArrayList<CDOMReference<T>> references = new ArrayList<>();
/**
* Creates a new CDOMCompoundOrReference with the given name which will
* contain CDOMReferences that contain objects of the given Class.
*
* @param objClass
* The Class of the underlying object contained by this
* CDOMCompoundOrReference.
* @param refName
* An identifier of the objects this CDOMCompoundOrReference
* contains.
*/
public CDOMCompoundOrReference(Class<T> objClass, String refName)
{
super(objClass, refName);
}
/**
* Adds a new CDOMReference to this CDOMCompoundOrReference.
*
* @param ref
* The CDOMReference to add to this CDOMCompoundOrReference
* @throws IllegalArgumentException
* if the given CDOMReference for addition to this
* CDOMCompoundOrReference does not represent the same
* CDOMObject class as this CDOMCompoundOrReference
* @throws NullPointerException
* if the given CDOMReference is null
*/
public void addReference(CDOMReference<T> ref)
{
/*
* Extra protection in case generics fail
*/
if (!getReferenceClass().equals(ref.getReferenceClass()))
{
throw new IllegalArgumentException("Cannot add reference of "
+ ref.getReferenceClass()
+ " to CDOMCompoundOrReference of " + getReferenceClass());
}
references.add(ref);
}
/**
* Returns true if the given Object is included in the Collection of Objects
* to which this CDOMCompoundOrReference refers.
*
* Note that the behavior of this class is undefined if CDOMReferences have
* not been added to this CDOMCompoundOrReference or if any of the
* underlying CDOMReference objects have not been resolved.
*
* @param item
* The object to be tested to see if it is referred to by this
* CDOMCompoundOrReference.
* @return true if the given Object is included in the Collection of Objects
* to which this CDOMCompoundOrReference refers; false otherwise.
*/
@Override
public boolean contains(T item)
{
for (CDOMReference<T> ref : references)
{
if (ref.contains(item))
{
return true;
}
}
return false;
}
/**
* For purposes of memory optimization, allows the underlying collection of
* CDOMReferences to be compacted to the exact size of the number of
* CDOMReference objects that this CDOMCompoundOrReference contains.
*/
public void trimToSize()
{
references.trimToSize();
}
/**
* Returns a representation of this CDOMCompoundOrReference, suitable for
* storing in an LST file.
*
* Note that this will call the getLSTformat() method of the underlying
* CDOMReference objects. Therefore, the contents of the String returned by
* this method is partially governed by the response of the individual
* CDOMReference objects contained by this CDOMCompoundOrReference.
*
* Note that this will ALWAYS return a comma-delimited list of objects if
* more than one reference is present in the CDOMCompoundOrReference.
*
* @return A representation of this CDOMCompoundOrReference, suitable for
* storing in an LST file.
*/
@Override
public String getLSTformat(boolean useAny)
{
return ReferenceUtilities.joinLstFormat(references, Constants.COMMA);
}
/**
* Throws an exception. This method may not be called because a
* CDOMCompoundOrReference refers to objects indirectly through references.
*
* To add items to this CDOMCompoundOrReference, see
* addReference(CDOMReference)
*
* @param item
* ignored
* @throws IllegalStateException
* because a CDOMCompoundOrReference does not get directly
* resolved.
*/
@Override
public void addResolution(T item)
{
throw new IllegalStateException(
"CompoundReference cannot be given a resolution");
}
/**
* Returns the count of the number of objects included in the Collection of
* Objects to which this CDOMCompoundOrReference refers.
*
* Note that the behavior of this class is undefined if CDOMReferences have
* not been added to this CDOMCompoundOrReference or if any of the
* underlying CDOMReference objects have not been resolved.
*
* @return the count of the number of objects included in the Collection of
* Objects to which this CDOMCompoundOrReference refers.
*/
@Override
public int getObjectCount()
{
int count = 0;
for (CDOMReference<T> ref : references)
{
count += ref.getObjectCount();
}
return count;
}
/**
* Returns a Collection containing the Objects to which this
* CDOMCompoundOrReference refers.
*
* Note that the behavior of this class is undefined if CDOMReferences have
* not been added to this CDOMCompoundOrReference or if any of the
* underlying CDOMReference objects have not been resolved.
*
* This method is reference-semantic, meaning that ownership of the
* Collection returned by this method is transferred to the calling object.
* Modification of the returned Collection should not result in modifying
* the CDOMCompoundOrReference, and modifying the CDOMCompoundOrReference
* after the Collection is returned should not modify the Collection.
*
* @return A Collection containing the Objects to which this
* CDOMCompoundOrReference refers.
*/
@Override
public Collection<T> getContainedObjects()
{
Set<T> set = new HashSet<>();
for (CDOMReference<T> ref : references)
{
set.addAll(ref.getContainedObjects());
}
return set;
}
/**
* Returns the GroupingState for this CDOMCompoundOrReference. The
* GroupingState indicates how this CDOMCompoundOrReference can be combined
* with other PrimitiveChoiceFilters.
*
* @return The GroupingState for this CDOMCompoundOrReference.
*/
@Override
public GroupingState getGroupingState()
{
GroupingState state = GroupingState.EMPTY;
for (CDOMReference<T> ref : references)
{
state = state.add(ref.getGroupingState());
}
return state.compound(GroupingState.ALLOWS_UNION);
}
@Override
public String getChoice()
{
return null;
}
}