/**
* TestHelper.java
* Copyright 2005 (c) Andrew Wilson <nuance@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
*
* Current Version: $Revision$
*
*/
package pcgen.util;
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.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.lang3.SystemUtils;
import pcgen.base.lang.UnreachableError;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.enumeration.ListKey;
import pcgen.cdom.enumeration.ObjectKey;
import pcgen.cdom.enumeration.SkillArmorCheck;
import pcgen.cdom.enumeration.StringKey;
import pcgen.cdom.enumeration.Type;
import pcgen.cdom.reference.CDOMDirectSingleRef;
import pcgen.core.Ability;
import pcgen.core.AbilityCategory;
import pcgen.core.Campaign;
import pcgen.core.ChronicleEntry;
import pcgen.core.Domain;
import pcgen.core.Equipment;
import pcgen.core.GameMode;
import pcgen.core.Globals;
import pcgen.core.Kit;
import pcgen.core.PCClass;
import pcgen.core.PCStat;
import pcgen.core.PCTemplate;
import pcgen.core.PlayerCharacter;
import pcgen.core.Race;
import pcgen.core.SettingsHandler;
import pcgen.core.SizeAdjustment;
import pcgen.core.Skill;
import pcgen.core.SystemCollections;
import pcgen.core.WeaponProf;
import pcgen.core.bonus.Bonus;
import pcgen.core.bonus.BonusObj;
import pcgen.core.spell.Spell;
import pcgen.persistence.CampaignFileLoader;
import pcgen.persistence.GameModeFileLoader;
import pcgen.persistence.PersistenceLayerException;
import pcgen.persistence.lst.AbilityLoader;
import pcgen.persistence.lst.CampaignSourceEntry;
import pcgen.persistence.lst.GenericLoader;
import pcgen.persistence.lst.LstObjectFileLoader;
import pcgen.persistence.lst.PCClassLoader;
import pcgen.rules.context.LoadContext;
import pcgen.system.ConfigurationSettings;
import pcgen.system.Main;
import pcgen.system.PCGenTask;
import pcgen.system.PropertyContextFactory;
import plugin.lsttokens.testsupport.BuildUtilities;
/**
* Helps Junit tests
*/
@SuppressWarnings("nls")
public class TestHelper
{
private static boolean loaded = false;
private static LstObjectFileLoader<Equipment> eqLoader = new GenericLoader<>(Equipment.class);
private static LstObjectFileLoader<Ability> abLoader = new AbilityLoader();
private static CampaignSourceEntry source = null;
/**
* Make some size adjustments
*/
public static void makeSizeAdjustments()
{
final String sizes =
"Fine|Diminutive|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal";
final StringTokenizer aTok = new StringTokenizer(sizes, "|");
GameMode gamemode = SystemCollections.getGameModeNamed("3.5");
if (gamemode == null)
{
gamemode = new GameMode("3.5");
SystemCollections.addToGameModeList(gamemode);
GameModeFileLoader.addDefaultTabInfo(gamemode);
}
SettingsHandler.setGame("3.5");
int count = 0;
while (aTok.hasMoreTokens())
{
SizeAdjustment sa = BuildUtilities.createSize(aTok.nextToken(), count++);
Globals.getContext().getReferenceContext().importObject(sa);
}
Globals.getContext().getReferenceContext()
.silentlyGetConstructedCDOMObject(SizeAdjustment.class, "M").put(
ObjectKey.IS_DEFAULT_SIZE, true);
}
/**
* Make some equipment
* @param input Equipment source line to be parsed
* @return true if OK
*/
public static boolean makeEquipment(final String input)
{
loadPlugins();
try
{
final CampaignSourceEntry source = createSource(TestHelper.class);
eqLoader.parseLine(Globals.getContext(), null, input, source);
return true;
}
catch (Exception e)
{
// TODO Deal with Exception?
}
return false;
}
/**
* Create a new CampaignSourceEntry for the class.
* @param cls The class the try is for.
* @return The CampaignSourceEntry.
*/
public static CampaignSourceEntry createSource(Class cls)
{
final CampaignSourceEntry source;
try
{
source = new CampaignSourceEntry(new Campaign(),
new URI("file:/" + cls.getName() + ".java"));
}
catch (URISyntaxException e)
{
throw new UnreachableError(e);
}
return source;
}
/**
* Load the plugins
*/
public static void loadPlugins()
{
if (!loaded)
{
pcgen.system.Main.createLoadPluginTask().execute();
loaded = true;
}
}
/**
* Get the field related to a name
* @param aClass The class to search for the field
* @param fieldName the field to search for
* @return the field related to a name in the class
*/
public static Object findField(final Class<?> aClass, final String fieldName)
{
try
{
Class<?> clazz = aClass;
while (true)
{
for (final Field f : Arrays.asList(clazz.getDeclaredFields()))
{
if (f.getName().equals(fieldName))
{
f.setAccessible(true);
return f;
}
}
if (!"Object".equals(clazz.getName()))
{
clazz = clazz.getSuperclass();
}
else
{
break;
}
}
}
catch (SecurityException e)
{
System.out.println(e);
}
return null;
}
/**
* Set the important info about a Skill
* @param name The skill name
* @param type The type info ("." separated)
* @param stat The key stat
* @param untrained Can this be used untrained
* @param armorCheck should an armor check penalty be applied
*/
public static Skill makeSkill(
final String name,
final String type,
final PCStat stat,
final boolean untrained,
final SkillArmorCheck armorCheck)
{
final Skill aSkill = new Skill();
aSkill.setName(name);
aSkill.put(StringKey.KEY_NAME, ("KEY_" + name));
addType(aSkill, type);
CDOMDirectSingleRef<PCStat> statRef = CDOMDirectSingleRef.getRef(stat);
aSkill.put(ObjectKey.KEY_STAT, statRef);
aSkill.put(ObjectKey.USE_UNTRAINED, untrained);
aSkill.put(ObjectKey.ARMOR_CHECK, armorCheck);
Globals.getContext().getReferenceContext().importObject(aSkill);
return aSkill;
}
/**
* Set the important info about a Skill
* @param name The skill name
* @param cat the category of this Ability
* @param type The type info ("." separated)
* @return The ability (which has also been added to global storage
*/
public static Ability makeAbility(final String name, final String cat, final String type)
{
AbilityCategory useCat = Globals.getContext().getReferenceContext()
.constructNowIfNecessary(AbilityCategory.class, cat);
final Ability anAbility = new Ability();
anAbility.setName(name);
anAbility.put(StringKey.KEY_NAME, ("KEY_" + name));
anAbility.setCDOMCategory(useCat);
addType(anAbility, type);
Globals.getContext().getReferenceContext().importObject(anAbility);
return anAbility;
}
/**
* Set the important info about a Skill
* @param name The skill name
* @param cat the category of this Ability
* @param type The type info ("." separated)
* @return The ability (which has also been added to global storage
*/
public static Ability makeAbility(final String name, final AbilityCategory cat, final String type)
{
final Ability anAbility = new Ability();
anAbility.setName(name);
anAbility.put(StringKey.KEY_NAME, ("KEY_" + name));
anAbility.setCDOMCategory(cat);
addType(anAbility, type);
Globals.getContext().getReferenceContext().importObject(anAbility);
return anAbility;
}
/**
* Make an ability
*
* @param input the Ability source string to parse and create the ability from
* @return true if OK
*/
public static boolean makeAbilityFromString(final String input)
{
loadPlugins();
try
{
if (null == source)
{
try
{
source = new CampaignSourceEntry(new Campaign(),
new URI("file:/" + TestHelper.class.getName() + ".java"));
}
catch (URISyntaxException e)
{
throw new UnreachableError(e);
}
}
abLoader.parseLine(Globals.getContext(), null, input, source);
return true;
}
catch (Exception e)
{
Logging.errorPrint(e.getLocalizedMessage());
}
return false;
}
/**
* Set the important info about a WeaponProf
* @param name The weaponprof name
* @param type The type info ("." separated)
* @return The weapon prof (which has also been added to global storage
*/
public static WeaponProf makeWeaponProf(final String name, final String type)
{
final WeaponProf aWpnProf = new WeaponProf();
aWpnProf.setName(name);
aWpnProf.put(StringKey.KEY_NAME, ("KEY_" + name));
addType(aWpnProf, type);
Globals.getContext().getReferenceContext().importObject(aWpnProf);
return aWpnProf;
}
/**
* Set the important info about a Race
* @param name The race name
* @return The race (which has also been added to global storage)
*/
public static Race makeRace(final String name)
{
final Race aRace = new Race();
aRace.setName(name);
aRace.put(StringKey.KEY_NAME, ("KEY_" + name));
LoadContext context = Globals.getContext();
final BonusObj bon = Bonus.newBonus(context, "FEAT|POOL|1");
aRace.addToListFor(ListKey.BONUS, bon);
context.getReferenceContext().importObject(aRace);
return aRace;
}
/**
* Set the important info about a Class
* @param name The race name
* @return The race (which has also been added to global storage)
*/
public static PCClass makeClass(final String name)
{
final PCClass aClass = new PCClass();
aClass.setName(name);
aClass.put(StringKey.KEY_NAME, ("KEY_" + name));
Globals.getContext().getReferenceContext().importObject(aClass);
return aClass;
}
/**
* Set the important info about a Domain
* @param name The domain name
* @return The domain (which has also been added to global storage)
*/
public static Domain makeDomain(final String name)
{
final Domain domain = new Domain();
domain.setName(name);
domain.put(StringKey.KEY_NAME, (name));
Globals.getContext().getReferenceContext().importObject(domain);
return domain;
}
/**
* Set the important info about a Spell
* @param name The spell name
* @return The spell (which has also been added to global storage)
*/
public static Spell makeSpell(final String name)
{
final Spell aSpell = new Spell();
aSpell.setName(name);
aSpell.put(StringKey.KEY_NAME, ("KEY_" + name));
Globals.getContext().getReferenceContext().importObject(aSpell);
return aSpell;
}
/**
* Set the important info about a Kit. Note the key of the kit created will
* be the provided name with KEY_ added at the front. e.g. KEY_name
* @param name The kit name
* @return The kit (which has also been added to global storage)
*/
public static Kit makeKit(final String name)
{
final Kit aKit = new Kit();
aKit.setName(name);
aKit.put(StringKey.KEY_NAME, ("KEY_" + name));
Globals.getContext().getReferenceContext().importObject(aKit);
return aKit;
}
/**
* Set the important info about a Template
* @param name The template name
* @return The template (which has also been added to global storage)
*/
public static PCTemplate makeTemplate(final String name)
{
final PCTemplate aTemplate = new PCTemplate();
aTemplate.setName(name);
aTemplate.put(StringKey.KEY_NAME, ("KEY_" + name));
Globals.getContext().getReferenceContext().importObject(aTemplate);
return aTemplate;
}
/**
* Get the Ability Category of the Ability object passed in. If it does
* not exist in the game mode, a new object wil be created and added to
* the game mode
*
* @param ability an ability in the AbilityCategory we want to retrieve
* @return the AbilityCategory
*/
public static AbilityCategory getAbilityCategory(final Ability ability)
{
return (AbilityCategory) ability.getCDOMCategory();
}
public static void addType(CDOMObject cdo, String string)
{
List<String> stringList = Arrays.asList(string.split("\\."));
for (String s : stringList)
{
cdo.addToListFor(ListKey.TYPE, Type.getConstant(s));
}
}
/**
* Checks to see if this PC has the weapon proficiency key aKey
*
* @param aKey
* @return boolean
*/
public static boolean hasWeaponProfKeyed(PlayerCharacter pc,
final String aKey)
{
WeaponProf wp = Globals.getContext().getReferenceContext()
.silentlyGetConstructedCDOMObject(WeaponProf.class, aKey);
return wp != null && pc.hasWeaponProf(wp);
}
/**
* Locate the data folder which contains the primary set of LST data. This
* defaults to the data folder under the current directory, but can be
* customised in the config.ini folder.
* @return The path of the data folder.
*/
public static String findDataFolder()
{
// Set the pcc location to "data"
String pccLoc = "data";
try
{
// Read in options.ini and override the pcc location if it exists
BufferedReader br =
new BufferedReader(new InputStreamReader(
new FileInputStream("config.ini"), "UTF-8"));
while (br.ready())
{
String line = br.readLine();
if (line != null
&& line.startsWith("pccFilesPath="))
{
pccLoc = line.substring(13);
break;
}
}
br.close();
}
catch (IOException e)
{
// Ignore, see method comment
}
return pccLoc;
}
/**
* Write a settings/config file for use by unit tests.
* @param configFileName The name of the new config file.
* @param configFolder The folder in which other settings files will be saved.
* @param pccLoc The location of the data folder.
* @return The file that was created.
* @throws IOException If the file cannot be written.
*/
public static File createDummySettingsFile(String configFileName,
String configFolder, String pccLoc) throws IOException
{
File configFile = new File(configFileName);
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
configFile), "UTF-8"));
bw.write("settingsPath=" + configFolder + "\r\n");
if (pccLoc != null)
{
System.out.println("Using PCC Location of '" + pccLoc + "'.");
bw.write("pccFilesPath=" + pccLoc + "\r\n");
}
bw.write("customPath=testsuite\\\\customdata\r\n");
bw.close();
return configFile;
}
public static void loadGameModes(String testConfigFile)
{
String configFolder = "testsuite";
String pccLoc = TestHelper.findDataFolder();
System.out.println("Got data folder of " + pccLoc);
try
{
TestHelper.createDummySettingsFile(testConfigFile, configFolder,
pccLoc);
}
catch (IOException e)
{
Logging.errorPrint("DataTest.loadGameModes failed", e);
}
PropertyContextFactory configFactory =
new PropertyContextFactory(SystemUtils.USER_DIR);
configFactory.registerAndLoadPropertyContext(ConfigurationSettings
.getInstance(testConfigFile));
Main.loadProperties(false);
PCGenTask loadPluginTask = Main.createLoadPluginTask();
loadPluginTask.execute();
GameModeFileLoader gameModeFileLoader = new GameModeFileLoader();
gameModeFileLoader.execute();
CampaignFileLoader campaignFileLoader = new CampaignFileLoader();
campaignFileLoader.execute();
}
public static ChronicleEntry buildChronicleEntry(boolean visible, String campaign, String date,
String gm, String party, String adventure, int xp, String chronicle)
{
ChronicleEntry chronEntry = new ChronicleEntry();
chronEntry.setOutputEntry(visible);
chronEntry.setCampaign(campaign);
chronEntry.setDate(date);
chronEntry.setGmField(gm);
chronEntry.setParty(party);
chronEntry.setAdventure(adventure);
chronEntry.setXpField(xp);
chronEntry.setChronicle(chronicle);
return chronEntry;
}
public static PCClass parsePCClassText(String classPCCText,
CampaignSourceEntry source) throws PersistenceLayerException
{
PCClassLoader pcClassLoader = new PCClassLoader();
PCClass reconstClass = null;
StringTokenizer tok = new StringTokenizer(classPCCText, "\n");
while (tok.hasMoreTokens())
{
String line = tok.nextToken();
if (line.trim().length() > 0)
{
System.out.println("Processing line:'" + line + "'.");
reconstClass =
pcClassLoader.parseLine(Globals.getContext(),
reconstClass, line, source);
}
}
return reconstClass;
}
}