Search in sources :

Example 46 with Prerequisite

use of pcgen.core.prereq.Prerequisite in project pcgen by PCGen.

the class SpellsLst method parseNonEmptyToken.

/**
	 * {@literal 
	 * SPELLS:<spellbook name>|[<optional parameters, pipe deliminated>] |<spell
	 * name>[,<formula for DC>] |<spell name2>[,<formula2 for DC>] |PRExxx
	 * |PRExxx
	 *
	 * CASTERLEVEL=<formula> Casterlevel of spells TIMES=<formula> Cast Times
	 * per day, -1=At Will
	 *}
	 * @param sourceLine
	 *            Line from the LST file without the SPELLS:
	 * @return spells list
	 */
@Override
protected ParseResult parseNonEmptyToken(LoadContext context, CDOMObject obj, String sourceLine) {
    if (obj instanceof Ungranted) {
        return new ParseResult.Fail("Cannot use " + getTokenName() + " on an Ungranted object type: " + obj.getClass().getSimpleName(), context);
    }
    if ((sourceLine == null) || sourceLine.isEmpty()) {
        return new ParseResult.Fail("Argument in " + getTokenName() + " cannot be empty", context);
    }
    if (sourceLine.equals(Constants.LST_DOT_CLEAR_ALL)) {
        context.getListContext().removeAllFromList(getTokenName(), obj, Spell.SPELLS);
        return ParseResult.SUCCESS;
    }
    ParsingSeparator sep = new ParsingSeparator(sourceLine, '|');
    sep.addGroupingPair('[', ']');
    sep.addGroupingPair('(', ')');
    String spellBook = sep.next();
    if (spellBook.isEmpty()) {
        return new ParseResult.Fail("SpellBook in " + getTokenName() + " cannot be empty", context);
    }
    // Formula casterLevel = null;
    String casterLevel = null;
    String times = null;
    String timeunit = null;
    if (!sep.hasNext()) {
        return new ParseResult.Fail(getTokenName() + ": minimally requires a Spell Name", context);
    }
    String token = sep.next();
    while (true) {
        if (token.startsWith("TIMES=")) {
            if (times != null) {
                return new ParseResult.Fail("Found two TIMES entries in " + getTokenName() + ": invalid: " + sourceLine, context);
            }
            times = token.substring(6);
            if (times.isEmpty()) {
                return new ParseResult.Fail("Error in Times in " + getTokenName() + ": argument was empty", context);
            }
            if (!sep.hasNext()) {
                return new ParseResult.Fail(getTokenName() + ": minimally requires " + "a Spell Name (after TIMES=)", context);
            }
            token = sep.next();
        } else if (token.startsWith("TIMEUNIT=")) {
            if (timeunit != null) {
                return new ParseResult.Fail("Found two TIMEUNIT entries in " + getTokenName() + ": invalid: " + sourceLine, context);
            }
            timeunit = token.substring(9);
            if (timeunit.isEmpty()) {
                return new ParseResult.Fail("Error in TimeUnit in " + getTokenName() + ": argument was empty", context);
            }
            if (!sep.hasNext()) {
                return new ParseResult.Fail(getTokenName() + ": minimally requires " + "a Spell Name (after TIMEUNIT=)", context);
            }
            token = sep.next();
        } else if (token.startsWith("CASTERLEVEL=")) {
            if (casterLevel != null) {
                return new ParseResult.Fail("Found two CASTERLEVEL entries in " + getTokenName() + ": invalid: " + sourceLine, context);
            }
            casterLevel = token.substring(12);
            if (casterLevel.isEmpty()) {
                return new ParseResult.Fail("Error in Caster Level in " + getTokenName() + ": argument was empty", context);
            }
            if (!sep.hasNext()) {
                return new ParseResult.Fail(getTokenName() + ": minimally requires a " + "Spell Name (after CASTERLEVEL=)", context);
            }
            token = sep.next();
        } else {
            break;
        }
    }
    if (times == null) {
        times = "1";
    }
    if (token.isEmpty()) {
        return new ParseResult.Fail("Spell arguments may not be empty in " + getTokenName() + ": " + sourceLine, context);
    }
    if (token.charAt(0) == ',') {
        return new ParseResult.Fail(getTokenName() + " Spell arguments may not start with , : " + token, context);
    }
    if (token.charAt(token.length() - 1) == ',') {
        return new ParseResult.Fail(getTokenName() + " Spell arguments may not end with , : " + token, context);
    }
    if (token.indexOf(",,") != -1) {
        return new ParseResult.Fail(getTokenName() + " Spell arguments uses double separator ,, : " + token, context);
    }
    /*
		 * CONSIDER This is currently order enforcing the reference fetching to
		 * match the integration tests that we perform, and their current
		 * behavior. Not sure if this is really tbe best solution?
		 *
		 * See CDOMObject.
		 */
    DoubleKeyMap<CDOMReference<Spell>, AssociationKey<?>, Object> dkm = new DoubleKeyMap<>(LinkedHashMap.class, HashMap.class);
    while (true) {
        if (token.isEmpty()) {
            return new ParseResult.Fail("Spell arguments may not end with comma or pipe in " + getTokenName() + ": " + sourceLine, context);
        }
        int commaLoc = token.indexOf(',');
        String name = commaLoc == -1 ? token : token.substring(0, commaLoc);
        CDOMReference<Spell> spell = context.getReferenceContext().getCDOMReference(Spell.class, name);
        dkm.put(spell, AssociationKey.CASTER_LEVEL, casterLevel);
        Formula timesFormula = FormulaFactory.getFormulaFor(times);
        if (!timesFormula.isValid()) {
            return new ParseResult.Fail("Times in " + getTokenName() + " was not valid: " + timesFormula.toString(), context);
        }
        dkm.put(spell, AssociationKey.TIMES_PER_UNIT, timesFormula);
        if (timeunit != null) {
            dkm.put(spell, AssociationKey.TIME_UNIT, timeunit);
        }
        dkm.put(spell, AssociationKey.SPELLBOOK, spellBook);
        if (commaLoc != -1) {
            dkm.put(spell, AssociationKey.DC_FORMULA, token.substring(commaLoc + 1));
        }
        if (!sep.hasNext()) {
            // No prereqs, so we're done
            finish(context, obj, dkm, null);
            return ParseResult.SUCCESS;
        }
        token = sep.next();
        if (looksLikeAPrerequisite(token)) {
            break;
        }
    }
    List<Prerequisite> prereqs = new ArrayList<>();
    while (true) {
        Prerequisite prereq = getPrerequisite(token);
        if (prereq == null) {
            return new ParseResult.Fail("   (Did you put spells after the " + "PRExxx tags in SPELLS:?)", context);
        }
        prereqs.add(prereq);
        if (!sep.hasNext()) {
            break;
        }
        token = sep.next();
    }
    finish(context, obj, dkm, prereqs);
    return ParseResult.SUCCESS;
}
Also used : AssociationKey(pcgen.cdom.enumeration.AssociationKey) ParseResult(pcgen.rules.persistence.token.ParseResult) ArrayList(java.util.ArrayList) Ungranted(pcgen.cdom.base.Ungranted) Spell(pcgen.core.spell.Spell) Formula(pcgen.base.formula.Formula) ParsingSeparator(pcgen.base.text.ParsingSeparator) CDOMObject(pcgen.cdom.base.CDOMObject) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) DoubleKeyMap(pcgen.base.util.DoubleKeyMap) CDOMReference(pcgen.cdom.base.CDOMReference) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 47 with Prerequisite

