/*
* CustomData.java
* Copyright 2002 (C) Greg Bingleman <byngl@hotmail.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 November 23, 2002, 12:53 AM
*
*
* Current Ver: $Revision$
*/
package pcgen.core;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.SortedMap;
import pcgen.cdom.base.Constants;
import pcgen.cdom.enumeration.StringKey;
import pcgen.core.prereq.Prerequisite;
import pcgen.core.spell.Spell;
import pcgen.persistence.lst.CampaignOutput;
import pcgen.persistence.lst.output.prereq.PrerequisiteWriter;
import pcgen.system.PCGenSettings;
import pcgen.util.Logging;
/**
* {@code CustomData}
*
* @author Greg Bingleman <byngl@hotmail.com>
*/
public final class CustomData
{
private static final String AUTO_GEN_WARN_LINE_1 = "#This file auto-generated by PCGen. Manual editing not recommended.";
private static final String AUTO_GEN_WARN_LINE_2 = "#Ensure PCGen is not running before editing. Make backups as errors may result in data loss.";
private static boolean customItemsLoaded = false;
/**
* As it only contains static methods, disable instance creation with a private constructor.
*/
private CustomData()
{
// Empty Constructor
}
/**
* Get custom equipment reader
* @return custom equipment reade
*/
public static BufferedReader getCustomEquipmentReader()
{
return getReader(customEquipmentFilePath());
}
/**
* Get custom bio file set path
* @param usePath
* @return custom bio file set path
*/
public static String customBioSetFilePath(final boolean usePath)
{
return getCustomPath("BioSet", usePath);
}
/**
* Get customClassFilePath
* @param usePath
* @return customClassFilePath
*/
public static String customClassFilePath(final boolean usePath)
{
return getCustomPath("Classes", usePath);
}
/**
* Get customDeityFilePath
* @param usePath
* @return customDeityFilePath
*/
public static String customDeityFilePath(final boolean usePath)
{
return getCustomPath("Deities", usePath);
}
/**
* Get customDomainFilePath
* @param usePath
* @return customDomainFilePath
*/
public static String customDomainFilePath(final boolean usePath)
{
return getCustomPath("Domains", usePath);
}
/**
* Get customAbilityFilePath
* @param usePath
* @return customAbilityFilePath
*/
public static String customAbilityFilePath(final boolean usePath)
{
return getCustomPath("Abilities", usePath);
}
/**
* Get customFeatFilePath
* @param usePath
* @return customFeatFilePath
*/
public static String customFeatFilePath(final boolean usePath)
{
return getCustomPath("Feats", usePath);
}
/**
* GEt customLanguageFilePath
* @param usePath
* @return customLanguageFilePath
*/
public static String customLanguageFilePath(final boolean usePath)
{
return getCustomPath("Languages", usePath);
}
/**
* Get custom purchase mode path
* @param usePath Should the game mode path be used
* @param gmName The name of the game mode to get the path for
* @return custom purchase mode file set path
*/
public static String customPurchaseModeFilePath(final boolean usePath, String gmName)
{
return getCustomPath("PointBuyMethods", usePath, gmName);
}
/**
* Get customRaceFilePath
* @param usePath
* @return customRaceFilePath
*/
public static String customRaceFilePath(final boolean usePath)
{
return getCustomPath("Races", usePath);
}
/**
* Get customSkillFilePath
* @param usePath
* @return customSkillFilePath
*/
public static String customSkillFilePath(final boolean usePath)
{
return getCustomPath("Skills", usePath);
}
/**
* Get customSpellFilePath
* @param usePath
* @return customSpellFilePath
*/
public static String customSpellFilePath(final boolean usePath)
{
return getCustomPath("Spells", usePath);
}
/**
* GEt customTemplateFilePath
* @param usePath
* @return customTemplateFilePath
*/
public static String customTemplateFilePath(final boolean usePath)
{
return getCustomPath("Templates", usePath);
}
/**
* Write custom files out
*/
public static void writeCustomFiles()
{
//
// Make sure the custom directory exists
//
ensureCustomDirExists();
writePurchaseModeConfiguration();
// Don't trash the file if user exits before loading custom items
if (!customItemsLoaded)
{
return;
}
writeCustomBioSet();
writeCustomClasses();
writeCustomDeities();
writeCustomDomains();
writeCustomAbilities();
writeCustomFeats();
writeCustomItems();
writeCustomLanguages();
writeCustomRaces();
writeCustomSkills();
writeCustomSpells();
writeCustomTemplates();
writeCustomSources();
}
/**
* This method will check for the system specific custom directory
* and will create it if it exists.
*/
private static void ensureCustomDirExists()
{
File customDir =
new File(PCGenSettings.getCustomDir() + File.separator
+ SettingsHandler.getGame().getName());
if (!customDir.exists())
{
try
{
customDir.mkdirs();
}
catch (SecurityException se)
{
Logging.errorPrint("Unable to create custom data directory '"
+ customDir.getPath() + "' due the following error.", se);
}
}
}
/**
* Write custom items out
*/
public static void writeCustomItems()
{
//check if custom equipment has been loaded. If not, just return without erasing customequipment.lst file
if (!customItemsLoaded && new File(customEquipmentFilePath()).exists())
{
if (Logging.isLoggable(Logging.WARNING))
{
Logging
.log(Logging.WARNING,
"Custom items had not been loaded, so we won't save them this time."); //$NON-NLS-1$
}
return;
}
ensureCustomDirExists();
final BufferedWriter bw = getCustomEquipmentWriter();
if (bw == null)
{
return;
}
try
{
bw.write(AUTO_GEN_WARN_LINE_1);
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_2);
bw.newLine();
for (Equipment aEq : Globals.getContext().getReferenceContext().getConstructedCDOMObjects(Equipment.class))
{
if (aEq.isType(Constants.TYPE_CUSTOM) && !aEq.isType("AUTO_GEN"))
{
aEq.save(bw);
}
}
}
catch (IOException e)
{
Logging.errorPrint("Error in writeCustomItems", e);
}
finally
{
try
{
bw.close();
}
catch (IOException ex)
{
Logging.errorPrint("Error in writeCustomItems while closing",
ex);
}
}
}
/**
* Write custom purchase mode config
*/
public static void writePurchaseModeConfiguration()
{
ensureCustomDirExists();
final BufferedWriter bw = getPurchaseModeWriter();
final SortedMap<Integer, PointBuyCost> pbStatCosts = SettingsHandler.getGame().getPointBuyStatCostMap();
if (bw == null || pbStatCosts == null)
{
return;
}
try
{
bw.write("#");
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_1);
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_2);
bw.newLine();
bw.write("#");
bw.newLine();
bw.write("# Point-buy ability score costs");
bw.newLine();
bw.write("#");
bw.newLine();
if (!pbStatCosts.isEmpty())
{
for ( Integer statValue : pbStatCosts.keySet() )
{
final PointBuyCost pbc = pbStatCosts.get(statValue);
bw.write("STAT:" + statValue.toString() + "\t\tCOST:" + Integer.toString(pbc.getBuyCost()));
final int iCount = pbc.getPrerequisiteCount();
if (iCount != 0)
{
final StringWriter writer = new StringWriter();
for (Prerequisite prereq : pbc.getPrerequisiteList())
{
final PrerequisiteWriter prereqWriter = new PrerequisiteWriter();
try
{
writer.write("\t");
prereqWriter.write(writer, prereq);
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
bw.write(writer.toString());
}
bw.newLine();
}
}
bw.write("#");
bw.newLine();
bw.write("# Point-buy methods");
bw.newLine();
bw.write("#");
bw.newLine();
for (PointBuyMethod pbm : SettingsHandler.getGame()
.getModeContext().getReferenceContext()
.getConstructedCDOMObjects(PointBuyMethod.class))
{
bw.write("METHOD:" + pbm.getDisplayName() + "\t\tPOINTS:"
+ pbm.getPointFormula());
bw.newLine();
}
}
catch (IOException e)
{
Logging.errorPrint("Error in writePurchaseModeConfiguration", e);
}
finally
{
try
{
bw.close();
}
catch (IOException ex)
{
Logging
.errorPrint(
"Error in writePurchaseModeConfiguration while closing",
ex);
}
}
}
private static BufferedWriter getCustomEquipmentWriter()
{
return getWriter(customEquipmentFilePath());
}
private static String getCustomPath(final String type,
final boolean usePath, String gmName)
{
String aString = "";
if (usePath)
{
aString = PCGenSettings.getCustomDir();
aString += File.separator + gmName;
}
return aString + File.separator + "custom" + type + Constants.EXTENSION_LIST_FILE;
}
private static String getCustomPath(final String type, final boolean usePath)
{
return getCustomPath(type, usePath, SettingsHandler.getGame().getName());
}
private static BufferedWriter getPurchaseModeWriter()
{
return getWriter(customPurchaseModeFilePath(true, SettingsHandler.getGame().getName()));
}
private static BufferedReader getReader(final String path)
{
try
{
//return new BufferedReader(new FileReader(path));
return new BufferedReader(new InputStreamReader(
new FileInputStream(path), "UTF-8"));
}
catch (IOException e)
{
Logging
.debugPrint("Could not get a reader to read from " + path, e);
return null;
}
}
private static BufferedWriter getWriter(final String path)
{
try
{
return new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(path), "UTF-8"));
}
catch (IOException e)
{
Logging
.errorPrint(
"Could not get a writer to write to "
+ path
+ " \nThis means that your custom files won't be written. Please check the path.",
e);
return null;
}
}
private static String customEquipmentFilePath()
{
return getCustomPath("Equipment", true);
}
private static void writeCustomBioSet()
{
final BufferedWriter bw = getWriter(customBioSetFilePath(true));
if (bw == null)
{
return;
}
try
{
bw.write("#");
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_1);
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_2);
bw.newLine();
bw.write("#");
bw.newLine();
for ( final Race race : Globals.getContext().getReferenceContext().getConstructedCDOMObjects(Race.class) )
{
if (race.isType(Constants.TYPE_CUSTOM))
{
String region;
String[] unp = Globals.getContext().unparseSubtoken(race, "REGION");
if (unp == null)
{
region = Constants.NONE;
}
else
{
region = unp[0];
}
final String key = race.getKeyName();
bw.write(SettingsHandler.getGame().getBioSet().getRacePCCText(region, key));
bw.newLine();
}
}
// We are grouping the custom bio sets under the region of custom,
// rather than types which are used elsewhere.
// This done as type is not supported for bio sets.
//bw.write(BioSet.getRegionPCCText("Custom"));
bw.newLine();
}
catch (IOException e)
{
Logging.errorPrint("Error in writeCustomBioSet", e);
}
finally
{
try
{
bw.close();
}
catch (IOException ex)
{
Logging.errorPrint("Error in writeCustomBioSet while closing",
ex);
}
}
}
private static void writeCustomClasses()
{
writeCustomPObjects(customClassFilePath(true), Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(PCClass.class).iterator());
}
private static void writeCustomDeities()
{
writeCustomPObjects(customDeityFilePath(true), Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(Deity.class).iterator());
}
private static void writeCustomDomains()
{
writeCustomPObjects(customDomainFilePath(true),
Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(Domain.class).iterator());
}
private static void writeCustomAbilities()
{
for (AbilityCategory ac : SettingsHandler.getGame().getAllAbilityCategories())
{
writeCustomPObjects(customAbilityFilePath(true), Globals
.getContext().getReferenceContext().getManufacturer(Ability.class, ac)
.getAllObjects().iterator());
}
}
private static void writeCustomFeats()
{
File temp = new File(customFeatFilePath(true));
temp.delete();
}
private static void writeCustomHeader(final BufferedWriter bw)
throws IOException
{
bw.write("#");
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_1);
bw.newLine();
bw.write(AUTO_GEN_WARN_LINE_2);
bw.newLine();
bw.write("#");
bw.newLine();
bw.write("SOURCELONG:Custom\tSOURCESHORT:Custom");
bw.newLine();
}
private static void writeCustomLanguages()
{
writeCustomPObjects(customLanguageFilePath(true),
Globals.getContext().getReferenceContext().getConstructedCDOMObjects(
Language.class).iterator());
}
private static void writeCustomPObjects(final String filename, final Iterator<? extends PObject> it)
{
final BufferedWriter bw = getWriter(filename);
if (bw == null)
{
return;
}
try
{
writeCustomHeader(bw);
while (it.hasNext())
{
final PObject pobj = it.next();
if (pobj.isType(Constants.TYPE_CUSTOM))
{
bw.write(pobj.getPCCText());
bw.newLine();
}
}
}
catch (IOException e)
{
Logging.errorPrint("Error in writeCustomPObjects", e);
}
finally
{
try
{
bw.close();
}
catch (IOException ex)
{
Logging.errorPrint(
"Error in writeCustomPObjects while closing", ex);
}
}
}
private static void writeCustomRaces()
{
writeCustomPObjects(customRaceFilePath(true), Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(Race.class).iterator());
}
private static void writeCustomSkills()
{
writeCustomPObjects(customSkillFilePath(true), Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(Skill.class).iterator());
}
private static void writeCustomSources()
{
for ( Campaign c : Globals.getCampaignList() )
{
if (!c.getSafe(StringKey.DESTINATION).isEmpty())
{
CampaignOutput.output(Globals.getContext(), c);
}
}
}
private static void writeCustomSpells()
{
final BufferedWriter bw = getWriter(customSpellFilePath(true));
if (bw == null)
{
return;
}
try
{
writeCustomHeader(bw);
for(Spell spell : Globals.getContext().getReferenceContext()
.getConstructedCDOMObjects(Spell.class))
{
if (spell.isType(Constants.TYPE_CUSTOM))
{
bw.write(spell.getPCCText());
bw.newLine();
}
}
}
catch (IOException e)
{
Logging.errorPrint("Error in writeCustomSpells", e);
}
finally
{
try
{
bw.close();
}
catch (IOException ex)
{
Logging.errorPrint("Error in writeCustomSpells while closing",
ex);
}
}
}
private static void writeCustomTemplates()
{
writeCustomPObjects(customTemplateFilePath(true),
Globals.getContext().getReferenceContext().getConstructedCDOMObjects(
PCTemplate.class).iterator());
}
/**
* @param loaded Have the custom items ben loaded?
*/
public static void setCustomItemsLoaded(boolean loaded)
{
customItemsLoaded = loaded;
}
}