/* * Copyright 2014 (C) Tom Parker <thpr@users.sourceforge.net> * * 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 */ package pcgen.rules.persistence; import java.net.URI; import java.util.HashMap; import java.util.Map; import pcgen.cdom.base.Loadable; import pcgen.cdom.content.DefaultVarValue; import pcgen.cdom.content.UserFunction; import pcgen.cdom.content.fact.FactDefinition; import pcgen.cdom.content.factset.FactSetDefinition; import pcgen.cdom.inst.DynamicCategory; import pcgen.persistence.PersistenceLayerException; import pcgen.persistence.SystemLoader; import pcgen.persistence.lst.LstLineFileLoader; import pcgen.rules.context.AbstractReferenceContext; import pcgen.rules.context.LoadContext; import pcgen.util.Logging; /** * A CDOMControlLoader is a loader that processes the Data Definitions * (initially FACT/FACTSET) */ public class CDOMControlLoader extends LstLineFileLoader { private final Map<String, CDOMSubLineLoader<?>> loadMap = new HashMap<>(); public CDOMControlLoader() { //CONSIDER better way to load these? addLineLoader(new CDOMSubLineLoader<>("FACTDEF", FactDefinition.class)); addLineLoader(new CDOMSubLineLoader<>("FACTSETDEF", FactSetDefinition.class)); addLineLoader(new CDOMSubLineLoader<>("DEFAULTVARIABLEVALUE", DefaultVarValue.class)); addLineLoader(new CDOMSubLineLoader<>("FUNCTION", UserFunction.class)); addLineLoader(new CDOMSubLineLoader<>("DYNAMICSCOPE", DynamicCategory.class)); } private void addLineLoader(CDOMSubLineLoader<?> loader) { if (loader == null) { throw new IllegalArgumentException("Cannot add null loader to Control Loader"); } String prefix = loader.getPrefix(); if (loadMap.containsKey(prefix)) { throw new IllegalArgumentException("Cannot add a second loader for prefix: " + prefix); } loadMap.put(loader.getPrefix(), loader); } private boolean parseSubLine(LoadContext context, String val, URI source) { int sepLoc = val.indexOf('\t'); String firstToken = (sepLoc == -1) ? val : val.substring(0, sepLoc); int colonLoc = firstToken.indexOf(':'); if (colonLoc == -1) { Logging.addParseMessage(Logging.LST_ERROR, "Unsure what to do with line without " + "a colon in first token: " + val + " in file: " + source); return false; } String prefix = firstToken.substring(0, colonLoc); CDOMSubLineLoader<?> loader = loadMap.get(prefix); if (loader == null) { Logging.addParseMessage(Logging.LST_ERROR, "Unsure what to do with line with prefix: " + prefix + ". Line was: " + val + " in file: " + source); return false; } try { if (!subParse(context, loader, val)) { return false; } } catch (PersistenceLayerException ple) { Logging.errorPrint("Exception in Load: ", ple); return false; } return true; } private <CC extends Loadable> boolean subParse(LoadContext context, CDOMSubLineLoader<CC> loader, String line) throws PersistenceLayerException { int tabLoc = line.indexOf(SystemLoader.TAB_DELIM); String lineIdentifier; if (tabLoc == -1) { lineIdentifier = line; } else { lineIdentifier = line.substring(0, tabLoc); } int colonLoc = lineIdentifier.indexOf(':'); if (colonLoc == -1) { Logging.errorPrint("First token on line had no colon: " + line, context); return false; } String name = lineIdentifier.substring(colonLoc + 1); if ((name == null) || name.isEmpty()) { Logging.errorPrint("First token on line had no content: " + line, context); return false; } AbstractReferenceContext refContext = context.getReferenceContext(); CC obj = refContext.constructNowIfNecessary(loader.getLoadedClass(), name.replace('|', ' ').replace(',', ' ')); return loader.parseLine(context, obj, line); } @Override public void parseLine(LoadContext context, String inputLine, URI sourceURI) throws PersistenceLayerException { context.rollback(); if (parseSubLine(context, inputLine, sourceURI)) { Logging.clearParseMessages(); context.commit(); } else { context.rollback(); Logging.replayParsedMessages(); Logging.clearParseMessages(); } } }