/*
* Copyright 2010 (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.reference;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import pcgen.base.util.ObjectContainer;
import pcgen.cdom.base.PrimitiveCollection;
import pcgen.cdom.enumeration.GroupingState;
import pcgen.cdom.primitive.PrimitiveUtilities;
public class FilteredReference<T> extends CDOMGroupRef<T>
{
private final Set<CDOMSingleRef<? super T>> filterSet = new HashSet<>();
private final ObjectContainer<T> baseSet;
public FilteredReference(Class<T> objClass, ObjectContainer<T> allRef)
{
super(objClass, "Filtered Reference");
if (objClass == null)
{
throw new IllegalArgumentException(
"Class for FilteredReference cannot be null");
}
if (allRef == null)
{
throw new IllegalArgumentException(
"Base Set for FilteredReference cannot be null");
}
baseSet = allRef;
}
public void addProhibitedItem(CDOMSingleRef<? super T> prohibitedRef)
{
if (prohibitedRef == null)
{
throw new IllegalArgumentException(
"CDOMSingleRef to be added cannot be null");
}
Class<?> refClass = prohibitedRef.getReferenceClass();
if (!baseSet.getReferenceClass().isAssignableFrom(refClass))
{
throw new IllegalArgumentException("CDOMSingleRef to be added "
+ refClass + " is a different class type than "
+ baseSet.getReferenceClass().getSimpleName());
}
filterSet.add(prohibitedRef);
}
public Class<? super T> getChoiceClass()
{
return baseSet.getReferenceClass();
}
@Override
public int hashCode()
{
return baseSet.hashCode() + filterSet.size();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof FilteredReference)
{
FilteredReference<?> other = (FilteredReference<?>) obj;
return baseSet.equals(other.baseSet)
&& filterSet.equals(other.filterSet);
}
return false;
}
@Override
public GroupingState getGroupingState()
{
GroupingState state = GroupingState.EMPTY;
for (PrimitiveCollection<? super T> pcf : filterSet)
{
state = pcf.getGroupingState().add(state);
}
return (filterSet.size() == 1) ? state : state
.compound(GroupingState.ALLOWS_UNION);
}
@Override
public boolean contains(T item)
{
return getContainedObjects().contains(item);
}
@Override
public void addResolution(T item)
{
throw new IllegalStateException(
"CompoundReference cannot be given a resolution");
}
@Override
public Collection<T> getContainedObjects()
{
Set<T> choices = new HashSet<>();
choices.addAll(baseSet.getContainedObjects());
RETAIN: for (Iterator<T> it = choices.iterator(); it.hasNext();)
{
T choice = it.next();
for (CDOMSingleRef<? super T> prohibitedRef : filterSet)
{
if (prohibitedRef.contains(choice))
{
it.remove();
continue RETAIN;
}
}
}
return choices;
}
@Override
public String getLSTformat(boolean useAny)
{
Set<PrimitiveCollection<? super T>> sortSet = new TreeSet<>(
PrimitiveUtilities.COLLECTION_SORTER);
sortSet.addAll(filterSet);
return "ALL|!" + PrimitiveUtilities.joinLstFormat(sortSet, "|!", useAny);
}
@Override
public int getObjectCount()
{
return baseSet.getContainedObjects().size() - filterSet.size();
}
@Override
public String getChoice()
{
return null;
}
}