/* * Copyright 2008 (C) Tom 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 pcgen.rules.persistence.token; import pcgen.cdom.enumeration.IntegerKey; import pcgen.cdom.enumeration.ObjectKey; import pcgen.cdom.inst.PCClassLevel; import pcgen.core.PCClass; import pcgen.core.SubClass; import pcgen.core.SubstitutionClass; import pcgen.rules.context.LoadContext; /** * ClassWrappedToken provides compatibility for previously allowed bad behavior * in data files. * * Many Class tokens in PCGen versions up to 5.14 ignored the class level, so * they are technically Class tags and not CLASSLEVEL tags. Yet, PCGen 5.14 * allows those tags to appear on class level lines. This is a bit deceptive to * users in that the effect will always be on the class, and not appear on the * specified level. * * Unfortunately, one cannot simply remove support for using CLASS tokens on * CLASSLEVEL lines, because if they are used at level 1, then they are * equivalent to appearing on a CLASS line. Certainly, the data monkeys use it * that way. For example, Blackguard in RSRD advanced uses EXCHANGELEVEL on the * first level line. * * Therefore the entire ClassWrappedToken system is a workaround for data * monkeys using CLASS tokens on CLASSLEVEL lines, and therefore it should only * work on level one, otherwise expectations for when the token will take * effect are not set. */ public class ClassWrappedToken implements CDOMCompatibilityToken<PCClassLevel> { private static int wrapIndex = Integer.MIN_VALUE; private static final Integer ONE = 1; private final CDOMToken<PCClass> wrappedToken; private final int priority = wrapIndex++; @Override public Class<PCClassLevel> getTokenClass() { return PCClassLevel.class; } public ClassWrappedToken(CDOMToken<PCClass> tok) { wrappedToken = tok; } @Override public ParseResult parseToken(LoadContext context, PCClassLevel obj, String value) { if (ONE.equals(obj.get(IntegerKey.LEVEL))) { PCClass parent = (PCClass) obj.get(ObjectKey.TOKEN_PARENT); if (parent instanceof SubClass || parent instanceof SubstitutionClass) { return new ParseResult.Fail("Data used token: " + value + " which is a Class token, " + "but it was used in a class level for a " + parent.getClass().getSimpleName(), context); } return wrappedToken.parseToken(context, parent, value); } return new ParseResult.Fail("Data used token: " + value + " which is a Class token, " + "but it was used in a class level line other than level 1", context); } @Override public String getTokenName() { return wrappedToken.getTokenName(); } @Override public int compatibilityLevel() { return 5; } @Override public int compatibilityPriority() { return priority; } @Override public int compatibilitySubLevel() { return 14; } }