use of pcgen.rules.persistence.token.ComplexParseResult in project pcgen by PCGen.
the class CompanionListLst method parseTokenWithSeparator.
@Override
protected ParseResult parseTokenWithSeparator(LoadContext context, CDOMObject obj, String value) {
if (obj instanceof Ungranted) {
return new ParseResult.Fail("Cannot use " + getTokenName() + " on an Ungranted object type: " + obj.getClass().getSimpleName(), context);
}
StringTokenizer tok = new StringTokenizer(value, LstUtils.PIPE);
String companionType = tok.nextToken();
if (!tok.hasMoreTokens()) {
return new ParseResult.Fail(getTokenName() + " requires more than just a Type: " + value, context);
}
String list = tok.nextToken();
ParseResult pr = checkForIllegalSeparator(',', list);
if (!pr.passed()) {
return pr;
}
StringTokenizer subTok = new StringTokenizer(list, LstUtils.COMMA);
Set<CDOMReference<Race>> races = new HashSet<>();
boolean foundAny = false;
while (subTok.hasMoreTokens()) {
String tokString = subTok.nextToken();
if (Constants.LST_ANY.equalsIgnoreCase(tokString)) {
foundAny = true;
races.add(context.getReferenceContext().getCDOMAllReference(Race.class));
} else if (tokString.startsWith("RACETYPE=")) {
String raceType = tokString.substring(9);
if (raceType.isEmpty()) {
return new ParseResult.Fail(getTokenName() + " Error: RaceType was not specified.", context);
}
races.add(new ObjectMatchingReference<>(tokString, Race.class, context.getReferenceContext().getCDOMAllReference(Race.class), ObjectKey.RACETYPE, RaceType.getConstant(raceType)));
} else if (tokString.startsWith("RACESUBTYPE=")) {
String raceSubType = tokString.substring(12);
if (raceSubType.isEmpty()) {
return new ParseResult.Fail(getTokenName() + " Error: RaceSubType was not specified.", context);
}
races.add(new ListMatchingReference<>(tokString, Race.class, context.getReferenceContext().getCDOMAllReference(Race.class), ListKey.RACESUBTYPE, RaceSubType.getConstant(raceSubType)));
} else if (looksLikeAPrerequisite(tokString)) {
return new ParseResult.Fail(getTokenName() + " Error: " + tokString + " found where companion race expected.", context);
} else {
races.add(context.getReferenceContext().getCDOMReference(Race.class, tokString));
}
}
if (foundAny && races.size() > 1) {
return new ParseResult.Fail("Non-sensical Race List includes Any and specific races: " + value, context);
}
if (!tok.hasMoreTokens()) {
// No other args, so we're done
finish(context, obj, companionType, races, null, null);
return ParseResult.SUCCESS;
}
// The remainder of the elements are optional.
Integer followerAdjustment = null;
String optArg = tok.nextToken();
while (true) {
if (optArg.startsWith(FOLLOWERADJUSTMENT)) {
if (followerAdjustment != null) {
return new ParseResult.Fail(getTokenName() + " Error: Multiple " + FOLLOWERADJUSTMENT + " tags specified.", context);
}
int faStringLength = FOLLOWERADJUSTMENT.length();
if (optArg.length() <= faStringLength + 1) {
return new ParseResult.Fail("Empty FOLLOWERADJUSTMENT value in " + getTokenName() + " is prohibited", context);
}
String adj = optArg.substring(faStringLength + 1);
try {
followerAdjustment = Integer.valueOf(adj);
} catch (NumberFormatException nfe) {
ComplexParseResult cpr = new ComplexParseResult();
cpr.addErrorMessage("Expecting a number for FOLLOWERADJUSTMENT: " + adj);
cpr.addErrorMessage(" was parsing Token " + getTokenName());
return cpr;
}
} else if (looksLikeAPrerequisite(optArg)) {
break;
} else {
return new ParseResult.Fail(getTokenName() + ": Unknown argument (was expecting FOLLOWERADJUSTMENT: or PRExxx): " + optArg, context);
}
if (!tok.hasMoreTokens()) {
// No prereqs, so we're done
finish(context, obj, companionType, races, followerAdjustment, null);
return ParseResult.SUCCESS;
}
optArg = tok.nextToken();
}
List<Prerequisite> prereqs = new ArrayList<>();
while (true) {
Prerequisite prereq = getPrerequisite(optArg);
if (prereq == null) {
return new ParseResult.Fail(" (Did you put items after the " + "PRExxx tags in " + getTokenName() + ":?)", context);
}
prereqs.add(prereq);
if (!tok.hasMoreTokens()) {
break;
}
optArg = tok.nextToken();
}
finish(context, obj, companionType, races, followerAdjustment, prereqs);
return ParseResult.SUCCESS;
}
use of pcgen.rules.persistence.token.ComplexParseResult in project pcgen by PCGen.
the class DrLst method parseTokenWithSeparator.
@Override
protected ParseResult parseTokenWithSeparator(LoadContext context, CDOMObject obj, String value) {
if (obj instanceof Ungranted) {
return new ParseResult.Fail("Cannot use " + getTokenName() + " on an Ungranted object type: " + obj.getClass().getSimpleName(), context);
}
if (Constants.LST_DOT_CLEAR.equals(value)) {
context.getObjectContext().removeList(obj, ListKey.DAMAGE_REDUCTION);
return ParseResult.SUCCESS;
}
StringTokenizer tok = new StringTokenizer(value, Constants.PIPE);
String drString = tok.nextToken();
ParseResult pr = checkForIllegalSeparator('/', drString);
if (!pr.passed()) {
return pr;
}
String[] values = drString.split("/");
if (values.length != 2) {
ComplexParseResult cpr = new ComplexParseResult();
cpr.addErrorMessage(getTokenName() + " failed to build DamageReduction with value " + value);
cpr.addErrorMessage(" ...expected a String with one / as a separator");
return cpr;
}
Formula formula = FormulaFactory.getFormulaFor(values[0]);
if (!formula.isValid()) {
return new ParseResult.Fail("Formula in " + getTokenName() + " was not valid: " + formula.toString(), context);
}
DamageReduction dr = new DamageReduction(formula, values[1]);
if (tok.hasMoreTokens()) {
String currentToken = tok.nextToken();
Prerequisite prereq = getPrerequisite(currentToken);
if (prereq == null) {
return ParseResult.INTERNAL_ERROR;
}
dr.addPrerequisite(prereq);
}
context.getObjectContext().addToList(obj, ListKey.DAMAGE_REDUCTION, dr);
return ParseResult.SUCCESS;
}
use of pcgen.rules.persistence.token.ComplexParseResult in project pcgen by PCGen.
the class RepeatlevelToken method parseTokenWithSeparator.
@Override
protected ParseResult parseTokenWithSeparator(LoadContext context, PCTemplate template, String value) {
ParseResult pr = checkForIllegalSeparator(':', value);
if (!pr.passed()) {
return pr;
}
//
// x|y|z:level:<level assigned item>
//
int endRepeat = value.indexOf(Constants.COLON);
if (endRepeat < 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (No Colon): " + value, context);
}
int endLevel = value.indexOf(Constants.COLON, endRepeat + 1);
if (endLevel < 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Only One Colon): " + value, context);
}
int endAssignType = value.indexOf(Constants.COLON, endLevel + 1);
if (endAssignType == -1) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Only Two Colons): " + value, context);
}
String repeatedInfo = value.substring(0, endRepeat);
StringTokenizer repeatToken = new StringTokenizer(repeatedInfo, Constants.PIPE);
if (repeatToken.countTokens() != 3) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (incorrect PIPE count in repeat): " + repeatedInfo, context);
}
String levelIncrement = repeatToken.nextToken();
int lvlIncrement;
try {
lvlIncrement = Integer.parseInt(levelIncrement);
} catch (NumberFormatException nfe) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Level Increment was not an Integer): " + levelIncrement, context);
}
if (lvlIncrement <= 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Level Increment was <= 0): " + lvlIncrement, context);
}
String consecutiveString = repeatToken.nextToken();
int consecutive;
try {
consecutive = Integer.parseInt(consecutiveString);
} catch (NumberFormatException nfe) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Consecutive Value was not an Integer): " + consecutiveString, context);
}
if (consecutive < 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Consecutive String was <= 0): " + consecutive, context);
}
String maxLevelString = repeatToken.nextToken();
int maxLevel;
try {
maxLevel = Integer.parseInt(maxLevelString);
} catch (NumberFormatException nfe) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Max Level was not an Integer): " + maxLevelString, context);
}
if (maxLevel <= 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Max Level was <= 0): " + maxLevel, context);
}
String levelString = value.substring(endRepeat + 1, endLevel);
int iLevel;
try {
iLevel = Integer.parseInt(levelString);
} catch (NumberFormatException nfe) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Level was not a number): " + levelString, context);
}
if (iLevel <= 0) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Level was <= 0): " + iLevel, context);
}
if (iLevel > maxLevel) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Starting Level was > Maximum Level)", context);
}
if (iLevel + lvlIncrement > maxLevel) {
return new ParseResult.Fail("Malformed " + getTokenName() + " Token (Does not repeat, Staring Level + Increment > Maximum Level)", context);
}
if (consecutive != 0 && ((maxLevel - iLevel) / lvlIncrement) < consecutive) {
ComplexParseResult cpr = new ComplexParseResult();
cpr.addErrorMessage("Malformed " + getTokenName() + " Token (Does not use Skip Interval value): " + consecutive);
cpr.addErrorMessage(" You should set the interval to zero");
return cpr;
}
String typeStr = value.substring(endLevel + 1, endAssignType);
String contentStr = value.substring(endAssignType + 1);
/*
* typeStr and contentStr can't be null due to hasIllegalSeparator check
* on colon above
*/
PCTemplate consolidator = new PCTemplate();
consolidator.put(IntegerKey.CONSECUTIVE, consecutive);
consolidator.put(IntegerKey.MAX_LEVEL, maxLevel);
consolidator.put(IntegerKey.LEVEL_INCREMENT, lvlIncrement);
consolidator.put(IntegerKey.START_LEVEL, iLevel);
context.getObjectContext().addToList(template, ListKey.REPEATLEVEL_TEMPLATES, consolidator);
context.getReferenceContext().getManufacturer(PCTemplate.class).addDerivativeObject(consolidator);
for (int count = consecutive; iLevel <= maxLevel; iLevel += lvlIncrement) {
if ((consecutive == 0) || (count != 0)) {
PCTemplate derivative = new PCTemplate();
derivative.put(IntegerKey.LEVEL, count);
context.getReferenceContext().getManufacturer(PCTemplate.class).addDerivativeObject(derivative);
context.getObjectContext().addToList(consolidator, ListKey.LEVEL_TEMPLATES, derivative);
try {
if (!context.processToken(derivative, typeStr, contentStr)) {
return ParseResult.INTERNAL_ERROR;
}
} catch (PersistenceLayerException e) {
return new ParseResult.Fail(e.getMessage(), context);
}
}
if (consecutive != 0) {
if (count == 0) {
count = consecutive;
} else {
--count;
}
}
}
return ParseResult.SUCCESS;
}
use of pcgen.rules.persistence.token.ComplexParseResult in project pcgen by PCGen.
the class VisibleToken method parseNonEmptyToken.
@Override
protected ParseResult parseNonEmptyToken(LoadContext context, Skill skill, String value) {
String visString = value;
int pipeLoc = value.indexOf(Constants.PIPE);
boolean readOnly = false;
if (pipeLoc != -1) {
if (value.substring(pipeLoc + 1).equals("READONLY")) {
visString = value.substring(0, pipeLoc);
readOnly = true;
} else {
return new ParseResult.Fail("Misunderstood text after pipe on Tag: " + value, context);
}
}
Visibility vis;
if (visString.equals("YES")) {
vis = Visibility.DEFAULT;
} else if (visString.equals("ALWAYS")) {
vis = Visibility.DEFAULT;
} else if (visString.equals("DISPLAY")) {
vis = Visibility.DISPLAY_ONLY;
} else if (visString.equals("GUI")) {
vis = Visibility.DISPLAY_ONLY;
} else if (visString.equals("EXPORT")) {
vis = Visibility.OUTPUT_ONLY;
} else if (visString.equals("CSHEET")) {
vis = Visibility.OUTPUT_ONLY;
} else if (visString.equals("NO")) {
vis = Visibility.HIDDEN;
} else {
ComplexParseResult cpr = new ComplexParseResult();
cpr.addErrorMessage("Unexpected value used in " + getTokenName() + " in Skill");
cpr.addErrorMessage(" " + value + " is not a valid value for " + getTokenName());
cpr.addErrorMessage(" Valid values in Skill are YES, ALWAYS, NO, DISPLAY, GUI, EXPORT, CSHEET");
return cpr;
}
context.getObjectContext().put(skill, ObjectKey.VISIBILITY, vis);
if (readOnly) {
if (vis.equals(Visibility.OUTPUT_ONLY)) {
return new ParseResult.Fail("|READONLY suffix not valid with " + getTokenName() + " EXPORT or CSHEET", context);
}
context.getObjectContext().put(skill, ObjectKey.READ_ONLY, Boolean.TRUE);
}
return ParseResult.SUCCESS;
}
use of pcgen.rules.persistence.token.ComplexParseResult in project pcgen by PCGen.
the class HitdieToken method parseNonEmptyToken.
@Override
protected ParseResult parseNonEmptyToken(LoadContext context, PCTemplate template, String value) {
try {
String lock = value;
int pipeLoc = lock.indexOf(Constants.PIPE);
if (pipeLoc != lock.lastIndexOf(Constants.PIPE)) {
return new ParseResult.Fail(getTokenName() + " has more than one pipe, " + "is not of format: <int>[|<prereq>]", context);
}
// Do not initialize, null is significant
CDOMReference<PCClass> owner = null;
if (pipeLoc != -1) {
// Has a limitation
String lockPre = lock.substring(pipeLoc + 1);
if (lockPre.startsWith("CLASS.TYPE=")) {
String substring = lock.substring(pipeLoc + 12);
if (substring.isEmpty()) {
return new ParseResult.Fail("Cannot have Empty Type Limitation in " + getTokenName() + ": " + value, context);
}
ParseResult pr = checkForIllegalSeparator('.', substring);
if (!pr.passed()) {
return pr;
}
owner = context.getReferenceContext().getCDOMTypeReference(PCCLASS_CLASS, substring.split("\\."));
} else if (lockPre.startsWith(Constants.LST_CLASS_EQUAL)) {
String substring = lock.substring(pipeLoc + 7);
if (substring.isEmpty()) {
return new ParseResult.Fail("Cannot have Empty Class Limitation in " + getTokenName() + ": " + value, context);
}
owner = context.getReferenceContext().getCDOMReference(PCCLASS_CLASS, substring);
} else {
return new ParseResult.Fail("Invalid Limitation in HITDIE: " + lockPre, context);
}
lock = lock.substring(0, pipeLoc);
}
Processor<HitDie> hdm;
if (lock.startsWith("%/")) {
// HITDIE:%/num --- divides the classes hit die by num.
int denom = Integer.parseInt(lock.substring(2));
if (denom <= 0) {
return new ParseResult.Fail(getTokenName() + " was expecting a Positive Integer " + "for dividing Lock, was : " + lock.substring(2), context);
}
hdm = new HitDieFormula(new DividingFormula(denom));
} else if (lock.startsWith("%*")) {
// HITDIE:%*num --- multiplies the classes hit die by num.
int mult = Integer.parseInt(lock.substring(2));
if (mult <= 0) {
return new ParseResult.Fail(getTokenName() + " was expecting a Positive " + "Integer for multiplying Lock, was : " + lock.substring(2), context);
}
hdm = new HitDieFormula(new MultiplyingFormula(mult));
} else if (lock.startsWith("%+")) {
// possibly redundant with BONUS:HD MAX|num
// HITDIE:%+num --- adds num to the classes hit die.
int add = Integer.parseInt(lock.substring(2));
if (add <= 0) {
return new ParseResult.Fail(getTokenName() + " was expecting a Positive " + "Integer for adding Lock, was : " + lock.substring(2), context);
}
hdm = new HitDieFormula(new AddingFormula(add));
} else if (lock.startsWith("%-")) {
// HITDIE:%-num --- subtracts num from the classes hit die.
// possibly redundant with BONUS:HD MAX|num if that will
// take negative numbers.
int sub = Integer.parseInt(lock.substring(2));
if (sub <= 0) {
return new ParseResult.Fail(getTokenName() + " was expecting a Positive " + "Integer for subtracting Lock, was : " + lock.substring(2), context);
}
hdm = new HitDieFormula(new SubtractingFormula(sub));
} else if (lock.startsWith("%up")) {
// HITDIE:%upnum --- moves the hit die num steps up the die size
// list d4,d6,d8,d10,d12. Stops at d12.
int steps = Integer.parseInt(lock.substring(3));
if (steps <= 0) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName() + " up (must be positive)", context);
}
if (steps >= 5) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName() + " up (too large)", context);
}
hdm = new HitDieStep(steps, new HitDie(12));
} else if (lock.startsWith("%Hup")) {
// HITDIE:%upnum --- moves the hit die num steps up the die size
// No limit.
int steps = Integer.parseInt(lock.substring(4));
if (steps <= 0) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName(), context);
}
hdm = new HitDieStep(steps, null);
} else if (lock.startsWith("%down")) {
// HITDIE:%downnum --- moves the hit die num steps down the die
// size
// list d4,d6,d8,d10,d12. Stops at d4.
int steps = Integer.parseInt(lock.substring(5));
if (steps <= 0) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName() + " down (must be positive)", context);
}
if (steps >= 5) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName() + " down (too large)", context);
}
hdm = new HitDieStep(-steps, new HitDie(4));
} else if (lock.startsWith("%Hdown")) {
// HITDIE:%downnum --- moves the hit die num steps down the die
// size
// list. No limit.
int steps = Integer.parseInt(lock.substring(6));
if (steps <= 0) {
return new ParseResult.Fail("Invalid Step Count: " + steps + " in " + getTokenName(), context);
}
hdm = new HitDieStep(-steps, null);
} else {
int i = Integer.parseInt(lock);
if (i <= 0) {
return new ParseResult.Fail("Invalid HitDie: " + i + " in " + getTokenName(), context);
}
// HITDIE:num --- sets the hit die to num regardless of class.
hdm = new HitDieLock(new HitDie(i));
}
Processor<HitDie> mod = owner == null ? hdm : new ContextProcessor<>(hdm, owner);
context.getObjectContext().put(template, ObjectKey.HITDIE, mod);
return ParseResult.SUCCESS;
} catch (NumberFormatException nfe) {
ComplexParseResult cpr = new ComplexParseResult();
cpr.addErrorMessage("Invalid Number in " + getTokenName() + ": " + nfe.getLocalizedMessage());
cpr.addErrorMessage(" Must be an Integer");
return cpr;
}
}
Aggregations