use of pcgen.core.prereq.Prerequisite in project pcgen by PCGen.

the class SpellknownLst 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);
    }
    String workingValue = value;
    List<Prerequisite> prereqs = new ArrayList<>();
    while (true) {
        int lastPipeLoc = workingValue.lastIndexOf('|');
        if (lastPipeLoc == -1) {
            return new ParseResult.Fail("Invalid " + getTokenName() + " not enough tokens: " + value, context);
        }
        String lastToken = workingValue.substring(lastPipeLoc + 1);
        if (looksLikeAPrerequisite(lastToken)) {
            workingValue = workingValue.substring(0, lastPipeLoc);
            Prerequisite prerequisite = getPrerequisite(lastToken);
            if (prerequisite == null) {
                return new ParseResult.Fail("Invalid prerequisite " + lastToken + " in " + getTokenName() + " tag: " + value, context);
            }
            prereqs.add(prerequisite);
        } else {
            break;
        }
    }
    StringTokenizer tok = new StringTokenizer(workingValue, Constants.PIPE);
    if (tok.countTokens() < 3) {
        return new ParseResult.Fail("Insufficient values in SPELLKNOWN tag: " + value, context);
    }
    // CLASS only
    String tagType = tok.nextToken();
    while (tok.hasMoreTokens()) {
        String tokString = tok.nextToken();
        String spellString = tok.nextToken();
        if (tagType.equalsIgnoreCase("CLASS")) {
            if (!subParse(context, obj, ClassSpellList.class, tokString, spellString, prereqs)) {
                return ParseResult.INTERNAL_ERROR;
            //return new ParseResult.Fail("  " + getTokenName()
            //		+ " error - entire token was " + value, context);
            }
        } else {
            return new ParseResult.Fail("First token of " + getTokenName() + " must be CLASS: " + value, context);
        }
    }
    return ParseResult.SUCCESS;
}
Also used : StringTokenizer(java.util.StringTokenizer) ArrayList(java.util.ArrayList) ClassSpellList(pcgen.cdom.list.ClassSpellList) Ungranted(pcgen.cdom.base.Ungranted) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 48 with Prerequisite

