/* * AbilitySelection.java * Missing License Header, Copyright 2016 (C) Andrew Maitland <amaitland@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 pcgen.cdom.content; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import pcgen.cdom.base.CDOMObject; import pcgen.cdom.base.Constants; import pcgen.cdom.base.Reducible; import pcgen.cdom.enumeration.ObjectKey; import pcgen.core.Ability; import pcgen.core.AbilityCategory; import pcgen.core.AbilityUtilities; import pcgen.core.SettingsHandler; import pcgen.rules.context.LoadContext; public class AbilitySelection extends Selection<Ability, String> implements Comparable<AbilitySelection>, Reducible { public AbilitySelection(Ability obj, String sel) { super(obj, sel); } /** * Decodes the given String into an AbilitySelection. The String format to * be passed into this method is defined solely by the return result of the * getPersistentFormat method. There is no guarantee that the encoding is * human readable, simply that the encoding is uniquely identifying such * that this method is capable of decoding the String into an * AbilitySelection. * * @param persistentFormat * The String which should be decoded to provide an * AbilitySelection. * * @return An AbilitySelection that was encoded in the given String. */ public static AbilitySelection getAbilitySelectionFromPersistentFormat( LoadContext context, String persistentFormat) { if (persistentFormat.indexOf(Constants.PIPE) < 0) { return decodeFeatSelectionChoice(context, persistentFormat); } StringTokenizer st = new StringTokenizer(persistentFormat, Constants.PIPE); String catString = st.nextToken(); if (!catString.startsWith("CATEGORY=")) { throw new IllegalArgumentException( "String in getAbilitySelectionFromPersistentFormat " + "must start with CATEGORY=, found: " + persistentFormat); } String cat = catString.substring(9); AbilityCategory ac = SettingsHandler.getGame().getAbilityCategory(cat); if (ac == null) { throw new IllegalArgumentException( "Category in getAbilitySelectionFromPersistentFormat " + "must exist found: " + cat); } String ab = st.nextToken(); Ability a = context.getReferenceContext().silentlyGetConstructedCDOMObject( Ability.class, ac, ab); if (a == null) { throw new IllegalArgumentException( "Second argument in String in getAbilitySelectionFromPersistentFormat " + "must be an Ability, but it was not found: " + persistentFormat); } String sel = null; if (st.hasMoreTokens()) { /* * No need to check for MULT:YES/NO here, as that is checked * implicitly in the construction of AbilitySelection below */ sel = st.nextToken(); } else if (persistentFormat.endsWith(Constants.PIPE)) { // Handle the StringTokenizer ignoring blank tokens at the end sel = ""; } if (st.hasMoreTokens()) { throw new IllegalArgumentException( "String in getAbilitySelectionFromPersistentFormat " + "must have 2 or 3 arguments, but found more: " + persistentFormat); } return new AbilitySelection(a, sel); } /** * Decode a legacy feat selection format. This may come from a character * saved when an ability was coded with a FEATSELECTION but is loaded with * the same tag migrated to an ABILITYSELECTION. * * @param context * The data loading context in use. * @param persistentFormat * The String which should be decoded to provide an * AbilitySelection. * * @return An AbilitySelection that was encoded in the given String. */ private static AbilitySelection decodeFeatSelectionChoice( LoadContext context, String persistentFormat) { Ability ability = context.getReferenceContext().silentlyGetConstructedCDOMObject( Ability.class, AbilityCategory.FEAT, persistentFormat); if (ability == null) { List<String> choices = new ArrayList<>(); String baseKey = AbilityUtilities.getUndecoratedName(persistentFormat, choices); ability = context.getReferenceContext() .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: " + persistentFormat); } return new AbilitySelection(ability, 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 AbilitySelection(ability, ""); } else { return new AbilitySelection(ability, null); } } /** * Encodes the AbilitySelection into a String sufficient to uniquely * identify the AbilitySelection. This may not sufficiently encode to be * stored into a file or format which restricts certain characters (such as * URLs), it simply encodes into an identifying String. There is no * guarantee that this encoding is human readable, simply that the encoding * is uniquely identifying such that the * getAbilitySelectionFromPersistentFormat method of AbilitySelection is * capable of decoding the String into an AbilitySelection. * * @return A String sufficient to uniquely identify the AbilitySelection. */ public String getPersistentFormat() { Ability ability = getObject(); StringBuilder sb = new StringBuilder(); sb.append("CATEGORY="); sb.append(ability.getCDOMCategory().getKeyName()); sb.append('|'); sb.append(ability.getKeyName()); String selection = getSelection(); if (selection != null) { sb.append('|'); sb.append(selection); } return sb.toString(); } public String getAbilityKey() { return getObject().getKeyName(); } public boolean containsAssociation(String a) { String assoc = getSelection(); return (a == assoc) || ((a != null) && a.equalsIgnoreCase(assoc)); } @Override public String toString() { StringBuilder sb = new StringBuilder(50); sb.append(getAbilityKey()); String selection = getSelection(); if ((selection != null) && (!selection.isEmpty())) { sb.append(" ("); sb.append(selection); sb.append(')'); } return sb.toString(); } @Override public int compareTo(AbilitySelection o) { int acompare = getObject().compareTo(o.getObject()); if (acompare != 0) { return acompare; } String selection = getSelection(); String oselection = o.getSelection(); if (selection == oselection) { return 0; } if (selection == null) { return -1; } return selection.compareTo(oselection); } /** * @see pcgen.cdom.base.Reducible#getCDOMObject() */ @Override public CDOMObject getCDOMObject() { return getObject(); } }