Search in sources :

Example 31 with CDOMReference

use of pcgen.cdom.base.CDOMReference in project pcgen by PCGen.

the class ClassSkillsLevelToken method parseNonEmptyToken.

@Override
protected ParseResult parseNonEmptyToken(LoadContext context, PCClassLevel obj, String value) {
    ParsingSeparator sep = new ParsingSeparator(value, '|');
    sep.addGroupingPair('[', ']');
    sep.addGroupingPair('(', ')');
    String activeValue = sep.next();
    Formula count;
    if (!sep.hasNext()) {
        count = FormulaFactory.ONE;
    } else {
        count = FormulaFactory.getFormulaFor(activeValue);
        if (!count.isValid()) {
            return new ParseResult.Fail("Count in " + getTokenName() + " was not valid: " + count.toString(), context);
        }
        if (count.isStatic() && count.resolveStatic().doubleValue() <= 0) {
            return new ParseResult.Fail("Count in " + getFullName() + " must be > 0", context);
        }
        activeValue = sep.next();
    }
    if (sep.hasNext()) {
        return new ParseResult.Fail(getFullName() + " had too many pipe separated items: " + value, context);
    }
    ParseResult pr = checkSeparatorsAndNonEmpty(',', activeValue);
    if (!pr.passed()) {
        return pr;
    }
    List<CDOMReference<Skill>> refs = new ArrayList<>();
    StringTokenizer tok = new StringTokenizer(activeValue, Constants.COMMA);
    CDOMGroupRef<Skill> allRef = context.getReferenceContext().getCDOMAllReference(SKILL_CLASS);
    Integer autoRank = null;
    while (tok.hasMoreTokens()) {
        String tokText = tok.nextToken();
        if (Constants.LST_ALL.equals(tokText) || Constants.LST_ANY.equals(tokText)) {
            refs.add(allRef);
        } else {
            if (Constants.LST_UNTRAINED.equals(tokText)) {
                ObjectMatchingReference<Skill, Boolean> omr = new ObjectMatchingReference<>(tokText, SKILL_CLASS, allRef, ObjectKey.USE_UNTRAINED, Boolean.TRUE);
                omr.returnIncludesNulls(true);
                refs.add(omr);
            } else if (Constants.LST_TRAINED.equals(tokText)) {
                refs.add(new ObjectMatchingReference<>(tokText, SKILL_CLASS, allRef, ObjectKey.USE_UNTRAINED, Boolean.FALSE));
            } else if (Constants.LST_EXCLUSIVE.equals(tokText)) {
                refs.add(new ObjectMatchingReference<>(tokText, SKILL_CLASS, allRef, ObjectKey.EXCLUSIVE, Boolean.TRUE));
            } else if (Constants.LST_NONEXCLUSIVE.equals(tokText) || Constants.LST_CROSS_CLASS.equals(tokText)) {
                ObjectMatchingReference<Skill, Boolean> omr = new ObjectMatchingReference<>(tokText, SKILL_CLASS, allRef, ObjectKey.EXCLUSIVE, Boolean.FALSE);
                omr.returnIncludesNulls(true);
                refs.add(omr);
            } else if (tokText.startsWith("AUTORANK=")) {
                if (autoRank != null) {
                    return new ParseResult.Fail("Cannot have two " + "AUTORANK= items in " + getFullName() + ": " + value, context);
                }
                String rankString = tokText.substring(9);
                try {
                    autoRank = Integer.decode(rankString);
                    if (autoRank <= 0) {
                        return new ParseResult.Fail("Expected AUTORANK= to be" + " greater than zero, found: " + autoRank, context);
                    }
                } catch (NumberFormatException e) {
                    return new ParseResult.Fail("Expected AUTORANK= to have" + " an integer value, found: " + rankString, context);
                }
            } else {
                CDOMReference<Skill> skref = TokenUtilities.getTypeOrPrimitive(context, SKILL_CLASS, tokText);
                if (skref == null) {
                    return new ParseResult.Fail("  Error was encountered while parsing " + getFullName() + ": " + value + " had an invalid reference: " + tokText, context);
                }
                refs.add(skref);
            }
        }
    }
    if (refs.isEmpty()) {
        return new ParseResult.Fail("Non-sensical " + getFullName() + ": Contains no skill reference: " + value, context);
    }
    ReferenceChoiceSet<Skill> rcs = new ReferenceChoiceSet<>(refs);
    if (!rcs.getGroupingState().isValid()) {
        return new ParseResult.Fail("Non-sensical " + getFullName() + ": Contains ANY and a specific reference: " + value, context);
    }
    ChoiceSet<Skill> cs = new ChoiceSet<>(getTokenName(), rcs, true);
    PersistentTransitionChoice<Skill> tc = new ConcretePersistentTransitionChoice<>(cs, count);
    // TODO This is a hack, to get this to work pre-CDOM
    PCClass parent = (PCClass) obj.get(ObjectKey.TOKEN_PARENT);
    ClassSkillChoiceActor actor = new ClassSkillChoiceActor(parent, autoRank);
    tc.setChoiceActor(actor);
    context.getObjectContext().addToList(obj, ListKey.ADD, tc);
    return ParseResult.SUCCESS;
}
Also used : ArrayList(java.util.ArrayList) ConcretePersistentTransitionChoice(pcgen.cdom.base.ConcretePersistentTransitionChoice) Formula(pcgen.base.formula.Formula) ObjectMatchingReference(pcgen.cdom.reference.ObjectMatchingReference) ParseResult(pcgen.rules.persistence.token.ParseResult) ReferenceChoiceSet(pcgen.cdom.choiceset.ReferenceChoiceSet) ChoiceSet(pcgen.cdom.base.ChoiceSet) PCClass(pcgen.core.PCClass) StringTokenizer(java.util.StringTokenizer) Skill(pcgen.core.Skill) ParsingSeparator(pcgen.base.text.ParsingSeparator) ClassSkillChoiceActor(pcgen.cdom.helper.ClassSkillChoiceActor) CDOMReference(pcgen.cdom.base.CDOMReference) ReferenceChoiceSet(pcgen.cdom.choiceset.ReferenceChoiceSet)

