/*
* PrereqObject.java
* Copyright 2006 Aaron Divinsky <boomer70@yahoo.com>
*
* 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
*
* Current Version: $Revision: 5686 $
*
*/
package pcgen.cdom.base;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import pcgen.base.util.ListSet;
import pcgen.core.PlayerCharacter;
import pcgen.core.prereq.PrereqHandler;
import pcgen.core.prereq.Prerequisite;
import pcgen.core.prereq.PrerequisiteUtilities;
/**
* A ConcretePrereqObject is an object that contains a list of Prerequisites.
* This list of Prerequisites is designed to serve as a list of conditions that
* must be met before the PrereqObject can be "used"
*
* ConcretePrereqObject is intended to provide a quick foundation class that
* implements PrereqObject.
*/
public class ConcretePrereqObject implements Cloneable, PrereqObject
{
/** The list of prerequisites */
private Set<Prerequisite> thePrereqs = null;
/**
* Returns a List of the Prerequisite objects contained in the PrereqObject.
* If the PrereqObject contains no Prerequisites, the return value may be
* null or an empty list, it is implementation-specific.
*
* This method is value-semantic in that ownership of the returned List is
* transferred to the class calling this method. Modification of the
* returned List will not modify this ConcretePrereqObject and modification
* of this ConcretePrereqObject will not modify the returned List.
*
* @return A List of Prerequisite objects contained in the PrereqObject.
*/
@Override
public List<Prerequisite> getPrerequisiteList()
{
if (thePrereqs == null)
{
return Collections.emptyList();
}
/*
* TODO This is an ugly facade, but required for easy compatibility with
* 5.14 - to be changed once 5.14 code is gone and this can be changed
* to return Collection or Set (or perhaps ListSet?)
*/
return Collections.unmodifiableList(new ArrayList<>(
thePrereqs));
}
/**
* Returns true if this object has any prerequisites of the kind that is
* passed in.
*
* @param matchType
* The kind of Prerequisite to test for.
*
* @return <tt>true</tt> if this object has a prerequisite of the kind
* that is passed in
*
* @see pcgen.core.prereq.Prerequisite#getKind()
*/
public final boolean hasPreReqTypeOf(final String matchType)
{
if (!hasPrerequisites())
{
return false;
}
for (Prerequisite prereq : getPrerequisiteList())
{
if (PrerequisiteUtilities.hasPreReqKindOf(prereq, matchType))
{
return true;
}
}
return false;
}
/**
* Clones this ConcretePrereqObject. This is not a "deep" clone, in that the
* List of Prerequisites is cloned (to allow Prerequisites to be
* added/removed without altering the original or the clone), but the
* Prerequisites contained within the ConcretePrereqObject are not cloned.
*
* @see java.lang.Object#clone()
*/
@Override
public ConcretePrereqObject clone() throws CloneNotSupportedException
{
final ConcretePrereqObject obj = (ConcretePrereqObject) super.clone();
if (thePrereqs != null)
{
obj.thePrereqs = new ListSet<>();
obj.thePrereqs.addAll(thePrereqs);
}
return obj;
}
/**
* Adds a Collection of Prerequisite objects to the ConcretePrereqObject.
*
* This method is both reference-semantic and value-semantic. This
* ConcretePrereqObject will not maintain a reference to or modify the given
* Collection. However, this ConcretePrereqObject will maintain a strong
* reference to the Prerequisite objects in the given Collection.
*
* @param prereqs
* A Collection of Prerequisite objects to added to the
* ConcretePrereqObject.
*/
@Override
public void addAllPrerequisites(final Collection<Prerequisite> prereqs)
{
if (prereqs == null || prereqs.isEmpty())
{
return;
}
if (thePrereqs == null)
{
thePrereqs = new ListSet<>(prereqs.size());
}
for (final Prerequisite pre : prereqs)
{
addPrerequisite(pre);
}
}
/**
* Add a Prerequisite to the ConcretePrereqObject.
*
* If the Prerequisite kind is CLEAR all the prerequisites will be cleared
* from the list.
*
* @param preReq
* The Prerequisite to add to the ConcretePrereqObject.
*/
@Override
public void addPrerequisite(Prerequisite preReq)
{
if (preReq == null)
{
return;
}
if (thePrereqs == null)
{
thePrereqs = new ListSet<>();
}
thePrereqs.add(preReq);
}
/**
* Remove All Prerequisites contained in the ConcretePrereqObject.
*/
@Override
public void clearPrerequisiteList()
{
thePrereqs = null;
}
/**
* Returns the number of Prerequisites contained in the
* ConcretePrereqObject.
*
* @return the number of Prerequisites contained in the
* ConcretePrereqObject.
*/
@Override
public int getPrerequisiteCount()
{
if (thePrereqs == null)
{
return 0;
}
return thePrereqs.size();
}
/**
* Returns true if this ConcretePrereqObject contains any Prerequisites;
* false otherwise.
*
* @return true if this ConcretePrereqObject contains any Prerequisites;
* false otherwise.
*/
@Override
public boolean hasPrerequisites()
{
return thePrereqs != null;
}
/**
* Returns true if the given PrereqObject contains Prerequisites that are
* equal to the Prerequisites contained within this ConcretePrereqObject. If
* the number of Prerequisites does not match, or if the Prerequisites are
* not equal, this will return false.
*
* @param other
* The PrereqObject for which the Prerequisites will be compared
* to the Prerequisites in this ConcretePrereqObject.
* @return true if the given PrereqObject contains Prerequisites that are
* equal to the Prerequisites contained within this
* ConcretePrereqObject; false otherwise
*/
public boolean equalsPrereqObject(PrereqObject other)
{
if (this == other)
{
return true;
}
boolean otherHas = other.hasPrerequisites();
if (!hasPrerequisites())
{
return !otherHas;
}
if (!otherHas)
{
return false;
}
List<Prerequisite> otherPRL = other.getPrerequisiteList();
if (otherPRL.size() != thePrereqs.size())
{
return false;
}
List<Prerequisite> removed = new ArrayList<>(
thePrereqs);
removed.removeAll(otherPRL);
return removed.isEmpty();
}
/**
* Tests if the specified PlayerCharacter passes all the prerequisites.
*
* @param aPC
* The <tt>PlayerCharacter</tt> to test.
*
* @return <tt>true</tt> if the PC passes all the prerequisites.
*/
public boolean qualifies(final PlayerCharacter aPC, Object owner)
{
return !hasPrerequisites()
|| PrereqHandler.passesAll(getPrerequisiteList(), aPC, owner);
}
}