use of pcgen.core.prereq.Prerequisite in project pcgen by PCGen.

the class VisionLst 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 aTok = new StringTokenizer(value, Constants.PIPE);
    String visionString = aTok.nextToken();
    if (looksLikeAPrerequisite(visionString)) {
        return new ParseResult.Fail("Cannot have only PRExxx subtoken in " + getTokenName() + ": " + value, context);
    }
    ArrayList<AssociatedPrereqObject> edgeList = new ArrayList<>();
    boolean foundClear = false;
    while (true) {
        if (Constants.LST_DOT_CLEAR.equals(visionString)) {
            context.getListContext().removeAllFromList(getTokenName(), obj, Vision.VISIONLIST);
            foundClear = true;
        } else if (visionString.startsWith(Constants.LST_DOT_CLEAR_DOT)) {
            try {
                Vision vis = Vision.getVision(visionString.substring(7));
                context.getListContext().removeFromList(getTokenName(), obj, Vision.VISIONLIST, new CDOMDirectSingleRef<>(vis));
            } catch (IllegalArgumentException e) {
                ComplexParseResult cpr = new ComplexParseResult();
                cpr.addErrorMessage("Bad Syntax for Cleared Vision in " + getTokenName());
                cpr.addErrorMessage(e.getMessage());
                return cpr;
            }
            foundClear = true;
        } else if (looksLikeAPrerequisite(visionString)) {
            break;
        } else {
            try {
                Vision vision = Vision.getVision(visionString);
                AssociatedPrereqObject edge = context.getListContext().addToList(getTokenName(), obj, Vision.VISIONLIST, new CDOMDirectSingleRef<>(vision));
                edgeList.add(edge);
            } catch (IllegalArgumentException e) {
                ComplexParseResult cpr = new ComplexParseResult();
                cpr.addErrorMessage("Bad Syntax for Vision in " + getTokenName());
                cpr.addErrorMessage(e.getMessage());
                return cpr;
            }
        }
        if (!aTok.hasMoreTokens()) {
            return ParseResult.SUCCESS;
        }
        visionString = aTok.nextToken();
    }
    if (foundClear) {
        return new ParseResult.Fail("Cannot use PREREQs when using .CLEAR or .CLEAR. in " + getTokenName(), context);
    }
    while (true) {
        Prerequisite prereq = getPrerequisite(visionString);
        if (prereq == null) {
            return new ParseResult.Fail("   (Did you put vision after the " + "PRExxx tags in " + getTokenName() + ":?)", context);
        }
        for (AssociatedPrereqObject edge : edgeList) {
            edge.addPrerequisite(prereq);
        }
        if (!aTok.hasMoreTokens()) {
            break;
        }
        visionString = aTok.nextToken();
    }
    return ParseResult.SUCCESS;
}
Also used : CDOMDirectSingleRef(pcgen.cdom.reference.CDOMDirectSingleRef) ArrayList(java.util.ArrayList) ComplexParseResult(pcgen.rules.persistence.token.ComplexParseResult) Ungranted(pcgen.cdom.base.Ungranted) StringTokenizer(java.util.StringTokenizer) Vision(pcgen.core.Vision) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 49 with Prerequisite

use of pcgen.core.prereq.Prerequisite in project pcgen by PCGen.

the class AspectToken method parseAspect.

/**
	 * Parses the ASPECT tag into a Aspect object.
	 * 
	 * @param aspectDef
	 *            The LST tag
	 * @return A <tt>Aspect</tt> object
	 */