Example 32 with CDOMReference

use of pcgen.cdom.base.CDOMReference in project pcgen by PCGen.

the class DomainsToken method unparse.

@Override
public String[] unparse(LoadContext context, Spell spell) {
    DoubleKeyMapToList<Prerequisite, Integer, CDOMReference<DomainSpellList>> dkmtl = new DoubleKeyMapToList<>();
    List<String> list = new ArrayList<>();
    Changes<CDOMReference<DomainSpellList>> masterChanges = context.getListContext().getMasterListChanges(getTokenName(), spell, SPELLLIST_CLASS);
    if (masterChanges.includesGlobalClear()) {
        list.add(Constants.LST_DOT_CLEAR_ALL);
    }
    if (masterChanges.hasRemovedItems()) {
        for (CDOMReference<DomainSpellList> swl : masterChanges.getRemoved()) {
            AssociatedChanges<Spell> changes = context.getListContext().getChangesInMasterList(getTokenName(), spell, swl);
            MapToList<Spell, AssociatedPrereqObject> map = changes.getRemovedAssociations();
            if (map != null && !map.isEmpty()) {
                for (Spell added : map.getKeySet()) {
                    if (!spell.getLSTformat().equals(added.getLSTformat())) {
                        context.addWriteMessage("Spell " + getTokenName() + " token cannot remove another Spell " + "(must only remove itself)");
                        return null;
                    }
                    for (AssociatedPrereqObject assoc : map.getListFor(added)) {
                        List<Prerequisite> prereqs = assoc.getPrerequisiteList();
                        if (prereqs != null && !prereqs.isEmpty()) {
                            context.addWriteMessage("Incoming Remove " + "Edge to " + spell.getKeyName() + " had a " + "Prerequisite: " + prereqs.size());
                            return null;
                        }
                        dkmtl.addToListFor(null, -1, swl);
                    }
                }
            }
        }
    }
    for (CDOMReference<DomainSpellList> swl : masterChanges.getAdded()) {
        AssociatedChanges<Spell> changes = context.getListContext().getChangesInMasterList(getTokenName(), spell, swl);
        Collection<Spell> removedItems = changes.getRemoved();
        if (removedItems != null && !removedItems.isEmpty() || changes.includesGlobalClear()) {
            context.addWriteMessage(getTokenName() + " does not support .CLEAR.");
            return null;
        }
        MapToList<Spell, AssociatedPrereqObject> map = changes.getAddedAssociations();
        if (map != null && !map.isEmpty()) {
            for (Spell added : map.getKeySet()) {
                if (!spell.getLSTformat().equals(added.getLSTformat())) {
                    context.addWriteMessage("Spell " + getTokenName() + " token cannot allow another Spell " + "(must only allow itself)");
                    return null;
                }
                for (AssociatedPrereqObject assoc : map.getListFor(added)) {
                    List<Prerequisite> prereqs = assoc.getPrerequisiteList();
                    Prerequisite prereq;
                    if (prereqs == null || prereqs.isEmpty()) {
                        prereq = null;
                    } else if (prereqs.size() == 1) {
                        prereq = prereqs.get(0);
                    } else {
                        context.addWriteMessage("Incoming Edge to " + spell.getKeyName() + " had more than one " + "Prerequisite: " + prereqs.size());
                        return null;
                    }
                    Integer level = assoc.getAssociation(AssociationKey.SPELL_LEVEL);
                    if (level == null) {
                        context.addWriteMessage("Incoming Allows Edge to " + spell.getKeyName() + " had no Spell Level defined");
                        return null;
                    }
                    if (level.intValue() < 0) {
                        context.addWriteMessage("Incoming Allows Edge to " + spell.getKeyName() + " had invalid Level: " + level + ". Must be >= 0.");
                        return null;
                    }
                    dkmtl.addToListFor(prereq, level, swl);
                }
            }
        }
    }
    if (dkmtl.isEmpty()) {
        if (list.isEmpty()) {
            // Legal if no DOMAINS was present in the Spell
            return null;
        } else {
            return list.toArray(new String[list.size()]);
        }
    }
    PrerequisiteWriter prereqWriter = new PrerequisiteWriter();
    SortedSet<CDOMReference<DomainSpellList>> set = new TreeSet<>(ReferenceUtilities.REFERENCE_SORTER);
    SortedSet<Integer> levelSet = new TreeSet<>();
    for (Prerequisite prereq : dkmtl.getKeySet()) {
        StringBuilder sb = new StringBuilder();
        boolean needPipe = false;
        levelSet.clear();
        levelSet.addAll(dkmtl.getSecondaryKeySet(prereq));
        for (Integer i : levelSet) {
            set.clear();
            set.addAll(dkmtl.getListFor(prereq, i));
            if (needPipe) {
                sb.append(Constants.PIPE);
            }
            sb.append(ReferenceUtilities.joinLstFormat(set, Constants.COMMA));
            sb.append('=').append(i);
            needPipe = true;
        }
        if (prereq != null) {
            sb.append('[');
            StringWriter swriter = new StringWriter();
            try {
                prereqWriter.write(swriter, prereq);
            } catch (PersistenceLayerException e) {
                context.addWriteMessage("Error writing Prerequisite: " + e);
                return null;
            }
            sb.append(swriter.toString());
            sb.append(']');
        }
        list.add(sb.toString());
    }
    return list.toArray(new String[list.size()]);
}
Also used : PrerequisiteWriter(pcgen.persistence.lst.output.prereq.PrerequisiteWriter) ArrayList(java.util.ArrayList) Spell(pcgen.core.spell.Spell) StringWriter(java.io.StringWriter) TreeSet(java.util.TreeSet) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) DoubleKeyMapToList(pcgen.base.util.DoubleKeyMapToList) DomainSpellList(pcgen.cdom.list.DomainSpellList) PersistenceLayerException(pcgen.persistence.PersistenceLayerException) CDOMReference(pcgen.cdom.base.CDOMReference) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 33 with CDOMReference

