/* * 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 plugin.lsttokens.equipment; import java.math.BigDecimal; import java.util.Collection; import java.util.StringTokenizer; import pcgen.cdom.base.Constants; import pcgen.cdom.enumeration.IntegerKey; import pcgen.cdom.enumeration.ListKey; import pcgen.cdom.enumeration.ObjectKey; import pcgen.cdom.helper.Capacity; import pcgen.core.Equipment; import pcgen.rules.context.Changes; import pcgen.rules.context.LoadContext; import pcgen.rules.persistence.token.AbstractTokenWithSeparator; import pcgen.rules.persistence.token.CDOMPrimaryToken; import pcgen.rules.persistence.token.ParseResult; import pcgen.util.BigDecimalHelper; /** * Deals with CONTAINS token */ public class ContainsToken extends AbstractTokenWithSeparator<Equipment> implements CDOMPrimaryToken<Equipment> { @Override public String getTokenName() { return "CONTAINS"; } @Override protected char separator() { return '|'; } @Override protected ParseResult parseTokenWithSeparator(LoadContext context, Equipment eq, String value) { StringTokenizer pipeTok = new StringTokenizer(value, Constants.PIPE); context.getObjectContext().removeList(eq, ListKey.CAPACITY); String weightCapacity = pipeTok.nextToken(); boolean hadAsterisk = false; if (weightCapacity.charAt(0) == Constants.CHAR_ASTERISK) { hadAsterisk = true; context.getObjectContext().put(eq, ObjectKey.CONTAINER_CONSTANT_WEIGHT, Boolean.TRUE); weightCapacity = weightCapacity.substring(1); } int percentLoc = weightCapacity.indexOf(Constants.PERCENT); if (percentLoc != weightCapacity.lastIndexOf(Constants.PERCENT)) { return new ParseResult.Fail("Cannot have two weight reduction " + "characters (indicated by %): " + value, context); } if (percentLoc != -1) { if (hadAsterisk) { return new ParseResult.Fail("Cannot have Constant Weight (indicated by *) " + "and weight reduction (indicated by %): " + value, context); } String redString = weightCapacity.substring(0, percentLoc); weightCapacity = weightCapacity.substring(percentLoc + 1); try { context.getObjectContext().put(eq, IntegerKey.CONTAINER_REDUCE_WEIGHT, Integer.valueOf(redString)); } catch (NumberFormatException ex) { return new ParseResult.Fail("Weight Reduction (indicated by %) must be an integer: " + value, context); } } BigDecimal weightCap; if ("UNLIM".equals(weightCapacity)) { weightCap = Capacity.UNLIMITED; } else { try { weightCap = BigDecimalHelper.trimBigDecimal(new BigDecimal( weightCapacity)); if (BigDecimal.ZERO.compareTo(weightCap) > 0) { return new ParseResult.Fail( "Weight Capacity must be >= 0: " + weightCapacity + "\n Use 'UNLIM' (not -1) for unlimited Count", context); } } catch (NumberFormatException ex) { return new ParseResult.Fail("Weight Capacity must be 'UNLIM or a number >= 0: " + weightCapacity, context); } } context.getObjectContext().put(eq, ObjectKey.CONTAINER_WEIGHT_CAPACITY, weightCap); Capacity totalCap = null; boolean limited = true; if (!pipeTok.hasMoreTokens()) { limited = false; totalCap = Capacity.ANY; } BigDecimal limitedCapacity = BigDecimal.ZERO; while (pipeTok.hasMoreTokens()) { String typeString = pipeTok.nextToken(); int equalLoc = typeString.indexOf(Constants.EQUALS); if (equalLoc != typeString.lastIndexOf(Constants.EQUALS)) { return new ParseResult.Fail("Two many = signs", context); } if (equalLoc == -1) { limited = false; context.getObjectContext().addToList(eq, ListKey.CAPACITY, new Capacity(typeString, Capacity.UNLIMITED)); } else { String itemType = typeString.substring(0, equalLoc); String itemNumString = typeString.substring(equalLoc + 1); BigDecimal itemNumber; if ("UNLIM".equals(itemNumString)) { limited = false; itemNumber = Capacity.UNLIMITED; } else { try { itemNumber = BigDecimalHelper .trimBigDecimal(new BigDecimal(itemNumString)); } catch (NumberFormatException ex) { return new ParseResult.Fail("Item Number for " + itemType + " must be 'UNLIM' or a number > 0: " + itemNumString, context); } if (BigDecimal.ZERO.compareTo(itemNumber) >= 0) { return new ParseResult.Fail("Cannot have negative quantity of " + itemType + ": " + value, context); } } if (limited) { limitedCapacity = limitedCapacity.add(itemNumber); } context.getObjectContext().addToList(eq, ListKey.CAPACITY, new Capacity(itemType, itemNumber)); } } if (totalCap == null) { BigDecimal totalCapacity = limited ? limitedCapacity : Capacity.UNLIMITED; totalCap = Capacity.getTotalCapacity(totalCapacity); } context.getObjectContext().put(eq, ObjectKey.TOTAL_CAPACITY, totalCap); return ParseResult.SUCCESS; } @Override public String[] unparse(LoadContext context, Equipment eq) { Changes<Capacity> changes = context.getObjectContext().getListChanges( eq, ListKey.CAPACITY); Capacity totalCapacity = context.getObjectContext().getObject(eq, ObjectKey.TOTAL_CAPACITY); if (totalCapacity == null && (changes == null || changes.isEmpty())) { return null; } StringBuilder sb = new StringBuilder(); Boolean b = context.getObjectContext().getObject(eq, ObjectKey.CONTAINER_CONSTANT_WEIGHT); if (b != null && b.booleanValue()) { sb.append(Constants.CHAR_ASTERISK); } Integer reducePercent = context.getObjectContext().getInteger(eq, IntegerKey.CONTAINER_REDUCE_WEIGHT); if (reducePercent != null) { sb.append(reducePercent).append(Constants.PERCENT); } BigDecimal cap = context.getObjectContext().getObject(eq, ObjectKey.CONTAINER_WEIGHT_CAPACITY); if (cap == null) { // CONSIDER ERROR?? return null; } if (Capacity.UNLIMITED.equals(cap)) { sb.append("UNLIM"); } else { sb.append(cap); } Collection<Capacity> capacityList = changes.getAdded(); if (capacityList == null) { if (Capacity.UNLIMITED.equals(totalCapacity.getCapacity())) { // Special Case: Nothing additional return new String[] { sb.toString() }; } } BigDecimal limitedCapacity = BigDecimal.ZERO; boolean limited = true; for (Capacity c : capacityList) { String capType = c.getType(); sb.append(Constants.PIPE); BigDecimal thisCap = c.getCapacity(); sb.append(capType); if (Capacity.UNLIMITED.equals(thisCap)) { limited = false; } else { if (limited) { limitedCapacity = limitedCapacity.add(thisCap); } sb.append(Constants.EQUALS).append(thisCap); } } if (!limitedCapacity.equals(totalCapacity.getCapacity()) && !Capacity.UNLIMITED.equals(totalCapacity.getCapacity())) { // Need to write out total sb.append("Total").append(Constants.EQUALS).append( totalCapacity.getCapacity()); } return new String[] { sb.toString() }; } @Override public Class<Equipment> getTokenClass() { return Equipment.class; } }