From: <th...@us...> - 2010-12-17 18:51:23
|
Revision: 14165 http://pcgen.svn.sourceforge.net/pcgen/?rev=14165&view=rev Author: thpr Date: 2010-12-17 18:51:13 +0000 (Fri, 17 Dec 2010) Log Message: ----------- Fix: ObjectAdditionFacet receives added Abilty prior to CHOOSE selection being made Issue#: CODE-421 Modified Paths: -------------- Trunk/pcgen/code/src/itest/plugin/lsttokens/editcontext/AbilityIntegrationTest.java Trunk/pcgen/code/src/java/pcgen/cdom/base/Constants.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractListFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractQualifiedListFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalAbilityFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalTemplateFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/EquipSetFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/FacetInitialization.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/GrantedAbilityFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/RacialSubTypesFacet.java Trunk/pcgen/code/src/java/pcgen/core/AbilityUtilities.java Trunk/pcgen/code/src/java/pcgen/core/PlayerCharacter.java Trunk/pcgen/code/src/java/pcgen/gui/KitSelector.java Trunk/pcgen/code/src/java/plugin/lsttokens/AbilityLst.java Trunk/pcgen/code/src/java/plugin/lsttokens/TemplateLst.java Trunk/pcgen/code/src/java/plugin/lsttokens/VFeatLst.java Trunk/pcgen/code/src/java/plugin/lsttokens/auto/FeatToken.java Trunk/pcgen/code/src/java/plugin/lsttokens/domain/FeatToken.java Trunk/pcgen/code/src/java/plugin/lsttokens/race/FavclassToken.java Trunk/pcgen/code/src/java/plugin/lsttokens/race/FeatToken.java Trunk/pcgen/code/src/java/plugin/lsttokens/template/FavoredclassToken.java Trunk/pcgen/code/src/utest/pcgen/cdom/testsupport/AbstractListFacetTest.java Trunk/pcgen/code/src/utest/plugin/lsttokens/AbilityLstTest.java Trunk/pcgen/code/src/utest/plugin/lsttokens/VFeatLstTest.java Trunk/pcgen/code/src/utest/plugin/lsttokens/auto/FeatTokenTest.java Trunk/pcgen/code/src/utest/plugin/lsttokens/domain/FeatTokenTest.java Trunk/pcgen/code/src/utest/plugin/lsttokens/race/FeatTokenTest.java Trunk/pcgen/code/src/utest/resultactor/auto/FeatTokenTest.java Trunk/pcgen/code/src/utest/resultactor/testsupport/AbstractResultActorTest.java Added Paths: ----------- Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionallyGrantedAbilityFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/facet/DirectAbilityFacet.java Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilitySelector.java Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilityTargetSelector.java Trunk/pcgen/code/src/java/pcgen/cdom/helper/CategorizedAbilitySelection.java Removed Paths: ------------- Trunk/pcgen/code/src/java/pcgen/cdom/facet/DeniedAbilityFacet.java Modified: Trunk/pcgen/code/src/itest/plugin/lsttokens/editcontext/AbilityIntegrationTest.java =================================================================== --- Trunk/pcgen/code/src/itest/plugin/lsttokens/editcontext/AbilityIntegrationTest.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/itest/plugin/lsttokens/editcontext/AbilityIntegrationTest.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -69,8 +69,8 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|NORMAL|Abil1"); - commit(modCampaign, tc, "Feat|VIRTUAL|TYPE=TestType"); + commit(testCampaign, tc, "FEAT|NORMAL|Abil1"); + commit(modCampaign, tc, "FEAT|VIRTUAL|TYPE=TestType"); completeRoundRobin(tc); } @@ -88,8 +88,8 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|Abil1|Abil2"); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2"); + commit(testCampaign, tc, "FEAT|VIRTUAL|Abil1|Abil2"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2"); completeRoundRobin(tc); } @@ -107,8 +107,8 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2|Abil1"); - commit(modCampaign, tc, "Feat|AUTOMATIC|.CLEAR.Abil1|Abil2"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2|Abil1"); + commit(modCampaign, tc, "FEAT|AUTOMATIC|.CLEAR.Abil1|Abil2"); completeRoundRobin(tc); } @@ -127,7 +127,7 @@ secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); emptyCommit(testCampaign, tc); - commit(modCampaign, tc, "Feat|VIRTUAL|Abil1|Abil2"); + commit(modCampaign, tc, "FEAT|VIRTUAL|Abil1|Abil2"); completeRoundRobin(tc); } @@ -145,7 +145,7 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|Abil1|Abil2"); + commit(testCampaign, tc, "FEAT|VIRTUAL|Abil1|Abil2"); emptyCommit(modCampaign, tc); completeRoundRobin(tc); } @@ -161,7 +161,7 @@ secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); emptyCommit(testCampaign, tc); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2"); completeRoundRobin(tc); } @@ -176,7 +176,7 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2"); emptyCommit(modCampaign, tc); completeRoundRobin(tc); } @@ -190,8 +190,8 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR"); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2"); completeRoundRobin(tc); } @@ -205,8 +205,8 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR.Abil2"); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR.Abil2"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR"); completeRoundRobin(tc); } @@ -216,7 +216,7 @@ verifyCleanStart(); TestContext tc = new TestContext(); emptyCommit(testCampaign, tc); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR"); completeRoundRobin(tc); } @@ -225,7 +225,7 @@ { verifyCleanStart(); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR"); emptyCommit(modCampaign, tc); completeRoundRobin(tc); } @@ -244,9 +244,9 @@ ab = secondaryContext.ref.constructCDOMObject(Ability.class, "Abil2"); secondaryContext.ref.reassociateCategory(AbilityCategory.FEAT, ab); TestContext tc = new TestContext(); - commit(testCampaign, tc, "Feat|VIRTUAL|.CLEAR", - "Feat|VIRTUAL|Abil1|Abil2"); - commit(modCampaign, tc, "Feat|VIRTUAL|.CLEAR"); + commit(testCampaign, tc, "FEAT|VIRTUAL|.CLEAR", + "FEAT|VIRTUAL|Abil1|Abil2"); + commit(modCampaign, tc, "FEAT|VIRTUAL|.CLEAR"); completeRoundRobin(tc); } } Modified: Trunk/pcgen/code/src/java/pcgen/cdom/base/Constants.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/base/Constants.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/base/Constants.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -297,7 +297,7 @@ String DOT = "."; String LST_LIST = "LIST"; String LST_PATTERN = "%"; - String LST_PRECENTLIST = "%LIST"; + String LST_PERCENTLIST = "%LIST"; String COLON = ":"; String LST_NONE = "NONE"; String LST_DOT_CLEARALL = ".CLEARALL"; Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractListFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractListFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractListFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; -import java.util.Set; import pcgen.cdom.enumeration.CharID; @@ -79,7 +78,7 @@ */ public void addAll(CharID id, Collection<T> c) { - Set<T> set = getConstructingCachedSet(id); + Collection<T> set = getConstructingCachedSet(id); for (T obj : c) { if (obj == null) @@ -112,7 +111,7 @@ { throw new IllegalArgumentException("Object to add may not be null"); } - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); if (componentSet != null) { if (componentSet.remove(obj)) @@ -140,7 +139,7 @@ */ public void removeAll(CharID id, Collection<T> c) { - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); if (componentSet != null) { for (T obj : c) @@ -170,9 +169,9 @@ * in this AbstractListFacet for the Player Character represented by * the given CharID */ - public Set<T> removeAll(CharID id) + public Collection<T> removeAll(CharID id) { - Set<T> componentSet = (Set<T>) FacetCache.remove(id, thisClass); + Collection<T> componentSet = (Collection<T>) FacetCache.remove(id, thisClass); if (componentSet == null) { return Collections.emptySet(); @@ -194,14 +193,14 @@ * @return A non-null Set of objects in this AbstractListFacet for the * Player Character represented by the given CharID */ - public Set<T> getSet(CharID id) + public Collection<T> getSet(CharID id) { - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); if (componentSet == null) { return Collections.emptySet(); } - return Collections.unmodifiableSet(componentSet); + return Collections.unmodifiableCollection(componentSet); } /** @@ -216,7 +215,7 @@ */ public int getCount(CharID id) { - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); if (componentSet == null) { return 0; @@ -237,7 +236,7 @@ */ public boolean isEmpty(CharID id) { - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); return componentSet == null || componentSet.isEmpty(); } @@ -258,7 +257,7 @@ /* * TODO null? - log an error? */ - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); return componentSet != null && componentSet.contains(obj); } @@ -277,9 +276,9 @@ * null if no information has been set in this AbstractListFacet for * the Player Character. */ - protected Set<T> getCachedSet(CharID id) + protected Collection<T> getCachedSet(CharID id) { - return (Set<T>) FacetCache.get(id, thisClass); + return (Collection<T>) FacetCache.get(id, thisClass); } /** @@ -295,14 +294,19 @@ * The CharID for which the Set should be returned * @return The Set for the Player Character represented by the given CharID. */ - private Set<T> getConstructingCachedSet(CharID id) + private Collection<T> getConstructingCachedSet(CharID id) { - Set<T> componentSet = getCachedSet(id); + Collection<T> componentSet = getCachedSet(id); if (componentSet == null) { - componentSet = new LinkedHashSet<T>(); + componentSet = getComponentSet(); FacetCache.set(id, thisClass, componentSet); } return componentSet; } + + protected Collection<T> getComponentSet() + { + return new LinkedHashSet<T>(); + } } Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractQualifiedListFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractQualifiedListFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/AbstractQualifiedListFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -367,12 +367,17 @@ Map<T, Set<Object>> componentMap = getCachedMap(id); if (componentMap == null) { - componentMap = new IdentityHashMap<T, Set<Object>>(); + componentMap = getComponentMap(); FacetCache.set(id, getClass(), componentMap); } return componentMap; } + protected Map<T, Set<Object>> getComponentMap() + { + return new IdentityHashMap<T, Set<Object>>(); + } + /** * Copies the contents of the AbstractQualifiedListFacet from one Player * Character to another Player Character, based on the given CharIDs Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalAbilityFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalAbilityFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalAbilityFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -17,15 +17,13 @@ */ package pcgen.cdom.facet; +import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; import pcgen.cdom.enumeration.CharID; -import pcgen.cdom.helper.ConditionalAbility; +import pcgen.cdom.helper.CategorizedAbilitySelection; /** * @author Thomas Parker (thpr [at] yahoo.com) @@ -34,287 +32,51 @@ * Ability objects that are contained in a PlayerCharacter because the PC did * pass prerequisites */ -public class ConditionalAbilityFacet +public class ConditionalAbilityFacet extends + AbstractListFacet<CategorizedAbilitySelection> { + private PrerequisiteFacet prereqFacet = FacetLibrary + .getFacet(PrerequisiteFacet.class); - private final Class<?> thisClass = getClass(); - - /** - * Add the given object to the list of objects stored in this - * ConditionalAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character for which the - * given item should be added - * @param obj - * The object to be added to the list of objects stored in this - * ConditionalAbilityFacet for the Player Character represented - * by the given CharID - */ - public void add(CharID id, ConditionalAbility obj) + @Override + protected Collection<CategorizedAbilitySelection> getComponentSet() { - if (obj == null) - { - throw new IllegalArgumentException("Object to add may not be null"); - } - getConstructingCachedSet(id).add(obj); + return new ArrayList<CategorizedAbilitySelection>(); } - /** - * Adds all of the objects in the given Collection to the list of objects - * stored in this ConditionalAbilityFacet for the Player Character - * represented by the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * given items should be added - * @param c - * The Collection of objects to be added to the list of objects - * stored in this ConditionalAbilityFacet for the Player - * Character represented by the given CharID - * @throws NullPointerException - * if the given Collection is null - */ - public void addAll(CharID id, Collection<ConditionalAbility> c) + public Collection<CategorizedAbilitySelection> getQualifiedSet(CharID id) { - Set<ConditionalAbility> set = getConstructingCachedSet(id); - for (ConditionalAbility obj : c) + List<CategorizedAbilitySelection> set = new ArrayList<CategorizedAbilitySelection>(); + Collection<CategorizedAbilitySelection> cached = getCachedSet(id); + if (cached != null) { - if (obj == null) + for (CategorizedAbilitySelection cas : cached) { - throw new IllegalArgumentException( - "Object to add may not be null"); - } - set.add(obj); - } - } - - /** - * Removes the given object from the list of objects stored in this - * ConditionalAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character from which the - * given item should be removed - * @param obj - * The object to be removed from the list of objects stored in - * this ConditionalAbilityFacet for the Player Character - * represented by the given CharID - */ - public void remove(CharID id, ConditionalAbility obj) - { - if (obj == null) - { - throw new IllegalArgumentException("Object to add may not be null"); - } - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet != null) - { - componentSet.remove(obj); - } - } - - /** - * Removes all of the objects in the given Collection from the list of - * objects stored in this ConditionalAbilityFacet for the Player Character - * represented by the given CharID - * - * @param id - * The CharID representing the Player Character from which the - * given items should be removed - * @param c - * The Collection of objects to be removed from the list of - * objects stored in this ConditionalAbilityFacet for the Player - * Character represented by the given CharID - * @throws NullPointerException - * if the given Collection is null - */ - public void removeAll(CharID id, Collection<ConditionalAbility> c) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet != null) - { - for (ConditionalAbility obj : c) - { - if (obj == null) + if (prereqFacet.qualifies(id, cas, cas.getSource())) { - throw new IllegalArgumentException( - "Object to add may not be null"); + set.add(cas); } - componentSet.remove(obj); } } + return set; } - /** - * Removes all objects from the list of objects stored in this - * ConditionalAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character from which all - * items should be removed - * @return A non-null Set of objects removed from the list of objects stored - * in this ConditionalAbilityFacet for the Player Character - * represented by the given CharID - */ - public Set<ConditionalAbility> removeAll(CharID id) + public void removeAllFromSource(CharID id, Object source) { - Set<ConditionalAbility> componentSet = (Set<ConditionalAbility>) FacetCache - .remove(id, thisClass); - if (componentSet == null) + Collection<CategorizedAbilitySelection> cached = getCachedSet(id); + if (cached != null) { - return Collections.emptySet(); - } - return componentSet; - } - - /** - * Returns the Set of objects in this ConditionalAbilityFacet for the Player - * Character represented by the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * items in this ConditionalAbilityFacet should be returned. - * @return A non-null Set of objects in this ConditionalAbilityFacet for the - * Player Character represented by the given CharID - */ - public Set<ConditionalAbility> getSet(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - return Collections.emptySet(); - } - return Collections.unmodifiableSet(componentSet); - } - - /** - * Returns the count of items in this ConditionalAbilityFacet for the Player - * Character represented by the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * count of items should be returned - * @return The count of items in this ConditionalAbilityFacet for the Player - * Character represented by the given CharID - */ - public int getCount(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - return 0; - } - return componentSet.size(); - } - - /** - * Returns true if this ConditionalAbilityFacet does not contain any items - * for the Player Character represented by the given CharID - * - * @param id - * The CharId representing the PlayerCharacter to test if any - * items are contained by this ConditionalAbilityFacet - * @return true if this ConditionalAbilityFacet does not contain any items - * for the Player Character represented by the given CharID; false - * otherwise (if it does contain items for the Player Character) - */ - public boolean isEmpty(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - return componentSet == null || componentSet.isEmpty(); - } - - /** - * Returns true if this ConditionalAbilityFacet contains the given value in - * the list of items for the Player Character represented by the given - * CharID. - * - * @param id - * The CharID representing the Player Character used for testing - * @param obj - * The object to test if this ConditionalAbilityFacet contains - * that item for the Player Character represented by the given - * CharID - * @return true if this ConditionalAbilityFacet contains the given value for - * the Player Character represented by the given CharID; false - * otherwise - */ - public boolean contains(CharID id, ConditionalAbility obj) - { - /* - * TODO null? - log an error? - */ - Set<ConditionalAbility> componentSet = getCachedSet(id); - return componentSet != null && componentSet.contains(obj); - } - - /** - * Returns the type-safe Set for this ConditionalAbilityFacet and the given - * CharID. May return null if no information has been set in this - * ConditionalAbilityFacet for the given CharID. - * - * Note that this method SHOULD NOT be public. The Set is owned by - * ConditionalAbilityFacet, and since it can be modified, a reference to - * that object should not be exposed to any object other than - * ConditionalAbilityFacet. - * - * @param id - * The CharID for which the Set should be returned - * @return The Set for the Player Character represented by the given CharID; - * null if no information has been set in this - * ConditionalAbilityFacet for the Player Character. - */ - private Set<ConditionalAbility> getCachedSet(CharID id) - { - return (Set<ConditionalAbility>) FacetCache.get(id, thisClass); - } - - /** - * Returns a type-safe Set for this ConditionalAbilityFacet and the given - * CharID. Will return a new, empty Set if no information has been set in - * this ConditionalAbilityFacet for the given CharID. Will not return null. - * - * Note that this method SHOULD NOT be public. The Set object is owned by - * ConditionalAbilityFacet, and since it can be modified, a reference to - * that object should not be exposed to any object other than - * ConditionalAbilityFacet. - * - * @param id - * The CharID for which the Set should be returned - * @return The Set for the Player Character represented by the given CharID. - */ - private Set<ConditionalAbility> getConstructingCachedSet(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - componentSet = new LinkedHashSet<ConditionalAbility>(); - FacetCache.set(id, thisClass, componentSet); - } - return componentSet; - } - - public Set<ConditionalAbility> removeAll(CharID id, Object source) - { - Set<ConditionalAbility> removed = new HashSet<ConditionalAbility>(); - Set<ConditionalAbility> cachedSet = getCachedSet(id); - if (cachedSet != null) - { - for (Iterator<ConditionalAbility> it = cachedSet.iterator(); it + for (Iterator<CategorizedAbilitySelection> it = cached.iterator(); it .hasNext();) { - ConditionalAbility ca = it.next(); - if (ca.getParent().equals(source)) + CategorizedAbilitySelection cas = it.next(); + if (cas.getSource().equals(source)) { it.remove(); - removed.add(ca); + fireDataFacetChangeEvent(id, cas, + DataFacetChangeEvent.DATA_REMOVED); } } } - return removed; } } \ No newline at end of file Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalTemplateFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalTemplateFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionalTemplateFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -17,10 +17,10 @@ */ package pcgen.cdom.facet; +import java.util.Collection; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.facet.LevelFacet.LevelChangeEvent; @@ -92,7 +92,7 @@ public void levelChanged(LevelChangeEvent lce) { CharID id = lce.getCharID(); - Set<PCTemplate> oldSet = getSet(id); + Collection<PCTemplate> oldSet = getSet(id); int totalLevels = levelFacet.getTotalLevels(id); int totalHitDice = levelFacet.getMonsterLevelCount(id); Map<PCTemplate, PCTemplate> newMap = new IdentityHashMap<PCTemplate, PCTemplate>(); Added: Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionallyGrantedAbilityFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionallyGrantedAbilityFacet.java (rev 0) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/ConditionallyGrantedAbilityFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -0,0 +1,72 @@ +/* + * Copyright (c) Thomas Parker, 2010. + * + * 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.facet; + +import java.util.Collection; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Set; + +import pcgen.base.util.WrappedMapSet; +import pcgen.cdom.enumeration.CharID; +import pcgen.cdom.helper.CategorizedAbilitySelection; + +/** + * @author Thomas Parker (thpr [at] yahoo.com) + * + * An ConditionalAbilityFacet is a DataFacet that contains information about + * Ability objects that are contained in a PlayerCharacter because the PC did + * pass prerequisites + */ +public class ConditionallyGrantedAbilityFacet extends + AbstractListFacet<CategorizedAbilitySelection> +{ + + private final ConditionalAbilityFacet cabFacet = FacetLibrary + .getFacet(ConditionalAbilityFacet.class); + + public void update(CharID id) + { + Collection<CategorizedAbilitySelection> current = getSet(id); + Collection<CategorizedAbilitySelection> qualified = cabFacet + .getQualifiedSet(id); + HashSet<CategorizedAbilitySelection> toRemove = new HashSet<CategorizedAbilitySelection>( + current); + toRemove.removeAll(qualified); + HashSet<CategorizedAbilitySelection> toAdd = new HashSet<CategorizedAbilitySelection>( + qualified); + toAdd.removeAll(current); + for (CategorizedAbilitySelection cas : toRemove) + { + remove(id, cas); + } + for (CategorizedAbilitySelection cas : toAdd) + { + add(id, cas); + } + } + + @Override + protected Set<CategorizedAbilitySelection> getComponentSet() + { + return new WrappedMapSet<CategorizedAbilitySelection>( + IdentityHashMap.class); + } + + +} \ No newline at end of file Deleted: Trunk/pcgen/code/src/java/pcgen/cdom/facet/DeniedAbilityFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/DeniedAbilityFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/DeniedAbilityFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -1,311 +0,0 @@ -/* - * Copyright (c) Thomas Parker, 2010. - * - * 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.facet; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; - -import pcgen.cdom.enumeration.CharID; -import pcgen.cdom.helper.ConditionalAbility; - -/** - * @author Thomas Parker (thpr [at] yahoo.com) - * - * An DeniedAbilityFacet is a DataFacet that contains information about Ability - * objects that are not contained in a PlayerCharacter because the PC did not - * pass prerequisites - */ -public class DeniedAbilityFacet -{ - - private final Class<?> thisClass = getClass(); - - /** - * Add the given object to the list of objects stored in this - * DeniedAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character for which the - * given item should be added - * @param obj - * The object to be added to the list of objects stored in this - * DeniedAbilityFacet for the Player Character represented by the - * given CharID - */ - public void add(CharID id, ConditionalAbility obj) - { - if (obj == null) - { - throw new IllegalArgumentException("Object to add may not be null"); - } - getConstructingCachedSet(id).add(obj); - } - - /** - * Adds all of the objects in the given Collection to the list of objects - * stored in this DeniedAbilityFacet for the Player Character represented by - * the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * given items should be added - * @param c - * The Collection of objects to be added to the list of objects - * stored in this DeniedAbilityFacet for the Player Character - * represented by the given CharID - * @throws NullPointerException - * if the given Collection is null - */ - public void addAll(CharID id, Collection<ConditionalAbility> c) - { - Set<ConditionalAbility> set = getConstructingCachedSet(id); - for (ConditionalAbility obj : c) - { - if (obj == null) - { - throw new IllegalArgumentException( - "Object to add may not be null"); - } - set.add(obj); - } - } - - /** - * Removes the given object from the list of objects stored in this - * DeniedAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character from which the - * given item should be removed - * @param obj - * The object to be removed from the list of objects stored in - * this DeniedAbilityFacet for the Player Character represented - * by the given CharID - */ - public void remove(CharID id, ConditionalAbility obj) - { - if (obj == null) - { - throw new IllegalArgumentException("Object to add may not be null"); - } - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet != null) - { - componentSet.remove(obj); - } - } - - /** - * Removes all of the objects in the given Collection from the list of - * objects stored in this DeniedAbilityFacet for the Player Character - * represented by the given CharID - * - * @param id - * The CharID representing the Player Character from which the - * given items should be removed - * @param c - * The Collection of objects to be removed from the list of - * objects stored in this DeniedAbilityFacet for the Player - * Character represented by the given CharID - * @throws NullPointerException - * if the given Collection is null - */ - public void removeAll(CharID id, Collection<ConditionalAbility> c) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet != null) - { - for (ConditionalAbility obj : c) - { - if (obj == null) - { - throw new IllegalArgumentException( - "Object to add may not be null"); - } - componentSet.remove(obj); - } - } - } - - /** - * Removes all objects from the list of objects stored in this - * DeniedAbilityFacet for the Player Character represented by the given - * CharID - * - * @param id - * The CharID representing the Player Character from which all - * items should be removed - * @return A non-null Set of objects removed from the list of objects stored - * in this DeniedAbilityFacet for the Player Character represented - * by the given CharID - */ - public Set<ConditionalAbility> removeAll(CharID id) - { - Set<ConditionalAbility> componentSet = (Set<ConditionalAbility>) FacetCache - .remove(id, thisClass); - if (componentSet == null) - { - return Collections.emptySet(); - } - return componentSet; - } - - /** - * Returns the Set of objects in this DeniedAbilityFacet for the Player - * Character represented by the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * items in this DeniedAbilityFacet should be returned. - * @return A non-null Set of objects in this DeniedAbilityFacet for the - * Player Character represented by the given CharID - */ - public Set<ConditionalAbility> getSet(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - return Collections.emptySet(); - } - return Collections.unmodifiableSet(componentSet); - } - - /** - * Returns the count of items in this DeniedAbilityFacet for the Player - * Character represented by the given CharID - * - * @param id - * The CharID representing the Player Character for which the - * count of items should be returned - * @return The count of items in this DeniedAbilityFacet for the Player - * Character represented by the given CharID - */ - public int getCount(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - return 0; - } - return componentSet.size(); - } - - /** - * Returns true if this DeniedAbilityFacet does not contain any items for - * the Player Character represented by the given CharID - * - * @param id - * The CharId representing the PlayerCharacter to test if any - * items are contained by this DeniedAbilityFacet - * @return true if this DeniedAbilityFacet does not contain any items for - * the Player Character represented by the given CharID; false - * otherwise (if it does contain items for the Player Character) - */ - public boolean isEmpty(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - return componentSet == null || componentSet.isEmpty(); - } - - /** - * Returns true if this DeniedAbilityFacet contains the given value in the - * list of items for the Player Character represented by the given CharID. - * - * @param id - * The CharID representing the Player Character used for testing - * @param obj - * The object to test if this DeniedAbilityFacet contains that - * item for the Player Character represented by the given CharID - * @return true if this DeniedAbilityFacet contains the given value for the - * Player Character represented by the given CharID; false otherwise - */ - public boolean contains(CharID id, ConditionalAbility obj) - { - /* - * TODO null? - log an error? - */ - Set<ConditionalAbility> componentSet = getCachedSet(id); - return componentSet != null && componentSet.contains(obj); - } - - /** - * Returns the type-safe Set for this DeniedAbilityFacet and the given - * CharID. May return null if no information has been set in this - * DeniedAbilityFacet for the given CharID. - * - * Note that this method SHOULD NOT be public. The Set is owned by - * DeniedAbilityFacet, and since it can be modified, a reference to that - * object should not be exposed to any object other than DeniedAbilityFacet. - * - * @param id - * The CharID for which the Set should be returned - * @return The Set for the Player Character represented by the given CharID; - * null if no information has been set in this DeniedAbilityFacet - * for the Player Character. - */ - private Set<ConditionalAbility> getCachedSet(CharID id) - { - return (Set<ConditionalAbility>) FacetCache.get(id, thisClass); - } - - /** - * Returns a type-safe Set for this DeniedAbilityFacet and the given CharID. - * Will return a new, empty Set if no information has been set in this - * DeniedAbilityFacet for the given CharID. Will not return null. - * - * Note that this method SHOULD NOT be public. The Set object is owned by - * DeniedAbilityFacet, and since it can be modified, a reference to that - * object should not be exposed to any object other than DeniedAbilityFacet. - * - * @param id - * The CharID for which the Set should be returned - * @return The Set for the Player Character represented by the given CharID. - */ - private Set<ConditionalAbility> getConstructingCachedSet(CharID id) - { - Set<ConditionalAbility> componentSet = getCachedSet(id); - if (componentSet == null) - { - componentSet = new LinkedHashSet<ConditionalAbility>(); - FacetCache.set(id, thisClass, componentSet); - } - return componentSet; - } - - public void removeAll(CharID id, Object source) - { - Set<ConditionalAbility> cachedSet = getCachedSet(id); - if (cachedSet != null) - { - for (Iterator<ConditionalAbility> it = cachedSet.iterator(); it - .hasNext();) - { - if (it.next().getParent().equals(source)) - { - it.remove(); - } - } - } - } - -} \ No newline at end of file Added: Trunk/pcgen/code/src/java/pcgen/cdom/facet/DirectAbilityFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/DirectAbilityFacet.java (rev 0) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/DirectAbilityFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -0,0 +1,39 @@ +/* + * Copyright (c) Thomas Parker, 2009. + * + * 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.facet; + +import java.util.ArrayList; +import java.util.Collection; + +import pcgen.cdom.helper.CategorizedAbilitySelection; + +/** + * LanguageFacet is a Facet that tracks the Languages that have been granted to + * a Player Character. + */ +public class DirectAbilityFacet extends + AbstractListFacet<CategorizedAbilitySelection> +{ + + @Override + protected Collection<CategorizedAbilitySelection> getComponentSet() + { + return new ArrayList<CategorizedAbilitySelection>(); + } + +} Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/EquipSetFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/EquipSetFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/EquipSetFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -18,9 +18,9 @@ package pcgen.cdom.facet; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.Set; import pcgen.cdom.enumeration.CharID; import pcgen.core.Equipment; @@ -35,7 +35,7 @@ public boolean delEquipSet(CharID id, EquipSet eSet) { - Set<EquipSet> componentSet = getCachedSet(id); + Collection<EquipSet> componentSet = getCachedSet(id); if (componentSet == null) { return false; Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/FacetInitialization.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/FacetInitialization.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/FacetInitialization.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -162,6 +162,10 @@ .getFacet(ObjectAdditionFacet.class); GrantedAbilityFacet grantedAbilityFacet = FacetLibrary .getFacet(GrantedAbilityFacet.class); + DirectAbilityFacet directAbilityFacet = FacetLibrary + .getFacet(DirectAbilityFacet.class); + ConditionallyGrantedAbilityFacet cabFacet = FacetLibrary + .getFacet(ConditionallyGrantedAbilityFacet.class); HasAnyFavoredClassFacet hasAnyFavoredFacet = FacetLibrary .getFacet(HasAnyFavoredClassFacet.class); SpellBookFacet spellBookFacet = FacetLibrary @@ -226,6 +230,9 @@ classFacet.addLevelChangeListener(levelFacet); levelFacet.addLevelChangeListener(conditionalTemplateFacet); + directAbilityFacet.addDataFacetChangeListener(grantedAbilityFacet); + cabFacet.addDataFacetChangeListener(grantedAbilityFacet); + raceFacet.addDataFacetChangeListener(listSkillCostFacet); raceFacet.addDataFacetChangeListener(startingLangFacet); Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/GrantedAbilityFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/GrantedAbilityFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/GrantedAbilityFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -30,7 +30,9 @@ import pcgen.cdom.base.Category; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.enumeration.Nature; +import pcgen.cdom.helper.CategorizedAbilitySelection; import pcgen.core.Ability; +import pcgen.core.PlayerCharacter; /** * @author Thomas Parker (thpr [at] yahoo.com) @@ -38,8 +40,12 @@ * A GrantedAbilityFacet is a DataFacet that contains information about Ability * objects that are contained in a PlayerCharacter */ -public class GrantedAbilityFacet extends AbstractDataFacet<Ability> +public class GrantedAbilityFacet extends AbstractDataFacet<Ability> implements + DataFacetChangeListener<CategorizedAbilitySelection> { + private final PlayerCharacterTrackingFacet pcFacet = FacetLibrary + .getFacet(PlayerCharacterTrackingFacet.class); + /** * Add the given Ability to the list of Abilities defined by the given * Category and Nature, which is stored in this GrantedAbilityFacet for the @@ -568,4 +574,35 @@ Map<Category<Ability>, Map<Nature, Map<Ability, Set<Object>>>> catMap = getCachedMap(id); return catMap == null || catMap.isEmpty(); } + + public void dataAdded(DataFacetChangeEvent<CategorizedAbilitySelection> dfce) + { + CharID id = dfce.getCharID(); + CategorizedAbilitySelection cas = dfce.getCDOMObject(); + Ability ability = cas.getAbility(); + add(id, cas.getAbilityCategory(), cas.getNature(), ability, dfce + .getSource()); + PlayerCharacter pc = pcFacet.getPC(id); + String selection = cas.getSelection(); + if (selection != null) + { + pc.addAssociation(ability, selection); + } + } + + public void dataRemoved( + DataFacetChangeEvent<CategorizedAbilitySelection> dfce) + { + CharID id = dfce.getCharID(); + CategorizedAbilitySelection cas = dfce.getCDOMObject(); + PlayerCharacter pc = pcFacet.getPC(id); + Ability ability = cas.getAbility(); + String selection = cas.getSelection(); + if (selection != null) + { + pc.removeAssociation(ability, selection); + } + remove(id, cas.getAbilityCategory(), cas.getNature(), ability, dfce + .getSource()); + } } \ No newline at end of file Modified: Trunk/pcgen/code/src/java/pcgen/cdom/facet/RacialSubTypesFacet.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/facet/RacialSubTypesFacet.java 2010-12-17 15:43:13 UTC (rev 14164) +++ Trunk/pcgen/code/src/java/pcgen/cdom/facet/RacialSubTypesFacet.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -21,7 +21,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Set; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.enumeration.ListKey; @@ -60,7 +59,7 @@ racialSubTypes.add(st); } } - Set<PCTemplate> templates = templateFacet.getSet(id); + Collection<PCTemplate> templates = templateFacet.getSet(id); if (!templates.isEmpty()) { List<RaceSubType> added = new ArrayList<RaceSubType>(); Added: Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilitySelector.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilitySelector.java (rev 0) +++ Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilitySelector.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2008 Tom Parker <th...@us...> + * + * 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.List; + +import pcgen.cdom.base.CDOMObject; +import pcgen.cdom.base.Category; +import pcgen.cdom.base.ChooseResultActor; +import pcgen.cdom.base.ConcretePrereqObject; +import pcgen.cdom.base.QualifyingObject; +import pcgen.cdom.enumeration.Nature; +import pcgen.cdom.enumeration.ObjectKey; +import pcgen.core.Ability; +import pcgen.core.AbilityCategory; +import pcgen.core.AbilityUtilities; +import pcgen.core.Globals; +import pcgen.core.PlayerCharacter; +import pcgen.persistence.PersistenceLayerException; + +/** + * An AbilitySelection represents a "resolved" Ability, Nature and any choice + * associated with that Ability. + * + * This is generally used as the storage container when a selection has been + * made from a token like ADD:FEAT + */ +public class AbilitySelector extends ConcretePrereqObject implements + QualifyingObject, ChooseResultActor +{ + + private final String source; + + private final Category<Ability> category; + + /** + * The Nature of the Ability as it should be applied to a PlayerCharacter + */ + private final Nature nature; + + /** + * Creates a new AbilitySelection for the given Ability. The given Ability + * must be a MULT:NO Ability or this constructor will throw an exception. + * + * @param abil + * The Ability which this AbilitySelection will contain + * @param nat + * The Nature of the given Ability as it should be applied to a + * PlayerCharacter + */ + public AbilitySelector(String token, Category<Ability> cat, Nature nat) + { + category = cat; + nature = nat; + source = token; + } + + /** + * Returns the Category for the Ability in this AbilitySelection. + * + * @return The Category for the Ability in this AbilitySelection. + */ + public Category<Ability> getAbilityCategory() + { + return category; + } + + /** + * Returns the Nature of the Ability as it should be applied to a + * PlayerCharacter + * + * @return The Nature of the Ability as it should be applied to a + * PlayerCharacter + */ + public Nature getNature() + { + return nature; + } + + public void apply(PlayerCharacter pc, CDOMObject obj, String choice) + { + pc.addAppliedAbility(decodeChoice(obj, choice)); + } + + public String getLstFormat() throws PersistenceLayerException + { + return "%LIST"; + } + + public void remove(PlayerCharacter pc, CDOMObject obj, String choice) + { + pc.removeAppliedAbility(decodeChoice(obj, choice)); + } + + public CategorizedAbilitySelection decodeChoice(Object owner, String s) + { + Ability ability = Globals.getContext().ref + .silentlyGetConstructedCDOMObject(Ability.class, + AbilityCategory.FEAT, s); + + if (ability == null) + { + List<String> choices = new ArrayList<String>(); + String baseKey = AbilityUtilities.getUndecoratedName(s, choices); + ability = Globals.getContext().ref + .silentlyGetConstructedCDOMObject(Ability.class, + AbilityCategory.FEAT, baseKey); + if (ability == null) + { + throw new IllegalArgumentException("String in decodeChoice " + + "must be a Feat Key " + + "(or Feat Key with Selection if appropriate), was: " + + s); + } + return new CategorizedAbilitySelection(owner, AbilityCategory.FEAT, + ability, Nature.AUTOMATIC, choices.get(0)); + } + else if (ability.getSafe(ObjectKey.MULTIPLE_ALLOWED)) + { + /* + * MULT:YES, CHOOSE:NOCHOICE can land here + * + * TODO There needs to be better validation at some point that this + * is proper (meaning it is actually CHOOSE:NOCHOICE!) + */ + return new CategorizedAbilitySelection(owner, AbilityCategory.FEAT, + ability, Nature.AUTOMATIC, ""); + } + else + { + return new CategorizedAbilitySelection(owner, AbilityCategory.FEAT, + ability, Nature.AUTOMATIC); + } + } + + public String getSource() + { + return source; + } + + @Override + public int hashCode() + { + return category.hashCode() ^ nature.hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof AbilitySelector) + { + AbilitySelector other = (AbilitySelector) o; + return source.equals(other.source) + && category.equals(other.category) + && nature.equals(other.nature); + } + return false; + } +} Added: Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilityTargetSelector.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilityTargetSelector.java (rev 0) +++ Trunk/pcgen/code/src/java/pcgen/cdom/helper/AbilityTargetSelector.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2008 Tom Parker <th...@us...> + * + * 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 pcgen.cdom.base.CDOMObject; +import pcgen.cdom.base.Category; +import pcgen.cdom.base.ChooseResultActor; +import pcgen.cdom.base.ConcretePrereqObject; +import pcgen.cdom.base.Constants; +import pcgen.cdom.base.QualifyingObject; +import pcgen.cdom.enumeration.Nature; +import pcgen.cdom.reference.CDOMSingleRef; +import pcgen.core.Ability; +import pcgen.core.PlayerCharacter; +import pcgen.persistence.PersistenceLayerException; + +/** + * An AbilitySelection represents a "resolved" Ability, Nature and any choice + * associated with that Ability. + * + * This is generally used as the storage container when a selection has been + * made from a token like ADD:FEAT + */ +public class AbilityTargetSelector extends ConcretePrereqObject implements + QualifyingObject, ChooseResultActor +{ + + private final String source; + + private final Category<Ability> category; + + /** + * The Ability that this AbilitySelection represents + */ + private final CDOMSingleRef<Ability> ability; + + /** + * The Nature of the Ability as it should be applied to a PlayerCharacter + */ + private final Nature nature; + + private CategorizedAbilitySelection appliedSelection; + + /** + * Creates a new AbilitySelection for the given Ability. The given Ability + * must be a MULT:NO Ability or this constructor will throw an exception. + * + * @param abil + * The Ability which this AbilitySelection will contain + * @param nat + * The Nature of the given Ability as it should be applied to a + * PlayerCharacter + */ + public AbilityTargetSelector(String token, Category<Ability> cat, + CDOMSingleRef<Ability> abil, Nature nat) + { + category = cat; + ability = abil; + nature = nat; + source = token; + } + + /** + * Returns the key for the Ability in this AbilitySelection. + * + * @return The key for the Ability in this AbilitySelection. + */ + public String getAbilityKey() + { + return ability.resolvesTo().getKeyName(); + } + + /** + * Returns the Category for the Ability in this AbilitySelection. + * + * @return The Category for the Ability in this AbilitySelection. + */ + public Category<Ability> getAbilityCategory() + { + return category; + } + + /** + * Returns the "full" Key requried to fully resolve both the Ability and the + * selection for this AbilitySelection. The choice is encoded in parenthesis + * after the ability key. + * + * Note: This is primarily used for compatibility with "old" (5.x) style + * core objects and generally use of this method is discouraged. + * + * @return The "full" Key requried to fully resolve both the Ability and the + * selection for this AbilitySelection. + */ + public String getFullAbilityKey() + { + StringBuilder sb = new StringBuilder(); + sb.append(getAbilityKey()); + sb.append('('); + sb.append(Constants.LST_PERCENTLIST); + sb.append(')'); + return sb.toString(); + } + + /** + * Returns a String representation of this AbilitySelection. The choice is + * encoded in parenthesis after the Ability's name. + * + * Note: Since this does not depend on the key of the underlying Ability, it + * is an unreliable method to persistently store information about this + * AbilitySelection. If persistent storage is required, you should be using + * getPersistentFormat() + * + * @return A String representation of this AbilitySelection. + */ + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append(ability.resolvesTo().getDisplayName()); + sb.append('('); + sb.append(Constants.LST_PERCENTLIST); + sb.append(')'); + return sb.toString(); + } + + /** + * Returns the Nature of the Ability as it should be applied to a + * PlayerCharacter + * + * @return The Nature of the Ability as it should be applied to a + * PlayerCharacter + */ + public Nature getNature() + { + return nature; + } + + /** + * Returns the Ability that this AbilitySelection represents + * + * @return The Ability that this AbilitySelection represents + */ + public Ability getAbility() + { + return ability.resolvesTo(); + } + + public void apply(PlayerCharacter pc, CDOMObject obj, String choice) + { + if (appliedSelection == null) + { + appliedSelection = new CategorizedAbilitySelection(obj, category, + ability.resolvesTo(), nature, choice); + } + pc.addAppliedAbility(appliedSelection); + } + + public String getLstFormat() throws PersistenceLayerException + { + return ability.getLSTformat(false); + } + + public String getSource() + { + return source; + } + + public void remove(PlayerCharacter pc, CDOMObject obj, String choice) + { + if (appliedSelection != null) + { + pc.removeAppliedAbility(appliedSelection); + } + } + + @Override + public int hashCode() + { + return ability.hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof AbilityTargetSelector) + { + AbilityTargetSelector other = (AbilityTargetSelector) o; + return source.equals(other.source) + && category.equals(other.category) + && ability.equals(other.ability) + && nature.equals(other.nature); + } + return false; + } +} Added: Trunk/pcgen/code/src/java/pcgen/cdom/helper/CategorizedAbilitySelection.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/cdom/helper/CategorizedAbilitySelection.java (rev 0) +++ Trunk/pcgen/code/src/java/pcgen/cdom/helper/CategorizedAbilitySelection.java 2010-12-17 18:51:13 UTC (rev 14165) @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2008 Tom Parker <th...@us...> + * + * 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 pcgen.cdom.base.Category; +import pcgen.cdom.base.ConcretePrereqObject; +import pcgen.cdom.base.QualifyingObject; +import pcgen.cdom.enumeration.Nature; +import pcgen.cdom.enumeration.ObjectKey; +import pcgen.core.Ability; + +/** + * An AbilitySelection represents a "resolved" Ability, Nature and any choice + * associated with that Ability. + * + * This is generally used as the storage container when a se... [truncated message content] |