use of pcgen.cdom.base.CDOMReference in project pcgen by PCGen.

the class ClassesToken method unparse.

@Override
public String[] unparse(LoadContext context, Spell spell) {
    DoubleKeyMapToList<Prerequisite, Integer, CDOMReference<ClassSpellList>> dkmtl = new DoubleKeyMapToList<>();
    List<String> list = new ArrayList<>();
    Changes<CDOMReference<ClassSpellList>> masterChanges = context.getListContext().getMasterListChanges(getTokenName(), spell, SPELLLIST_CLASS);
    if (masterChanges.includesGlobalClear()) {
        list.add(Constants.LST_DOT_CLEAR_ALL);
    }
    if (masterChanges.hasRemovedItems()) {
        for (CDOMReference<ClassSpellList> swl : masterChanges.getRemoved()) {
            AssociatedChanges<Spell> changes = context.getListContext().getChangesInMasterList(getTokenName(), spell, swl);
            MapToList<Spell, AssociatedPrereqObject> map = changes.getRemovedAssociations();
            if (map != null && !map.isEmpty()) {
                for (Spell added : map.getKeySet()) {
                    if (!spell.getLSTformat().equals(added.getLSTformat())) {
                        context.addWriteMessage("Spell " + getTokenName() + " token cannot remove another Spell " + "(must only remove itself)");
                        return null;
                    }
                    for (AssociatedPrereqObject assoc : map.getListFor(added)) {
                        List<Prerequisite> prereqs = assoc.getPrerequisiteList();
                        if (prereqs != null && !prereqs.isEmpty()) {
                            context.addWriteMessage("Incoming Remove " + "Edge to " + spell.getKeyName() + " had a " + "Prerequisite: " + prereqs.size());
                            return null;
                        }
                        dkmtl.addToListFor(null, -1, swl);
                    }
                }
            }
        }
    }
    for (CDOMReference<ClassSpellList> swl : masterChanges.getAdded()) {
        AssociatedChanges<Spell> changes = context.getListContext().getChangesInMasterList(getTokenName(), spell, swl);
        Collection<Spell> removedItems = changes.getRemoved();
        if (removedItems != null && !removedItems.isEmpty() || changes.includesGlobalClear()) {
            context.addWriteMessage(getTokenName() + " does not support .CLEAR.");
            return null;
        }
        MapToList<Spell, AssociatedPrereqObject> map = changes.getAddedAssociations();
        if (map != null && !map.isEmpty()) {
            for (Spell added : map.getKeySet()) {
                if (!spell.getLSTformat().equals(added.getLSTformat())) {
                    context.addWriteMessage("Spell " + getTokenName() + " token cannot allow another Spell " + "(must only allow itself)");
                    return null;
                }
                for (AssociatedPrereqObject assoc : map.getListFor(added)) {
                    List<Prerequisite> prereqs = assoc.getPrerequisiteList();
                    Prerequisite prereq;
                    if (prereqs == null || prereqs.isEmpty()) {
                        prereq = null;
                    } else if (prereqs.size() == 1) {
                        prereq = prereqs.get(0);
                    } else {
                        context.addWriteMessage("Incoming Edge to " + spell.getKeyName() + " had more than one " + "Prerequisite: " + prereqs.size());
                        return null;
                    }
                    Integer level = assoc.getAssociation(AssociationKey.SPELL_LEVEL);
                    if (level == null) {
                        context.addWriteMessage("Incoming Allows Edge to " + spell.getKeyName() + " had no Spell Level defined");
                        return null;
                    }
                    if (level.intValue() < 0) {
                        context.addWriteMessage("Incoming Allows Edge to " + spell.getKeyName() + " had invalid Level: " + level + ". Must be >= 0.");
                        return null;
                    }
                    dkmtl.addToListFor(prereq, level, swl);
                }
            }
        }
    }
    if (dkmtl.isEmpty()) {
        if (list.isEmpty()) {
            // Legal if no CLASSES was present in the Spell
            return null;
        } else {
            return list.toArray(new String[list.size()]);
        }
    }
    PrerequisiteWriter prereqWriter = new PrerequisiteWriter();
    SortedSet<CDOMReference<ClassSpellList>> set = new TreeSet<>(ReferenceUtilities.REFERENCE_SORTER);
    SortedSet<Integer> levelSet = new TreeSet<>();
    for (Prerequisite prereq : dkmtl.getKeySet()) {
        StringBuilder sb = new StringBuilder();
        boolean needPipe = false;
        levelSet.clear();
        levelSet.addAll(dkmtl.getSecondaryKeySet(prereq));
        for (Integer i : levelSet) {
            set.clear();
            set.addAll(dkmtl.getListFor(prereq, i));
            if (needPipe) {
                sb.append(Constants.PIPE);
            }
            sb.append(ReferenceUtilities.joinLstFormat(set, Constants.COMMA));
            sb.append('=').append(i);
            needPipe = true;
        }
        if (prereq != null) {
            sb.append('[');
            StringWriter swriter = new StringWriter();
            try {
                prereqWriter.write(swriter, prereq);
            } catch (PersistenceLayerException e) {
                context.addWriteMessage("Error writing Prerequisite: " + e);
                return null;
            }
            sb.append(swriter.toString());
            sb.append(']');
        }
        list.add(sb.toString());
    }
    return list.toArray(new String[list.size()]);
}
Also used : PrerequisiteWriter(pcgen.persistence.lst.output.prereq.PrerequisiteWriter) ArrayList(java.util.ArrayList) Spell(pcgen.core.spell.Spell) StringWriter(java.io.StringWriter) TreeSet(java.util.TreeSet) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) ClassSpellList(pcgen.cdom.list.ClassSpellList) DoubleKeyMapToList(pcgen.base.util.DoubleKeyMapToList) PersistenceLayerException(pcgen.persistence.PersistenceLayerException) CDOMReference(pcgen.cdom.base.CDOMReference) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 34 with CDOMReference

