/* * Copyright (c) 2009 Tom Parker <thpr@users.sourceforge.net> * * This program 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 program 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package pcgen.gui2.converter.loader; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.List; import pcgen.cdom.base.CDOMObject; import pcgen.cdom.enumeration.IntegerKey; import pcgen.cdom.enumeration.ListKey; import pcgen.cdom.enumeration.ObjectKey; import pcgen.cdom.inst.PCClassLevel; import pcgen.core.Campaign; import pcgen.core.PCClass; import pcgen.core.SubClass; import pcgen.core.SubstitutionClass; import pcgen.gui2.converter.ConversionDecider; import pcgen.gui2.converter.Loader; import pcgen.gui2.converter.TokenConverter; import pcgen.gui2.converter.event.TokenProcessEvent; import pcgen.persistence.PersistenceLayerException; import pcgen.persistence.lst.CampaignSourceEntry; import pcgen.rules.context.EditorLoadContext; import pcgen.util.Logging; /** * ClassLoader is a loader dedicated to converting class and class level data. * * @author Tom Parker <thpr@users.sourceforge.net> */ public class ClassLoader implements Loader { public static final String FIELD_SEPARATOR = "\t"; //$NON-NLS-1$ private final EditorLoadContext context; private final Writer changeLogWriter; public ClassLoader(EditorLoadContext lc, Writer changeLogWriter) { context = lc; this.changeLogWriter = changeLogWriter; } @Override public List<CDOMObject> process(StringBuilder sb, int line, String lineString, ConversionDecider decider) throws PersistenceLayerException, InterruptedException { List<CDOMObject> list = new ArrayList<>(); String[] tokens = lineString.split(FIELD_SEPARATOR); if (tokens.length == 0) { return list; } String firstToken = tokens[0]; sb.append(firstToken); Class<? extends CDOMObject> buildClass; Class<? extends CDOMObject> buildParent = null; if (firstToken.startsWith("SUBCLASS:")) { buildClass = SubClass.class; } else if (firstToken.startsWith("SUBCLASSLEVEL:")) { buildClass = PCClassLevel.class; buildParent = SubClass.class; } else if (firstToken.startsWith("SUBSTITUTIONCLASS:")) { buildClass = SubstitutionClass.class; } else if (firstToken.startsWith("SUBSTITUTIONLEVEL:")) { buildClass = PCClassLevel.class; buildParent = SubstitutionClass.class; } else if (firstToken.startsWith("CLASS:")) { buildClass = PCClass.class; } else { buildClass = PCClassLevel.class; buildParent = PCClass.class; } for (int tok = 1; tok < tokens.length; tok++) { String token = tokens[tok]; sb.append(FIELD_SEPARATOR); if (token.isEmpty()) { continue; } CDOMObject obj = context.getReferenceContext().constructCDOMObject(buildClass, line + "Test" + tok); CDOMObject parent = null; if (obj instanceof PCClassLevel) { obj.put(IntegerKey.LEVEL, 1); parent = context.getReferenceContext().constructCDOMObject(buildParent, line + "Test" + tok); try { // Ensure processing against the PCClassLevel cannot cause side effects on the parent class obj.put(ObjectKey.TOKEN_PARENT, parent.clone()); } catch (CloneNotSupportedException e) { Logging.errorPrint("Unable to preare a copy of " + parent); } } List<CDOMObject> injected = processToken(sb, firstToken, obj, parent, token, decider, line); if (injected != null) { list.addAll(injected); } context.purge(obj); if (parent != null) { context.purge(parent); } TokenConverter.clearConstants(); } return list; } private List<CDOMObject> processToken(StringBuilder sb, String firstToken, CDOMObject obj, CDOMObject alt, String token, ConversionDecider decider, int line) throws PersistenceLayerException, InterruptedException { final int colonLoc = token.indexOf(':'); if (colonLoc == -1) { Logging.errorPrint("Invalid Token - does not contain a colon: " + token); return null; } else if (colonLoc == 0) { Logging.errorPrint("Invalid Token - starts with a colon: " + token); return null; } String key = token.substring(0, colonLoc); String value = (colonLoc == token.length() - 1) ? null : token .substring(colonLoc + 1); TokenProcessEvent tpe = new TokenProcessEvent(context, decider, key, value, firstToken, obj); String error = TokenConverter.process(tpe); if (!tpe.isConsumed() && alt != null) { tpe = new TokenProcessEvent(context, decider, key, value, firstToken, alt); error += TokenConverter.process(tpe); } if (tpe.isConsumed()) { if (!token.equals(tpe.getResult())) { try { changeLogWriter.append("Line " + line + " converted '"+token+"' to '" + tpe.getResult() +"'.\n"); } catch (IOException e) { Logging.errorPrint("Unable to log change", e); } } sb.append(tpe.getResult()); } else { Logging.errorPrint(error); } return tpe.getInjected(); } @Override public List<CampaignSourceEntry> getFiles(Campaign c) { return c.getSafeListFor(ListKey.FILE_CLASS); } public String getLoadName() { return "Class"; } }