/* * Copyright (c) 2008 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.helper; import java.util.ArrayList; import java.util.Collection; import java.util.List; import pcgen.cdom.base.ConcretePrereqObject; import pcgen.cdom.base.Constants; import pcgen.cdom.base.QualifyingObject; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.facet.FacetLibrary; import pcgen.cdom.facet.analysis.ChangeProfFacet; import pcgen.cdom.reference.CDOMGroupRef; import pcgen.cdom.reference.CDOMSingleRef; import pcgen.cdom.reference.ReferenceUtilities; import pcgen.core.WeaponProf; /** * A WeaponProfProvider is an object that contains the ability to contain * WeaponProficiencies, either by TYPE or direct WeaponProf references. Explicit * Storage of TYPE vs. primitive is necessary due to the ability of the * CHANGEPROF token to change types for a WeaponProf. * * This is typically used for an AUTO:WEAPONPROF token to store the granted * proficiencies. */ public class WeaponProfProvider extends ConcretePrereqObject implements QualifyingObject { private static ChangeProfFacet changeProfFacet = FacetLibrary .getFacet(ChangeProfFacet.class); /** * Contains the list of primitive WeaponProf objects that this * WeaponProfProvider contains */ private List<CDOMSingleRef<WeaponProf>> direct; /** * Contains the list of TYPEs of WeaponProf objects that this * WeaponProfProvider contains */ private List<CDOMGroupRef<WeaponProf>> type; /** * Contains the All WeaponProf reference if this WeaponProfProvider contains * it */ private CDOMGroupRef<WeaponProf> all; /** * Adds a primitive WeaponProf reference to this WeaponProfProvider. * * @param ref * The primitive WeaponProf reference that should be added to * this WeaponProfProvider */ public void addWeaponProf(CDOMSingleRef<WeaponProf> ref) { if (direct == null) { direct = new ArrayList<>(); } direct.add(ref); } /** * Adds a WeaponProf TYPE reference to this WeaponProfProvider. * * @param ref * The WeaponProf TYPE reference that should be added to this * WeaponProfProvider */ public void addWeaponProfType(CDOMGroupRef<WeaponProf> ref) { if (type == null) { type = new ArrayList<>(); } type.add(ref); } /** * Adds a All WeaponProf reference to this WeaponProfProvider. * * @param ref * The WeaponProf ALL reference that should be added to this * WeaponProfProvider */ public void addWeaponProfAll(CDOMGroupRef<WeaponProf> ref) { all = ref; } /** * Returns a collection of the WeaponProf objects that this * WeaponProfProvider contains relative to a given PlayerCharacter. The * PlayerCharacter must be known in order to resolve changes that may be * introduced by any proficiency changes (CHANGEPROF). * * Ownership of the Collection is transferred to the calling Object, no * association is kept between the Collection and this WeaponProfProvider. * (Thus, removal of a WeaponProf from the returned Collection will not * remove that WeaponProf from this WeaponProfProvider) * * @param id * The PlayerCharacter used to resolve the references in order to * account for any proficiency changes * @return A Collection of the WeaponProf objects that this * WeaponProfProvider contains relative to the given PlayerCharacter */ public Collection<WeaponProf> getContainedProficiencies(CharID id) { List<WeaponProf> list = new ArrayList<>(); if (all == null) { if (direct != null) { for (CDOMSingleRef<WeaponProf> ref : direct) { list.add(ref.get()); } } if (type != null) { for (CDOMGroupRef<WeaponProf> ref : type) { list.addAll(getWeaponProfsInTarget(id, ref)); } } } else { list.addAll(all.getContainedObjects()); } return list; } /** * Returns the LST format for this WeaponProfProvider. Provided primarily to * allow the Token/Loader system to properly unparse the WeaponProfProvider. * * @return The LST format of this WeaponProfProvider */ public String getLstFormat() { if (all != null) { return Constants.LST_ALL; } StringBuilder sb = new StringBuilder(); boolean typeEmpty = type == null || type.isEmpty(); if (direct != null && !direct.isEmpty()) { sb.append(ReferenceUtilities.joinLstFormat(direct, Constants.PIPE)); if (!typeEmpty) { sb.append(Constants.PIPE); } } if (!typeEmpty) { sb.append(ReferenceUtilities.joinLstFormat(type, Constants.PIPE)); } return sb.toString(); } /** * Returns true if the given object is a WeaponProfProvider with identical * underlying WeaponProfs and WeaponProf TYPEs and Prerequisites. * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof WeaponProfProvider) { WeaponProfProvider other = (WeaponProfProvider) obj; if (direct == null) { if (other.direct != null) { return false; } } else { if (!direct.equals(other.direct)) { return false; } } if (type == null) { if (other.type != null) { return false; } } else { if (!type.equals(other.type)) { return false; } } if (all == null) { if (other.all != null) { return false; } } else { if (!all.equals(other.all)) { return false; } } return this.equalsPrereqObject(other); } return false; } /** * Returns a consistent-with-equals hashCode for this WeaponProfProvider * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (direct == null ? 0 : direct.hashCode() * 29) + (type == null ? 0 : type.hashCode()); } /** * Returns true if this WeaponProfProvider is empty, meaning it contains no * direct references and no TYPE references. * * @return true if this WeaponProfProvider is empty; false otherwise */ public boolean isEmpty() { return all == null && (direct == null || direct.isEmpty()) && (type == null || type.isEmpty()); } public boolean isValid() { boolean hasDirect = (direct != null) && !direct.isEmpty(); boolean hasType = (type != null) && !type.isEmpty(); boolean hasIndividual = hasDirect || hasType; boolean hasAll = all != null; return hasAll ^ hasIndividual; } public List<WeaponProf> getWeaponProfsInTarget(CharID id, CDOMGroupRef<WeaponProf> master) { return changeProfFacet.getWeaponProfsInTarget(id, master); } }