use of pcgen.cdom.base.CDOMReference in project pcgen by PCGen.

the class LangbonusToken method parseTokenWithSeparator.

@Override
protected ParseResult parseTokenWithSeparator(LoadContext context, PCTemplate template, String value) {
    StringTokenizer tok = new StringTokenizer(value, Constants.COMMA);
    boolean foundAny = false;
    boolean foundOther = false;
    boolean firstToken = true;
    while (tok.hasMoreTokens()) {
        String tokText = tok.nextToken();
        if (Constants.LST_DOT_CLEAR.equals(tokText)) {
            if (!firstToken) {
                return new ParseResult.Fail("Non-sensical situation was " + "encountered while parsing " + getTokenName() + ": When used, .CLEAR must be the first argument", context);
            }
            context.getListContext().removeAllFromList(getTokenName(), template, Language.STARTING_LIST);
        } else if (tokText.startsWith(Constants.LST_DOT_CLEAR_DOT)) {
            String clearText = tokText.substring(7);
            CDOMReference<Language> lang = TokenUtilities.getReference(context, LANGUAGE_CLASS, clearText);
            if (lang == null) {
                return new ParseResult.Fail("  Error was encountered while parsing " + getTokenName() + ": " + value + " had an invalid .CLEAR. reference: " + clearText, context);
            }
            context.getListContext().removeFromList(getTokenName(), template, Language.STARTING_LIST, lang);
        } else {
            /*
				 * Note this is done one-by-one, because .CLEAR. token type
				 * needs to be able to perform the unlink. That could be
				 * changed, but the increase in complexity isn't worth it.
				 * (Changing it to a grouping object that didn't place links in
				 * the graph would also make it harder to trace the source of
				 * class skills, etc.)
				 */
            CDOMReference<Language> lang;
            if (Constants.LST_ALL.equals(tokText)) {
                foundAny = true;
                lang = context.getReferenceContext().getCDOMAllReference(LANGUAGE_CLASS);
            } else {
                foundOther = true;
                lang = TokenUtilities.getTypeOrPrimitive(context, LANGUAGE_CLASS, tokText);
            }
            if (lang == null) {
                return new ParseResult.Fail("  Error was encountered while parsing " + getTokenName() + ": " + value + " had an invalid reference: " + tokText, context);
            }
            context.getListContext().addToList(getTokenName(), template, Language.STARTING_LIST, lang);
        }
        firstToken = false;
    }
    if (foundAny && foundOther) {
        return new ParseResult.Fail("Non-sensical " + getTokenName() + ": Contains ANY and a specific reference: " + value, context);
    }
    return ParseResult.SUCCESS;
}
Also used : StringTokenizer(java.util.StringTokenizer) ParseResult(pcgen.rules.persistence.token.ParseResult) CDOMReference(pcgen.cdom.base.CDOMReference)

