/* * PreParserFactory.java * * Copyright 2003 (C) Chris Ward <frugal@purplewombat.co.uk> * * 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 18-Dec-2003 * * Current Ver: $Revision$ * * * */ package pcgen.persistence.lst.prereq; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import pcgen.core.prereq.Prerequisite; import pcgen.core.prereq.PrerequisiteOperator; import pcgen.persistence.PersistenceLayerException; import pcgen.system.PluginLoader; import pcgen.util.Logging; /** * @author wardc * */ public final class PreParserFactory implements PluginLoader { private static PreParserFactory instance = null; private static Map<String, PrerequisiteParserInterface> parserLookup = new HashMap<>(); private PreParserFactory() throws PersistenceLayerException { register(new PreMultParser()); } @Override public void loadPlugin(Class<?> clazz) throws Exception { register((PrerequisiteParserInterface) clazz.newInstance()); } @SuppressWarnings("unchecked") @Override public Class[] getPluginClasses() { return new Class[]{PrerequisiteParserInterface.class}; } /** * @return Returns the instance. * @throws PersistenceLayerException */ public static PreParserFactory getInstance() throws PersistenceLayerException { if (instance == null) { instance = new PreParserFactory(); } return instance; } public PrerequisiteParserInterface getParser(String kind) { return parserLookup.get(kind.toLowerCase()); } public static void register(PrerequisiteParserInterface testClass) throws PersistenceLayerException { String[] kindsHandled = testClass.kindsHandled(); for (int i = 0; i < kindsHandled.length; i++) { Object test = parserLookup.get(kindsHandled[i].toLowerCase()); if (test != null) { throw new PersistenceLayerException("Error registering '" + testClass.getClass().getName() + "' as test '" + kindsHandled[i] + "'. The test is already registered to '" + test.getClass().getName() + "'"); } parserLookup.put(kindsHandled[i].toLowerCase(), testClass); } } public static List<Prerequisite> parse(final List<String> preStrings) { final List<Prerequisite> ret = new ArrayList<>(preStrings.size()); for (String prestr : preStrings) { try { final PreParserFactory factory = PreParserFactory.getInstance(); final Prerequisite prereq = factory.parse(prestr); ret.add(prereq); } catch (PersistenceLayerException ple) { Logging.errorPrint(ple.getMessage(), ple); //The message is now produced at a lower level, and thus has to be localised there. //Logging.errorPrintLocalised(PropertyFactory.getString("PrereqHandler.Unable_to_parse"), object); //$NON-NLS-1$ } } return ret; } public Prerequisite parse(String prereqStr) throws PersistenceLayerException { if ((prereqStr == null) || (prereqStr.length() <= 0)) { throw new PersistenceLayerException("Null or empty PRE string"); } int index = prereqStr.indexOf(':'); if (index < 0) { throw new PersistenceLayerException("'" + prereqStr + "'" + " is a badly formatted prereq."); } String kind = prereqStr.substring(0, index); String formula = prereqStr.substring(index + 1); boolean overrideQualify = false; if (formula.startsWith("Q:")) { formula = formula.substring(2); overrideQualify = true; } boolean invertResult = false; if (kind.startsWith("!")) { invertResult = true; kind = kind.substring(1); } kind = kind.substring(3); PrerequisiteParserInterface parser = getParser(kind); if (parser == null) { throw new PersistenceLayerException( "Can not determine which parser to use for " + "'" + prereqStr + "'"); } try { Prerequisite prereq = parser.parse(kind, formula, invertResult, overrideQualify); //sanity check to make sure we have not got a top level element that // is a PREMULT with only 1 element. while (prereq.getKind() == null && prereq.getPrerequisiteCount() == 1 && prereq.getOperator().equals(PrerequisiteOperator.GTEQ) && prereq.getOperand().equals("1")) { Prerequisite sub = prereq.getPrerequisites().get(0); sub.setOriginalCheckmult(prereq.isOriginalCheckMult()); prereq = sub; } return prereq; } catch (Throwable t) { throw new PersistenceLayerException("Can not parse '" + prereqStr + "': " + t.getMessage()); } } /** * Identify if the token passed in defines a prerequisite. * * @param token The token to be checked. * @return True if the string is a prereq string. */ public static boolean isPreReqString(String token) { return (token.startsWith("PRE") || token.startsWith("!PRE")) && (token.indexOf(":") > 0); } public static void clear() { parserLookup.clear(); if (instance != null) { try { register(new PreMultParser()); } catch (PersistenceLayerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }