/* * Copyright 2007 (C) Thomas Parker <thpr@users.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 plugin.lsttokens.race; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import pcgen.base.formula.Formula; import pcgen.cdom.base.CDOMObject; import pcgen.cdom.base.CDOMReference; import pcgen.cdom.base.ChoiceSet; import pcgen.cdom.base.ConcretePersistentTransitionChoice; import pcgen.cdom.base.Constants; import pcgen.cdom.base.FormulaFactory; import pcgen.cdom.base.PersistentChoiceActor; import pcgen.cdom.base.PersistentTransitionChoice; import pcgen.cdom.base.SelectableSet; import pcgen.cdom.choiceset.ReferenceChoiceSet; import pcgen.cdom.enumeration.ListKey; import pcgen.cdom.enumeration.ObjectKey; import pcgen.core.Language; import pcgen.core.PlayerCharacter; import pcgen.core.Race; import pcgen.rules.context.LoadContext; import pcgen.rules.persistence.TokenUtilities; import pcgen.rules.persistence.token.AbstractTokenWithSeparator; import pcgen.rules.persistence.token.CDOMSecondaryToken; import pcgen.rules.persistence.token.DeferredToken; import pcgen.rules.persistence.token.ParseResult; public class ChooseLangautoToken extends AbstractTokenWithSeparator<Race> implements CDOMSecondaryToken<Race>, PersistentChoiceActor<Language>, DeferredToken<Race> { private static final Class<Language> LANGUAGE_CLASS = Language.class; @Override public String getParentToken() { return "CHOOSE"; } private String getFullName() { return getParentToken() + Constants.COLON + getTokenName(); } @Override public String getTokenName() { return "LANGAUTO"; } @Override protected char separator() { return '|'; } @Override public ParseResult parseTokenWithSeparator(LoadContext context, Race race, String value) { List<CDOMReference<Language>> refs = new ArrayList<CDOMReference<Language>>(); StringTokenizer tok = new StringTokenizer(value, Constants.PIPE); while (tok.hasMoreTokens()) { String tokText = tok.nextToken(); CDOMReference<Language> lang = TokenUtilities.getReference(context, LANGUAGE_CLASS, tokText); if (lang == null) { return new ParseResult.Fail(" Error was encountered while parsing " + getFullName() + ": " + value + " had an invalid reference: " + tokText, context); } refs.add(lang); } ReferenceChoiceSet<Language> rcs = new ReferenceChoiceSet<Language>(refs); if (!rcs.getGroupingState().isValid()) { return new ParseResult.Fail("Non-sensical " + getFullName() + ": Contains ANY and a specific reference: " + value, context); } ChoiceSet<Language> cs = new ChoiceSet<Language>(getTokenName(), rcs); cs.setTitle("Pick a Language"); PersistentTransitionChoice<Language> tc = new ConcretePersistentTransitionChoice<Language>(cs, FormulaFactory.ONE); context.getObjectContext().put(race, ObjectKey.CHOOSE_LANGAUTO, tc); tc.setChoiceActor(this); return ParseResult.SUCCESS; } @Override public String[] unparse(LoadContext context, Race race) { PersistentTransitionChoice<Language> container = context .getObjectContext().getObject(race, ObjectKey.CHOOSE_LANGAUTO); if (container == null) { return null; } SelectableSet<?> cs = container.getChoices(); Formula f = container.getCount(); if (f == null) { context.addWriteMessage("Unable to find " + getFullName() + " Count"); return null; } StringBuilder sb = new StringBuilder(); sb .append(cs.getLSTformat().replaceAll(Constants.COMMA, Constants.PIPE)); return new String[] { sb.toString() }; } @Override public Class<Race> getTokenClass() { return Race.class; } @Override public void applyChoice(CDOMObject owner, Language choice, PlayerCharacter pc) { pc.addFreeLanguage(choice, owner); } @Override public boolean allow(Language choice, PlayerCharacter pc, boolean allowStack) { return !pc.hasLanguage(choice); } @Override public Language decodeChoice(LoadContext context, String s) { return context.getReferenceContext().silentlyGetConstructedCDOMObject(LANGUAGE_CLASS, s); } @Override public String encodeChoice(Language choice) { return choice.getKeyName(); } @Override public void restoreChoice(PlayerCharacter pc, CDOMObject owner, Language choice) { pc.addFreeLanguage(choice, owner); } @Override public Class<Race> getDeferredTokenClass() { return Race.class; } /* * This is deferred into ListKey.ADD to ensure that ADD:.CLEAR doesn't * impact CHOOSE:LANGAUTO. It is hoped that CHOOSE:LANGAUTO can be * refactored into an ADD token in order to avoid this contortion */ @Override public boolean process(LoadContext context, Race race) { PersistentTransitionChoice<Language> langauto = race .get(ObjectKey.CHOOSE_LANGAUTO); if (langauto != null) { race.addToListFor(ListKey.ADD, langauto); } return true; } @Override public void removeChoice(PlayerCharacter pc, CDOMObject owner, Language choice) { pc.removeFreeLanguage(choice, owner); } }