Example 35 with CDOMReference

use of pcgen.cdom.base.CDOMReference in project pcgen by PCGen.

the class PCClassTest method testGetPCCText.

/**
	 * Test the processing of getPCCText to ensure that it correctly produces
	 * an LST representation of an object and that the LST can then be reloaded
	 * to recrete the object.
	 *
	 * @throws PersistenceLayerException
	 */
public void testGetPCCText() throws PersistenceLayerException {
    FactKey.getConstant("Abb", new StringManager());
    // Test a basic class
    String classPCCText = humanoidClass.getPCCText();
    assertNotNull("PCC Text for race should not be null", classPCCText);
    CampaignSourceEntry source;
    try {
        source = new CampaignSourceEntry(new Campaign(), new URI("file:/" + getClass().getName() + ".java"));
    } catch (URISyntaxException e) {
        throw new UnreachableError(e);
    }
    PCClass reconstClass = null;
    System.out.println("Got text:" + classPCCText);
    reconstClass = parsePCClassText(classPCCText, source);
    assertEquals("getPCCText should be the same after being encoded and reloaded", classPCCText, reconstClass.getPCCText());
    assertEquals("Class abbrev was not restored after saving and reloading.", humanoidClass.getAbbrev(), reconstClass.getAbbrev());
    // Test a class with some innate spells
    String b = "1" + "\t" + "SPELLS:" + "Humanoid|TIMES=1|CASTERLEVEL=var(\"TCL\")|Create undead,11+WIS";
    PCClassLoader classLoader = new PCClassLoader();
    classLoader.parseLine(Globals.getContext(), humanoidClass, b, source);
    classPCCText = humanoidClass.getPCCText();
    assertNotNull("PCC Text for race should not be null", classPCCText);
    reconstClass = null;
    System.out.println("Got text:" + classPCCText);
    reconstClass = parsePCClassText(classPCCText, source);
    assertEquals("getPCCText should be the same after being encoded and reloaded", classPCCText, reconstClass.getPCCText());
    assertEquals("Class abbrev was not restored after saving and reloading.", humanoidClass.getAbbrev(), reconstClass.getAbbrev());
    Collection<CDOMReference<Spell>> startSpells = humanoidClass.getOriginalClassLevel(1).getListMods(Spell.SPELLS);
    Collection<CDOMReference<Spell>> reconstSpells = reconstClass.getOriginalClassLevel(1).getListMods(Spell.SPELLS);
    assertEquals("All spell should have been reconstituted.", startSpells.size(), reconstSpells.size());
    assertEquals("Spell names should been preserved.", startSpells, reconstSpells);
}
Also used : CampaignSourceEntry(pcgen.persistence.lst.CampaignSourceEntry) PCClassLoader(pcgen.persistence.lst.PCClassLoader) URISyntaxException(java.net.URISyntaxException) UnreachableError(pcgen.base.lang.UnreachableError) URI(java.net.URI) CDOMReference(pcgen.cdom.base.CDOMReference) StringManager(pcgen.base.format.StringManager)

