/*
* Copyright (c) 2010 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.primitive;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import pcgen.cdom.base.Constants;
import pcgen.cdom.base.Converter;
import pcgen.cdom.base.PrimitiveCollection;
import pcgen.cdom.enumeration.GroupingState;
import pcgen.core.PlayerCharacter;
import pcgen.util.Logging;
public class CompoundAndPrimitive<T> implements PrimitiveCollection<T>
{
private final Class<? super T> refClass;
private final Set<PrimitiveCollection<T>> primCollection = new TreeSet<>(
PrimitiveUtilities.COLLECTION_SORTER);
public CompoundAndPrimitive(Collection<PrimitiveCollection<T>> pcfCollection)
{
if (pcfCollection == null)
{
throw new IllegalArgumentException(
"Collection for CompoundAndPrimitive cannot be null");
}
if (pcfCollection.isEmpty())
{
throw new IllegalArgumentException(
"Collection for CompoundAndPrimitive cannot be empty");
}
Class<? super T> pcfClass = null;
primCollection.addAll(pcfCollection);
if (primCollection.size() != pcfCollection.size())
{
if (Logging.isLoggable(Level.WARNING))
{
Logging.log(Level.WARNING, "Found duplicate item in "
+ pcfCollection);
}
primCollection.add(PrimitiveCollection.FIXED.invalid());
}
for (PrimitiveCollection<T> pcf : primCollection)
{
Class<? super T> thisPCFClass = pcf.getReferenceClass();
if (pcfClass == null)
{
pcfClass = thisPCFClass;
}
else if (!pcfClass.isAssignableFrom(thisPCFClass))
{
if (thisPCFClass.isAssignableFrom(pcfClass))
{
pcfClass = thisPCFClass;
}
else
{
throw new IllegalArgumentException(
"List contains incompatible types: "
+ pcfClass.getSimpleName() + " and "
+ thisPCFClass.getSimpleName());
}
}
}
refClass = pcfClass;
}
@Override
public <R> Collection<? extends R> getCollection(PlayerCharacter pc, Converter<T, R> c)
{
Collection<? extends R> returnSet = null;
for (PrimitiveCollection<T> cs : primCollection)
{
if (returnSet == null)
{
returnSet = cs.getCollection(pc, c);
}
else
{
returnSet.retainAll(cs.getCollection(pc, c));
}
}
return returnSet;
}
@Override
public Class<? super T> getReferenceClass()
{
return refClass;
}
/**
* Returns the GroupingState for this CompoundAndPrimitive. The
* GroupingState indicates how this CompoundAndPrimitive can be combined
* with other PrimitiveChoiceSets.
*
* @return The GroupingState for this CompoundAndPrimitive.
*/
@Override
public GroupingState getGroupingState()
{
GroupingState state = GroupingState.EMPTY;
for (PrimitiveCollection<T> pcs : primCollection)
{
state = pcs.getGroupingState().add(state);
}
return state.compound(GroupingState.ALLOWS_INTERSECTION);
}
/**
* Returns a representation of this CompoundAndPrimitive, suitable for
* storing in an LST file.
*
* @return A representation of this CompoundAndPrimitive, suitable for
* storing in an LST file.
*/
@Override
public String getLSTformat(boolean useAny)
{
return PrimitiveUtilities.joinLstFormat(primCollection,
Constants.COMMA, useAny);
}
/**
* Returns the consistent-with-equals hashCode for this CompoundAndPrimitive
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
return primCollection.hashCode();
}
/**
* Returns true if this CompoundAndPrimitive is equal to the given Object.
* Equality is defined as being another CompoundAndPrimitive object with
* equal underlying contents.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
return (obj instanceof CompoundAndPrimitive)
&& ((CompoundAndPrimitive<?>) obj).primCollection
.equals(primCollection);
}
}