public Aspect parseAspect(final String name, final String aspectDef) {
    final StringTokenizer tok = new StringTokenizer(aspectDef, Constants.PIPE);
    String firstToken = tok.nextToken();
    /*if (PreParserFactory.isPreReqString(firstToken))
		{
			Logging.errorPrint("Invalid " + getTokenName() + ": " + name);
			Logging.errorPrint("  PRExxx can not be only value");
			return null;
		}*/
    final Aspect aspect = new Aspect(name, EntityEncoder.decode(firstToken));
    boolean isPre = false;
    while (tok.hasMoreTokens()) {
        final String token = tok.nextToken();
        if (PreParserFactory.isPreReqString(token)) {
            Prerequisite prereq = getPrerequisite(token);
            if (prereq == null) {
                Logging.errorPrint(getTokenName() + " had invalid prerequisite : " + token);
                return null;
            }
            aspect.addPrerequisite(prereq);
            isPre = true;
        } else {
            if (isPre) {
                Logging.errorPrint("Invalid " + getTokenName() + ": " + name);
                Logging.errorPrint("  PRExxx must be at the END of the Token");
                return null;
            }
            aspect.addVariable(token);
        }
    }
    return aspect;
}
Also used : StringTokenizer(java.util.StringTokenizer) Aspect(pcgen.cdom.helper.Aspect) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 50 with Prerequisite

use of pcgen.core.prereq.Prerequisite in project pcgen by PCGen.

the class BenefitToken method parseBenefit.

/**
	 * Parses the BENEFIT tag into a Description object.
	 * 
	 * @param aDesc
	 *            The LST tag
	 * @return A <tt>Description</tt> object
	 */
public Description parseBenefit(final String aDesc) {
    if (isEmpty(aDesc) || hasIllegalSeparator('|', aDesc)) {
        return null;
    }
    final StringTokenizer tok = new StringTokenizer(aDesc, Constants.PIPE);
    String firstToken = tok.nextToken();
    if (PreParserFactory.isPreReqString(firstToken)) {
        Logging.errorPrint("Invalid " + getTokenName() + ": " + aDesc);
        Logging.errorPrint("  PRExxx can not be only value");
        return null;
    }
    String ds = EntityEncoder.decode(firstToken);
    if (!StringUtil.hasBalancedParens(ds)) {
        Logging.log(Logging.LST_ERROR, getTokenName() + " encountered imbalanced Parenthesis: " + aDesc);
        return null;
    }
    Description desc = new Description(ds);
    boolean isPre = false;
    while (tok.hasMoreTokens()) {
        final String token = tok.nextToken();
        if (PreParserFactory.isPreReqString(token)) {
            Prerequisite prereq = getPrerequisite(token);
            if (prereq == null) {
                Logging.errorPrint(getTokenName() + " had invalid prerequisite : " + token);
                return null;
            }
            desc.addPrerequisite(prereq);
            isPre = true;
        } else {
            if (isPre) {
                Logging.errorPrint("Invalid " + getTokenName() + ": " + aDesc);
                Logging.errorPrint("  PRExxx must be at the END of the Token");
                return null;
            }
            desc.addVariable(token);
        }
    }
    return desc;
}
Also used : StringTokenizer(java.util.StringTokenizer) Description(pcgen.core.Description) Prerequisite(pcgen.core.prereq.Prerequisite)

Aggregations

Prerequisite (pcgen.core.prereq.Prerequisite)267 PersistenceLayerException (pcgen.persistence.PersistenceLayerException)62 Test (org.junit.Test)61 PrerequisiteOperator (pcgen.core.prereq.PrerequisiteOperator)50 StringTokenizer (java.util.StringTokenizer)36 ArrayList (java.util.ArrayList)35 StringWriter (java.io.StringWriter)19 AssociatedPrereqObject (pcgen.cdom.base.AssociatedPrereqObject)19 CDOMReference (pcgen.cdom.base.CDOMReference)18 ParseResult (pcgen.rules.persistence.token.ParseResult)18 BonusObj (pcgen.core.bonus.BonusObj)13 TreeSet (java.util.TreeSet)12 PreParserFactory (pcgen.persistence.lst.prereq.PreParserFactory)12 CDOMSingleRef (pcgen.cdom.reference.CDOMSingleRef)10 Domain (pcgen.core.Domain)10 QualifiedObject (pcgen.core.QualifiedObject)10 PrerequisiteWriterInterface (pcgen.persistence.lst.output.prereq.PrerequisiteWriterInterface)10 PrerequisiteWriter (pcgen.persistence.lst.output.prereq.PrerequisiteWriter)9 Ungranted (pcgen.cdom.base.Ungranted)8 PrerequisiteException (pcgen.core.prereq.PrerequisiteException)8