/*
* 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;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import pcgen.base.lang.StringUtil;
import pcgen.base.util.DoubleKeyMapToList;
import pcgen.base.util.TripleKeyMapToList;
import pcgen.cdom.base.CDOMObject;
import pcgen.core.Campaign;
import pcgen.persistence.lst.CampaignSourceEntry;
import pcgen.rules.context.LoadContext;
import pcgen.system.PCGenPropBundle;
import pcgen.util.StringPClassUtil;
public class ObjectInjector
{
private final TripleKeyMapToList<URI, String, String, String> campaignData = new TripleKeyMapToList<>();
private final DoubleKeyMapToList<URI, File, String> fileData = new DoubleKeyMapToList<>();
private final Collection<Loader> loaders;
private final File outDir;
private final File rootDir;
public ObjectInjector(LoadContext context, File outputDir,
File rootDirectory, LSTConverter converter)
{
outDir = outputDir;
rootDir = rootDirectory;
loaders = converter.getInjectedLoaders();
for (Loader l : loaders)
{
for (URI uri : converter.getInjectedURIs(l))
{
for (CDOMObject o : converter.getInjectedObjects(l, uri))
{
Class<?> cl = o.getClass();
String className = StringPClassUtil.getStringFor(cl);
if ("EQMOD".equals(className))
{
className = "EQUIPMOD";
}
String fileName = className.toLowerCase()
+ "_516_conversion.lst";
context.setExtractURI(uri);
Collection<String> result = context.unparse(o);
String line = o.getDisplayName() + "\t"
+ StringUtil.join(result, "\t");
if (result != null)
{
fileData.addToListFor(uri,
getOutputFile(uri, fileName), line);
campaignData.addToListFor(uri, className, fileName,
line);
}
}
}
}
}
private File getOutputFile(URI uri, String fileName)
{
File outFile = new File(getNewOutputName(uri).getParentFile(), fileName);
if (outFile.exists())
{
System.err.println("Won't overwrite: " + outFile);
}
return outFile;
}
private File getNewOutputName(URI uri)
{
File in = new File(uri);
File base = findSubRoot(rootDir, in);
String relative = in.toString().substring(base.toString().length() + 1);
File actualRoot = generateCommonRoot(rootDir, outDir);
String outString = outDir.getAbsolutePath().substring(
actualRoot.getAbsolutePath().length());
File outputFileSibling = new File(actualRoot, File.separator + outString
+ File.separator + relative);
return outputFileSibling;
}
public void writeInjectedObjects(List<Campaign> list) throws IOException
{
List<URI> affectedURIs = new ArrayList<>();
boolean first = true;
for (Campaign campaign : list)
{
for (Loader l : loaders)
{
for (CampaignSourceEntry cse : l.getFiles(campaign))
{
first &= processWrite(campaign, campaignData, cse, first);
affectedURIs.add(cse.getURI());
}
}
}
for (URI uri : affectedURIs)
{
Set<File> files = fileData.getSecondaryKeySet(uri);
if (files != null)
{
for (File f : files)
{
writeFile(f, fileData.getListFor(uri, f));
}
}
}
}
private void writeFile(File f, List<String> lines) throws IOException
{
FileWriter writer = new FileWriter(f);
writer.write(getFileHeader());
for (String line : lines)
{
writer.write(line);
writer.write("\n");
}
writer.write(getFileFooter());
writer.close();
}
private String getFileHeader()
{
StringBuilder sb = new StringBuilder();
sb.append("# This file was automatically created ");
sb.append("during dataset conversion by PCGen ");
sb.append(PCGenPropBundle.getVersionNumber());
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
sb.append(" on ").append(df.format(new Date()));
sb.append("\n# This file does not contain SOURCE information\n");
return sb.toString();
}
private String getFileFooter()
{
StringBuilder sb = new StringBuilder();
sb.append("\n#\n#EOF\n#\n");
return sb.toString();
}
private boolean processWrite(Campaign campaign,
TripleKeyMapToList<URI, String, String, String> toWrite,
CampaignSourceEntry cse, boolean needHeader) throws IOException
{
URI uri = cse.getURI();
Set<String> classNames = toWrite.getSecondaryKeySet(uri);
if (classNames != null)
{
URI append = campaign.getSourceURI();
File campaignFile = getNewOutputName(append);
FileWriter writer = new FileWriter(campaignFile, true);
if (needHeader)
{
writer.write(getCampaignInsertInfo());
}
for (String className : classNames)
{
for (String fileName : toWrite
.getTertiaryKeySet(uri, className))
{
CampaignSourceEntry writecse = cse
.getRelatedTarget(fileName);
writer.write(className);
writer.write(":");
writer.write(writecse.getLSTformat());
writer.write("\n");
}
}
writer.close();
return false;
}
return true;
}
private String getCampaignInsertInfo()
{
StringBuilder sb = new StringBuilder();
sb.append("\n#\n# The following file(s) were automatically added");
sb.append(" during dataset conversion by PCGen ");
try
{
ResourceBundle d_properties = ResourceBundle
.getBundle("pcgen/gui/prop/PCGenProp");
sb.append(d_properties.getString("VersionNumber"));
}
catch (MissingResourceException mre)
{
mre.printStackTrace();
}
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
sb.append(" on ").append(df.format(new Date()));
sb.append("\n#\n");
return sb.toString();
}
private File findSubRoot(File root, File in)
{
if (in.getParentFile() == null)
{
return null;
}
if (in.getParentFile().getAbsolutePath().equals(root.getAbsolutePath()))
{
return in;
}
return findSubRoot(root, in.getParentFile());
}
private File generateCommonRoot(File a, File b)
{
/*
* FUTURE Think of whether this correctly works for items which may
* require a path resolution; is there a flag for that or should there
* be another method for that, or just tough luck to users requiring
* that?
*/
if (a.equals(b))
{
return a;
}
List<File> al = generateDirectoryHierarchy(a);
List<File> bl = generateDirectoryHierarchy(b);
File returnFile = null;
for (File f : al)
{
if (bl.contains(f))
{
returnFile = f;
}
else
{
break;
}
}
return returnFile;
}
private List<File> generateDirectoryHierarchy(File a)
{
List<File> l = new ArrayList<>();
while (a != null)
{
l.add(0, a);
a = a.getParentFile();
}
return l;
}
}