/* * CampaignLoader.java * Copyright 2001 (C) Bryan McRoberts <merton_monk@yahoo.com> * * 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 * * Created on February 22, 2002, 10:29 PM * * Current Ver: $Revision$ * */ package pcgen.persistence.lst; import java.net.URI; import java.util.ArrayList; import java.util.List; import pcgen.cdom.base.Constants; import pcgen.cdom.enumeration.ListKey; import pcgen.cdom.enumeration.SourceFormat; import pcgen.core.Campaign; import pcgen.core.Globals; import pcgen.core.prereq.Prerequisite; import pcgen.io.PCGFile; import pcgen.persistence.PersistenceLayerException; import pcgen.persistence.lst.output.prereq.PrerequisiteWriter; import pcgen.rules.context.LoadContext; import pcgen.util.Logging; /** * @author David Rice <david-pcgen@jcuz.com> */ public class CampaignLoader extends LstLineFileLoader { /** * The {@link pcgen.core.Campaign Campaign} being loaded by {@link #loadCampaignLstFile(java.net.URI) loadCampaignLstFile}. */ private Campaign campaign = null; private final List<Campaign> inittedCampaigns = new ArrayList<>(); public static final ListKey[] OTHER_FILE_LISTKEY = { ListKey.FILE_LST_EXCLUDE, ListKey.FILE_COVER}; public static final ListKey[] OBJECT_FILE_LISTKEY = {ListKey.FILE_RACE, ListKey.FILE_CLASS, ListKey.FILE_COMPANION_MOD, ListKey.FILE_SKILL, ListKey.FILE_ABILITY_CATEGORY, ListKey.FILE_ABILITY, ListKey.FILE_FEAT, ListKey.FILE_DEITY, ListKey.FILE_DOMAIN, ListKey.FILE_ARMOR_PROF, ListKey.FILE_SHIELD_PROF, ListKey.FILE_WEAPON_PROF, ListKey.FILE_EQUIP, ListKey.FILE_SPELL, ListKey.FILE_LANGUAGE, ListKey.FILE_TEMPLATE, ListKey.FILE_EQUIP_MOD, ListKey.FILE_KIT, ListKey.FILE_BIO_SET, ListKey.FILE_ALIGNMENT, ListKey.FILE_STAT, ListKey.FILE_SAVE, ListKey.FILE_SIZE, ListKey.FILE_DATACTRL, ListKey.FILE_VARIABLE, ListKey.FILE_DYNAMIC, ListKey.FILE_DATATABLE, ListKey.FILE_GLOBALMOD}; /** * This method initializes any campaigns that include other campaigns, * avoiding an infinite loop in the event of recursive (for example * interdependent campaigns) * * This specific overloading will recurse down the given * campaign object dependency tree, then return * * @param baseCampaign Campaign object that may or may not require * other campaigns */ public void initRecursivePccFiles(Campaign baseCampaign) //throws PersistenceLayerException { if (baseCampaign == null || inittedCampaigns.contains(baseCampaign)) { return; } inittedCampaigns.add(baseCampaign); // Add all sub-files to the base campaign, regardless of exclusions for (CampaignSourceEntry cse : baseCampaign.getSafeListFor(ListKey.FILE_PCC)) { URI fName = cse.getURI(); if (PCGFile.isPCGenCampaignFile(fName)) { // Find referenced campaign if loaded Campaign globalSubCampaign = Globals.getCampaignByURI(fName, false); // If this campaign has not already been loaded, do so if (globalSubCampaign == null) { try { loadCampaignLstFile(fName); globalSubCampaign = Globals.getCampaignByURI(fName, false); } catch (PersistenceLayerException e) { Logging.errorPrint("Recursive init failed on file " + fName, e); } } // add all sub-subs etc to the list initRecursivePccFiles(globalSubCampaign); // add subfile to the parent campaign for loading initRecursivePccFiles(baseCampaign, globalSubCampaign); } } } /** * This method adds all files from the included campaigns to this one. * It then strips out the excluded files via a call to stripLstExcludes. * * @param baseCampaign Campaign that includes another campaign * @param subCampaign Campaign included by the baseCampaign */ private void initRecursivePccFiles(Campaign baseCampaign, Campaign subCampaign) { if (subCampaign == null) { return; } for (ListKey<?> lk : OBJECT_FILE_LISTKEY) { addToBaseCampaign(baseCampaign, subCampaign, lk); } for (ListKey<?> lk : OTHER_FILE_LISTKEY) { addToBaseCampaign(baseCampaign, subCampaign, lk); } } private <T> void addToBaseCampaign(Campaign baseCampaign, Campaign subCampaign, ListKey<T> lk) { baseCampaign.addAllToListFor(lk, subCampaign.getSafeListFor(lk)); } /** * Parses a campaign LST file and adds it to the Global container if not already added. * @param filePath The file path to load. * @throws PersistenceLayerException */ public void loadCampaignLstFile(URI filePath) throws PersistenceLayerException { // Instantiate a Campaign, which will automatically establish a LoadContext campaign = new Campaign(); campaign.setSourceURI(filePath); // Parses the data in the referenced URI and loads it into a LoadContext; // this quickly goes to the parseLine method below super.loadLstFile(campaign.getCampaignContext(), filePath); // Make sure this campaign has not already been added to the Global container if (Globals.getCampaignByURI(campaign.getSourceURI(), false) == null) { // Check the campaign's prerequisites, generating errors if any are not met but proceeding validatePrereqs(campaign.getPrerequisiteList()); List<String> copyright = campaign.getListFor(ListKey.SECTION_15); if (copyright != null) { StringBuilder sec15 = Globals.getSection15(); sec15.append("<br><b>Source Material:</b>"); sec15.append(SourceFormat.getFormattedString(campaign, SourceFormat.LONG, true)); sec15.append("<br>"); sec15.append("<b>Section 15 Entry in Source Material:</b><br>"); for (String license : copyright) { sec15.append(license).append("<br>"); } } // Adds this campaign to the Global container. Globals.addCampaign(campaign); } } @Override public void parseLine(LoadContext context, String inputLine, URI sourceURI) throws PersistenceLayerException { LstUtils.processToken(context, campaign, sourceURI, inputLine); } /** * Check that all prerequisites specified in the PCC file are * supported. Any unsupported prereqs will be reported as LST * errors. This is a recursive function allowing it to * check nested prereqs. * * @param prereqList The prerequisites to be checked. */ private void validatePrereqs(List<Prerequisite> prereqList) { if (prereqList == null || prereqList.isEmpty()) { return; } for (Prerequisite prereq : prereqList) { if (prereq.isCharacterRequired()) { final PrerequisiteWriter prereqWriter = new PrerequisiteWriter(); ArrayList<Prerequisite> displayList = new ArrayList<>(); displayList.add(prereq); String lstString = prereqWriter.getPrerequisiteString(displayList, Constants.TAB); Logging.log(Logging.LST_ERROR, "Prereq " + prereq.getKind() + " is not supported in PCC files. Prereq was " + lstString + " in " + campaign.getSourceURI() + ". Prereq will be ignored."); } else { validatePrereqs(prereq.getPrerequisites()); } } } }