Aggregations

CDOMReference (pcgen.cdom.base.CDOMReference)125 ArrayList (java.util.ArrayList)57 StringTokenizer (java.util.StringTokenizer)40 AssociatedPrereqObject (pcgen.cdom.base.AssociatedPrereqObject)35 ParseResult (pcgen.rules.persistence.token.ParseResult)30 Skill (pcgen.core.Skill)24 ChoiceSet (pcgen.cdom.base.ChoiceSet)22 ConcretePersistentTransitionChoice (pcgen.cdom.base.ConcretePersistentTransitionChoice)21 ReferenceChoiceSet (pcgen.cdom.choiceset.ReferenceChoiceSet)19 Prerequisite (pcgen.core.prereq.Prerequisite)18 Formula (pcgen.base.formula.Formula)16 CDOMObject (pcgen.cdom.base.CDOMObject)15 Spell (pcgen.core.spell.Spell)15 TreeSet (java.util.TreeSet)14 Test (org.junit.Test)14 ClassSkillChoiceActor (pcgen.cdom.helper.ClassSkillChoiceActor)12 CharID (pcgen.cdom.enumeration.CharID)11 ObjectMatchingReference (pcgen.cdom.reference.ObjectMatchingReference)11 ParsingSeparator (pcgen.base.text.ParsingSeparator)10 CDOMList (pcgen.cdom.base.CDOMList)10