changeset 0:520818033bb6

Initial commit of WarFoundry code
author IBBoard <dev@ibboard.co.uk>
date Fri, 19 Dec 2008 15:57:51 +0000
parents
children df7211c5c448
files AssemblyInfo.cs IBBoard.WarFoundry.API.csproj IBBoard.WarFoundry.API.csproj.user IBBoard.WarFoundry.API.mdp IBBoard.WarFoundry.API.pidb api/Commands/CreateAndAddUnitCommand.cs api/Commands/RemoveUnitCommand.cs api/Commands/ReplaceUnitEquipmentCommand.cs api/Commands/SetNameCommand.cs api/Commands/SetUnitEquipmentAmountCommand.cs api/Commands/SetUnitSizeCommand.cs api/Delegates.cs api/Factories/AbstractNativeWarFoundryFactory.cs api/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs api/Factories/AbstractNonNativeWarFoundryFactory.cs api/Factories/AbstractWarFoundryFactory.cs api/Factories/INativeWarFoundryFactory.cs api/Factories/INonNativeWarFoundryFactory.cs api/Factories/IWarFoundryFactory.cs api/Factories/WarFoundryFactoryFactory.cs api/Factories/Xml/WarFoundryXmlElementName.cs api/Factories/Xml/WarFoundryXmlFactory.cs api/Factories/Xml/WarFoundryXmlSaver.cs api/Objects/Ability.cs api/Objects/ArmourType.cs api/Objects/Army.cs api/Objects/ArmyCategory.cs api/Objects/Category.cs api/Objects/EquipmentItem.cs api/Objects/GameSystem.cs api/Objects/IWarFoundryNativeSourceObject.cs api/Objects/IWarFoundryObject.cs api/Objects/IWarFoundryStagedLoadObject.cs api/Objects/Race.cs api/Objects/StagedLoadingGameSystem.cs api/Objects/StagedLoadingRace.cs api/Objects/Stat.cs api/Objects/StatSlot.cs api/Objects/Stats.cs api/Objects/SystemStats.cs api/Objects/SystemStatsSet.cs api/Objects/Unit.cs api/Objects/UnitEquipmentItem.cs api/Objects/UnitEquipmentItemObj.cs api/Objects/UnitType.cs api/Objects/WarFoundryObject.cs api/Requirements/AbstractArmyRequirement.cs api/Requirements/AbstractFailedRequirement.cs api/Requirements/AbstractRequirement.cs api/Requirements/AbstractUnitRequirement.cs api/Requirements/Delegates.cs api/Requirements/FailedRequirement.cs api/Requirements/FailedUnitRequirement.cs api/Requirements/RequirementAND.cs api/Requirements/RequirementOR.cs api/Requirements/UnitExcludesRequirement.cs api/Requirements/UnitExclusion.cs api/Requirements/UnitMaxNumberReached.cs api/Requirements/UnitMinNumberReached.cs api/Requirements/UnitRequirement.cs api/Requirements/UnitRequirementItem.cs api/Requirements/UnitRequirementMaxNumber.cs api/Requirements/UnitRequirementMinNumber.cs api/Requirements/UnitRequiresAtLeastRequirement.cs api/Savers/IWarFoundryFileSaver.cs api/Savers/WarFoundrySaver.cs api/WarFoundryCore.cs api/WarFoundryLoader.cs libs/ICSharpCode.SharpZipLib.dll libs/log4net.dll libs/log4net.xml test.c
diffstat 72 files changed, 34490 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AssemblyInfo.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("WarFoundry API")]
+[assembly: AssemblyDescription("The API for the WarFoundry army builder")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WarFoundry.API")]
+[assembly: AssemblyCopyright("IBBoard, 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.WarFoundry.API.csproj	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,212 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectType>Local</ProjectType>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{59EC117B-F955-44D5-8461-8F44F3A7481A}</ProjectGuid>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ApplicationIcon>
+    </ApplicationIcon>
+    <AssemblyKeyContainerName>
+    </AssemblyKeyContainerName>
+    <AssemblyName>IBBoard.WarFoundry.API</AssemblyName>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <DefaultClientScript>JScript</DefaultClientScript>
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>
+    <DelaySign>false</DelaySign>
+    <OutputType>Library</OutputType>
+    <RootNamespace>IBBoard.WarFoundry</RootNamespace>
+    <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+    <StartupObject>
+    </StartupObject>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <OutputPath>bin\Debug\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>true</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>false</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>full</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>bin\Release\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile>
+    </ConfigurationOverrideFile>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <DebugSymbols>false</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>
+    </NoWarn>
+    <Optimize>true</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>none</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821" />
+    <Reference Include="nunit.framework, Version=2.4.3.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77" />
+    <Reference Include="System">
+      <Name>System</Name>
+    </Reference>
+    <Reference Include="System.Data">
+      <Name>System.Data</Name>
+    </Reference>
+    <Reference Include="System.Windows.Forms">
+      <Name>System.Windows.Forms</Name>
+    </Reference>
+    <Reference Include="System.Xml">
+      <Name>System.XML</Name>
+    </Reference>
+    <ProjectReference Include="..\..\IBBoard\IBBoard.csproj">
+      <Name>IBBoard</Name>
+      <Project>{5DFD64F6-FC2B-4B4F-B92E-483BAC468105}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="API\Ability.cs" />
+    <Compile Include="API\ArmourType.cs" />
+    <Compile Include="API\Army.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\ArmyCategory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Category.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Commands\CreateAndAddUnitCommand.cs" />
+    <Compile Include="API\Commands\RemoveUnitCommand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Commands\ReplaceUnitEquipmentCommand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Commands\SetNameCommand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Commands\SetUnitEquipmentAmountCommand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Commands\SetUnitSizeCommand.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Delegates.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\EquipmentItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\GameSystem.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Race.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Requirements\AbstractArmyRequirement.cs" />
+    <Compile Include="API\Requirements\AbstractFailedRequirement.cs" />
+    <Compile Include="API\Requirements\AbstractRequirement.cs" />
+    <Compile Include="API\Requirements\AbstractUnitRequirement.cs" />
+    <Compile Include="API\Requirements\Delegates.cs" />
+    <Compile Include="API\Requirements\FailedRequirement.cs" />
+    <Compile Include="API\Requirements\FailedUnitRequirement.cs" />
+    <Compile Include="API\Requirements\RequirementAND.cs" />
+    <Compile Include="API\Requirements\RequirementOR.cs" />
+    <Compile Include="API\Requirements\UnitExcludesRequirement.cs" />
+    <Compile Include="API\Requirements\UnitExclusion.cs" />
+    <Compile Include="API\Requirements\UnitMaxNumberReached.cs" />
+    <Compile Include="API\Requirements\UnitMinNumberReached.cs" />
+    <Compile Include="API\Requirements\UnitRequirement.cs" />
+    <Compile Include="API\Requirements\UnitRequirementItem.cs" />
+    <Compile Include="API\Requirements\UnitRequirementMaxNumber.cs" />
+    <Compile Include="API\Requirements\UnitRequirementMinNumber.cs" />
+    <Compile Include="API\Requirements\UnitRequiresAtLeastRequirement.cs" />
+    <Compile Include="API\Stat.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\Stats.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\StatSlot.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\SystemStats.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\SystemStatsSet.cs" />
+    <Compile Include="API\Unit.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\UnitEquipmentItem.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\UnitEquipmentItemObj.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\UnitType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\WarFoundryCore.cs" />
+    <Compile Include="API\WarFoundryFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\WarFoundryFactoryFactory.cs" />
+    <Compile Include="API\WarFoundryObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="API\WarFoundrySaver.cs" />
+    <Compile Include="API\WarFoundryStagedLoadObject.cs" />
+    <Compile Include="API\WarFoundryXmlElementName.cs" />
+    <Compile Include="API\WarFoundryXmlFactory.cs" />
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="tests\WarFoundryFactoryFactoryTest.cs" />
+    <Compile Include="tests\WarFoundryFactoryTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="libs\log4net.dll" />
+    <Content Include="libs\log4net.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="testdata\" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.WarFoundry.API.csproj.user	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,58 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <LastOpenVersion>7.10.3077</LastOpenVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ReferencePath>
+    </ReferencePath>
+    <CopyProjectDestinationFolder>
+    </CopyProjectDestinationFolder>
+    <CopyProjectUncPath>
+    </CopyProjectUncPath>
+    <CopyProjectOption>0</CopyProjectOption>
+    <ProjectView>ShowAllFiles</ProjectView>
+    <ProjectTrust>0</ProjectTrust>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <EnableASPDebugging>false</EnableASPDebugging>
+    <EnableASPXDebugging>false</EnableASPXDebugging>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>
+    <RemoteDebugMachine>
+    </RemoteDebugMachine>
+    <StartAction>Project</StartAction>
+    <StartArguments>
+    </StartArguments>
+    <StartPage>
+    </StartPage>
+    <StartProgram>
+    </StartProgram>
+    <StartURL>
+    </StartURL>
+    <StartWorkingDirectory>
+    </StartWorkingDirectory>
+    <StartWithIE>true</StartWithIE>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <EnableASPDebugging>false</EnableASPDebugging>
+    <EnableASPXDebugging>false</EnableASPXDebugging>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>
+    <RemoteDebugMachine>
+    </RemoteDebugMachine>
+    <StartAction>Project</StartAction>
+    <StartArguments>
+    </StartArguments>
+    <StartPage>
+    </StartPage>
+    <StartProgram>
+    </StartProgram>
+    <StartURL>
+    </StartURL>
+    <StartWorkingDirectory>
+    </StartWorkingDirectory>
+    <StartWithIE>true</StartWithIE>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IBBoard.WarFoundry.API.mdp	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,98 @@
+<Project name="IBBoard.WarFoundry.API" fileversion="2.0" DefaultNamespace="IBBoard.WarFoundry" language="C#" clr-version="Net_2_0" ctype="DotNetProject">
+  <Configurations active="Debug">
+    <Configuration name="Debug" ctype="DotNetProjectConfiguration">
+      <Output directory="bin/Debug/" assemblyKeyFile="." assembly="IBBoard.WarFoundry.API" />
+      <Build debugmode="True" target="Library" />
+      <Execution runwithwarnings="False" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
+      <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+    </Configuration>
+    <Configuration name="Release" ctype="DotNetProjectConfiguration">
+      <Output directory="bin/Release/" assembly="IBBoard.WarFoundry.API" />
+      <Build debugmode="False" target="Library" />
+      <Execution runwithwarnings="False" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
+      <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="True" ctype="CSharpCompilerParameters" />
+    </Configuration>
+  </Configurations>
+  <Contents>
+    <File name="AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Delegates.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/CreateAndAddUnitCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/RemoveUnitCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/ReplaceUnitEquipmentCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/SetNameCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/SetUnitEquipmentAmountCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Commands/SetUnitSizeCommand.cs" subtype="Code" buildaction="Compile" />
+    <File name="libs/log4net.dll" subtype="Code" buildaction="Nothing" />
+    <File name="libs/log4net.xml" subtype="Code" buildaction="Nothing" />
+    <File name="api/Requirements" subtype="Directory" buildaction="Compile" />
+    <File name="api/Requirements/UnitExcludesRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitRequirementItem.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/RequirementAND.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/RequirementOR.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitRequiresAtLeastRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitMinNumberReached.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitMaxNumberReached.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/FailedUnitRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitExclusion.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/AbstractArmyRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/FailedRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitRequirementMaxNumber.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/UnitRequirementMinNumber.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/AbstractFailedRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/Delegates.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/WarFoundryCore.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/AbstractRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Requirements/AbstractUnitRequirement.cs" subtype="Code" buildaction="Compile" />
+    <File name="libs/ICSharpCode.SharpZipLib.dll" subtype="Code" buildaction="Nothing" />
+    <File name="api/WarFoundryLoader.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories" subtype="Directory" buildaction="Compile" />
+    <File name="api/Factories/AbstractNativeWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/WarFoundryFactoryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects" subtype="Directory" buildaction="Compile" />
+    <File name="api/Objects/Ability.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/ArmourType.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Army.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/ArmyCategory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Category.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/EquipmentItem.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/GameSystem.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/StagedLoadingRace.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Stat.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Stats.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/StatSlot.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/SystemStats.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/SystemStatsSet.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Unit.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/UnitEquipmentItem.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/UnitEquipmentItemObj.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/UnitType.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/IWarFoundryStagedLoadObject.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/WarFoundryObject.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/Xml" subtype="Directory" buildaction="Compile" />
+    <File name="api/Factories/Xml/WarFoundryXmlSaver.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/Xml/WarFoundryXmlFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/Xml/WarFoundryXmlElementName.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/AbstractNonNativeWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/IWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/AbstractWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Savers" subtype="Directory" buildaction="Compile" />
+    <File name="api/Savers/IWarFoundryFileSaver.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Savers/WarFoundrySaver.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/INonNativeWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Factories/INativeWarFoundryFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/Race.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/IWarFoundryNativeSourceObject.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/IWarFoundryObject.cs" subtype="Code" buildaction="Compile" />
+    <File name="api/Objects/StagedLoadingGameSystem.cs" subtype="Code" buildaction="Compile" />
+  </Contents>
+  <References>
+    <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Project" localcopy="True" refto="IBBoard" />
+    <ProjectReference type="Gac" localcopy="True" refto="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+    <ProjectReference type="Assembly" localcopy="True" refto="libs/ICSharpCode.SharpZipLib.dll" />
+  </References>
+</Project>
\ No newline at end of file
Binary file IBBoard.WarFoundry.API.pidb has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/CreateAndAddUnitCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,67 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for AddUnitCommand.
+	/// </summary>
+	public class CreateAndAddUnitCommand : Command
+	{
+		private UnitType addedUnitType;
+		private Army army;
+		private ArmyCategory cat;
+		private Unit addedUnit;
+
+		public CreateAndAddUnitCommand(UnitType toAdd, ArmyCategory catTo, Army armyTo)
+		{
+			addedUnitType = toAdd;
+			cat = catTo;
+			army = armyTo;
+		}
+
+		public CreateAndAddUnitCommand(UnitType toAdd, Category catTo, Army armyTo) : this (toAdd, armyTo.GetCategory(catTo), armyTo)
+		{
+		}
+
+		public override bool CanExecute()
+		{
+			return (addedUnitType!=null && army!=null);
+		}
+
+		public override string Description
+		{
+			get { return "Add unit of "+StringManipulation.CutToLength(addedUnitType.Name, 20)+" to the army"; }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Remove unit of "+StringManipulation.CutToLength(addedUnitType.Name, 20)+" from army"; }
+		}
+
+		public override bool Execute()
+		{
+			addedUnit = new Unit(addedUnitType, army);
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			cat.AddUnit(addedUnit);
+		}
+
+		public override void Undo()
+		{
+			cat.RemoveUnit(addedUnit);
+		}
+
+
+		public override string Name
+		{
+			get { return "Add new unit"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/RemoveUnitCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,57 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for RemoveUnitCommand.
+	/// </summary>
+	public class RemoveUnitCommand : Command
+	{
+		private Unit unit;
+		private ArmyCategory cat;
+
+		public RemoveUnitCommand(Unit toRemove)
+		{
+			unit = toRemove;
+			cat = unit.Category;
+		}
+
+		public override bool CanExecute()
+		{
+			return (unit!=null);
+		}
+
+		public override string Description
+		{
+			get { return "Remove an existing unit from the army"; }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Replace a removed unit"; }
+		}
+
+		public override bool Execute()
+		{
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			cat.RemoveUnit(unit);
+		}
+
+		public override void Undo()
+		{
+			cat.AddUnit(unit);
+		}
+
+		public override string Name
+		{
+			get { return "Remove unit"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/ReplaceUnitEquipmentCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,63 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for ReplaceUnitEquipmentCommand.
+	/// </summary>
+	public class ReplaceUnitEquipmentCommand : Command
+	{
+		private SetUnitEquipmentAmountCommand removeOldCommand, addNewCommand;
+		//private Unit unit;
+		//private EquipmentItem oldEquip, newEquip;
+		//private float newAmount, oldAmount;
+		
+		public ReplaceUnitEquipmentCommand(Unit unit, EquipmentItem oldItem, EquipmentItem newItem, float amount)
+		{
+			removeOldCommand = new SetUnitEquipmentAmountCommand(unit, oldItem, 0);
+			addNewCommand = new SetUnitEquipmentAmountCommand(unit, newItem, amount);
+		}
+
+		public override bool CanExecute()
+		{
+			return removeOldCommand.CanExecute() && addNewCommand.CanExecute();
+		}
+
+		public override string Description
+		{
+			get { return "Replace "+StringManipulation.CutToLength(removeOldCommand.EquipItem.Name, 20)+" with "+StringManipulation.CutToLength(addNewCommand.EquipItem.Name, 20)+ " for "+StringManipulation.CutToLength(removeOldCommand.Unit.Name, 20); }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Replace "+StringManipulation.CutToLength(addNewCommand.EquipItem.Name, 20)+" with "+StringManipulation.CutToLength(removeOldCommand.EquipItem.Name, 20)+ " for "+StringManipulation.CutToLength(removeOldCommand.Unit.Name, 20); }
+		}
+
+		public override bool Execute()
+		{
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			removeOldCommand.Redo();
+			addNewCommand.Redo();
+		}
+
+		public override void Undo()
+		{
+			addNewCommand.Undo();
+			removeOldCommand.Undo();
+		}
+
+
+		public override string Name
+		{
+			get { return "Replace required equipment"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/SetNameCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,58 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for SetNameCommand.
+	/// </summary>
+	public class SetNameCommand : Command
+	{
+		private WarFoundryObject obj;
+		private string newName, oldName;
+
+		public SetNameCommand(WarFoundryObject toRename, string name)
+		{
+			obj = toRename;
+			newName = name;
+			oldName = obj.Name;
+		}
+
+		public override bool CanExecute()
+		{
+			return (obj!=null && newName!=null && newName!="");
+		}
+
+		public override string Description
+		{
+			get { return "Rename "+oldName; }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Revert name of "+newName; }
+		}
+
+		public override bool Execute()
+		{
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			obj.Name = newName;
+		}
+
+		public override void Undo()
+		{
+			obj.Name = oldName;
+		}
+
+		public override string Name
+		{
+			get { return "Rename item"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/SetUnitEquipmentAmountCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,71 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for SetUnitEquipmentAmountCommand.
+	/// </summary>
+	public class SetUnitEquipmentAmountCommand : Command
+	{
+		private Unit unit;
+		private EquipmentItem equip;
+		private float newAmount, oldAmount;
+		
+		public SetUnitEquipmentAmountCommand(Unit unit, EquipmentItem item, float amount)
+		{
+			this.unit = unit;
+			equip = item;
+			newAmount = amount;
+			oldAmount = unit.GetEquipmentAmount(equip.ID);
+		}
+
+		public override bool CanExecute()
+		{
+			return (unit!=null && equip!=null);
+		}
+
+		public override string Description
+		{
+			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItemObj.FormatEquipmentAmount(equip, newAmount); }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Set "+StringManipulation.CutToLength(equip.Name, 20)+" amount for "+StringManipulation.CutToLength(unit.Name, 20)+" to "+UnitEquipmentItemObj.FormatEquipmentAmount(equip, oldAmount); }
+		}
+
+		public override bool Execute()
+		{
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			unit.SetEquipmentAmount(equip.ID, newAmount);
+		}
+
+		public override void Undo()
+		{
+			unit.SetEquipmentAmount(equip.ID, oldAmount);
+		}
+
+		public override string Name
+		{
+			get { return "Set equipment amount"; }
+		}
+
+		public EquipmentItem EquipItem
+		{
+			get { return equip; }
+		}
+
+		public Unit Unit
+		{
+			get { return unit; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Commands/SetUnitSizeCommand.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,58 @@
+using System;
+using IBBoard.Commands;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Commands
+{
+	/// <summary>
+	/// Summary description for SetNameCommand.
+	/// </summary>
+	public class SetUnitSizeCommand : Command
+	{
+		private Unit unit;
+		private int newSize, oldSize;
+
+		public SetUnitSizeCommand(Unit toResize, int size)
+		{
+			unit = toResize;
+			newSize = size;
+			oldSize = unit.Size;
+		}
+
+		public override bool CanExecute()
+		{
+			return (unit!=null && newSize >0 && oldSize > 0);
+		}
+
+		public override string Description
+		{
+			get { return "Change size of "+unit.Name; }
+		}
+
+		public override string UndoDescription
+		{
+			get { return "Revert size of "+unit.Name; }
+		}
+
+		public override bool Execute()
+		{
+			this.Redo();
+			return true;
+		}
+
+		public override void Redo()
+		{
+			unit.Size = newSize;
+		}
+
+		public override void Undo()
+		{
+			unit.Size = oldSize;
+		}
+
+		public override string Name
+		{
+			get { return "Change unit size"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Delegates.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API
+{
+	public delegate void ObjectChangedDelegate(WarFoundryObject oldValue, WarFoundryObject newValue);
+	public delegate void ArmyChangedDelegate(Army oldValue, Army newValue);
+	public delegate void GameSystemChangedDelegate(GameSystem oldValue, GameSystem newValue);
+	public delegate void ObjectAddDelegate(WarFoundryObject val);
+	public delegate void ObjectRemoveDelegate(WarFoundryObject val);	
+	public delegate void UnitAddDelegate(Unit val);
+	public delegate void UnitRemoveDelegate(Unit val);
+	public delegate void ObjectUpdatedDelegate(WarFoundryObject val, string updatedValName);
+	public delegate void DoubleValChangedDelegate(WarFoundryObject obj, double oldValue, double newValue);
+	public delegate void FloatValChangedDelegate(WarFoundryObject obj, float oldValue, float newValue);
+	public delegate void StringValChangedDelegate(WarFoundryObject obj, string oldValue, string newValue);
+	public delegate void IntValChangedDelegate(WarFoundryObject obj, int oldValue, int newValue);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/AbstractNativeWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,282 @@
+// WarFoundryXmlFactory.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Collections.Generic;
+using System.Text;
+using IBBoard;
+using IBBoard.IO;
+using IBBoard.Lang;
+using IBBoard.Logging;
+using IBBoard.Xml;
+using IBBoard.WarFoundry.API.Objects;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	/// <summary>
+	/// Base abstract class for all factories that load native WarFoundry data.
+	/// </summary>
+	public abstract class AbstractNativeWarFoundryFactory : AbstractWarFoundryFactory<ZipFile>, INativeWarFoundryFactory
+	{
+		protected static readonly string SYSTEM_ZIP_IDENTIFIER = "WarFoundry_System";
+		protected static readonly string RACE_ZIP_IDENTIFIER = "WarFoundry_Race";
+		protected static readonly string ARMY_ZIP_IDENTIFIER = "WarFoundry_Army";
+				
+		protected AbstractNativeWarFoundryFactory()
+		{
+			//Do nothing - just make the constructor non-public
+		}
+		
+		public abstract void CompleteLoading(IWarFoundryStagedLoadObject obj);
+		
+		protected override ZipFile GetFileAsSupportedType (FileInfo file)
+		{
+			ZipFile zip = null;
+			
+			try
+			{
+				zip = new ZipFile(file.FullName);
+			}
+			catch(ZipException ex)
+			{
+				//Silently dispose - we don't support the file and our other methods should handle that
+			}
+			
+			return zip;
+		}
+		
+		protected override bool CheckCanHandleFileFormat (ZipFile file)
+		{
+			bool canHandle = false;
+			
+			if (file!=null)
+			{			
+				canHandle = CheckCanHandleAsSystem(file) || CheckCanHandleAsRace(file) || CheckCanHandleAsArmy(file); 
+			}
+			
+			return canHandle;
+		}
+		
+		protected bool CheckCanHandleAsSystem(ZipFile file)
+		{
+			return file.ZipFileComment.StartsWith(SYSTEM_ZIP_IDENTIFIER) && CheckCanFindSystemFileContent(file);
+		}
+		
+		protected abstract bool CheckCanFindSystemFileContent(ZipFile file);
+		
+		protected bool CheckCanHandleAsRace(ZipFile file)
+		{
+			return file.ZipFileComment.StartsWith(RACE_ZIP_IDENTIFIER) && CheckCanFindRaceFileContent(file);
+		}
+		
+		protected abstract bool CheckCanFindRaceFileContent(ZipFile file);
+		
+		protected bool CheckCanHandleAsArmy(ZipFile file)
+		{
+			return file.ZipFileComment.StartsWith(ARMY_ZIP_IDENTIFIER) && CheckCanFindArmyFileContent(file);
+		}
+		
+		protected abstract bool CheckCanFindArmyFileContent(ZipFile file);
+		
+		protected override ICollection<IWarFoundryObject> DoCreateObjectsFromFile (ZipFile file)
+		{
+			ICollection<IWarFoundryObject> objects = null;
+			string comment = file.ZipFileComment;
+			IWarFoundryObject obj = null;
+				
+			if (comment.StartsWith(SYSTEM_ZIP_IDENTIFIER))
+			{
+				obj = CreateGameSystemFromFile(file);
+			}
+			else if (comment.StartsWith(RACE_ZIP_IDENTIFIER))
+			{
+				obj = CreateRaceFromFile(file);
+			}
+			else if (comment.StartsWith(ARMY_ZIP_IDENTIFIER))
+			{
+				obj = CreateArmyFromFile(file);
+			}
+			
+			if (obj!=null)
+			{
+				objects = new List<IWarFoundryObject>();
+				objects.Add(obj);
+			}
+			
+			return objects;
+		}
+
+		
+/*	
+		public override bool CanHandleArmyFileFormat(FileInfo file)
+		{
+			bool canHandle = false;
+			
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				canHandle = zip.ZipFileComment.StartsWith(ARMY_ZIP_IDENTIFIER) && CanHandleArmyFileFormat(zip);
+			}
+			catch (ZipException)
+			{
+				//Not a valid zip file so we can't handle it
+			}
+			
+			return canHandle;
+		}
+		
+		public override bool CanHandleRaceFileFormat(FileInfo file)
+		{
+			bool canHandle = false;
+			
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				canHandle = zip.ZipFileComment.StartsWith(RACE_ZIP_IDENTIFIER) && CanHandleRaceFileFormat(zip);
+			}
+			catch (ZipException)
+			{
+				//Not a valid zip file so we can't handle it
+			}
+			
+			return canHandle;
+		}
+		
+		public override bool CanHandleSystemFileFormat(FileInfo file)
+		{
+			bool canHandle = false;
+			
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				canHandle = zip.ZipFileComment.StartsWith(SYSTEM_ZIP_IDENTIFIER) && CanHandleSystemFileFormat(zip);
+			}
+			catch (ZipException)
+			{
+				//Not a valid zip file so we can't handle it
+			}
+			
+			return canHandle;
+		}
+		
+		public abstract bool CanHandleArmyFileFormat(ZipFile file);
+		public abstract bool CanHandleRaceFileFormat(ZipFile file);
+		public abstract bool CanHandleSystemFileFormat(ZipFile file);
+		
+		public override Army CreateArmyFromFile (FileInfo file)
+		{
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				return CreateArmyFromFile(zip);
+			}
+			catch(ZipException ex)
+			{
+				throw new InvalidFileException(Translation.GetTranslation("InvalidArmyFileException", "Cannot get Army for file {0} as it was not a recognised Army file", file.Name), ex);
+			}
+		}
+				
+		public override Race CreateRaceFromFile (FileInfo file)
+		{
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				return CreateRaceFromFile(zip);
+			}
+			catch(ZipException ex)
+			{
+				throw new InvalidFileException(Translation.GetTranslation("InvalidRaceFileException", "Cannot get Race for file {0} as it was not a recognised Race file", file.Name), ex);
+			}
+		}
+				
+		public override GameSystem CreateGameSystemFromFile (FileInfo file)
+		{
+			try
+			{
+				ZipFile zip = new ZipFile(file.FullName);
+				return CreateGameSystemFromFile(zip);
+			}
+			catch(ZipException ex)
+			{
+				throw new InvalidFileException(Translation.GetTranslation("InvalidGameSystemFileException", "Cannot get Game System for file {0} as it was not a recognised Race file", file.Name), ex);
+			}
+		}*/
+		
+		protected Army CreateArmyFromFile(ZipFile file)
+		{
+			Army army = CreateArmyFromStream(file, GetArmyDataStream(file));
+			//throw new InvalidFileException(Translation.GetTranslation("InvalidArmyFileException", "Cannot get Army for file {0} as it was not an Army file", file.Name));
+			return army;
+		}
+		
+		protected abstract Stream GetArmyDataStream(ZipFile file);
+		protected abstract Army CreateArmyFromStream(ZipFile file, Stream dataStream);
+		
+		protected Race CreateRaceFromFile(ZipFile file)
+		{
+			try
+			{
+				Race race = CreateRaceFromStream(file, GetRaceDataStream(file));			
+				//throw new InvalidFileException(Translation.GetTranslation("InvalidRaceFileException", "Cannot get Race for file {0} as it was not a Race file", file.Name));
+				return race;
+			}
+			catch (InvalidFileException ex)
+			{
+				throw new InvalidFileException("Data file "+file.Name+" was not a valid race file", ex);
+			}
+		}
+		
+		protected abstract Stream GetRaceDataStream(ZipFile file);
+		protected abstract Race CreateRaceFromStream(ZipFile file, Stream dataStream);
+		
+		protected GameSystem CreateGameSystemFromFile(ZipFile file)
+		{
+			GameSystem system = CreateGameSystemFromStream(file, GetGameSystemDataStream(file));		
+			//throw new InvalidFileException(Translation.GetTranslation("InvalidGameSystemFileException", "Cannot get Game System for file {0} as it was not a Game System file", file.Name));
+			return system;
+		}
+		
+		protected abstract Stream GetGameSystemDataStream(ZipFile file);
+		protected abstract GameSystem CreateGameSystemFromStream(ZipFile file, Stream dataStream);
+		
+		public override bool Equals (object o)
+		{
+			if (o == this)
+			{
+				return true;
+			}
+			else if (o == null || !(this.GetType().Equals(o.GetType())))
+			{
+				return false;
+			}
+			
+			return true;
+		}
+		
+		public override int GetHashCode ()
+		{
+			return GetType().FullName.GetHashCode();
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/AbstractNonNativeFileExtensionWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,64 @@
+// AbstractNonNativeFileExtensionWarFoundryFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Factories
+{	
+	public abstract class AbstractNonNativeFileExtensionWarFoundryFactory : AbstractNonNativeWarFoundryFactory<FileInfo>
+	{
+		protected abstract string ArmyFileExtension { get; }
+		protected abstract string RaceFileExtension { get; }
+		protected abstract string GameSystemFileExtension { get; }
+		
+		protected override bool CheckCanHandleFileFormat (FileInfo file)
+		{
+			return IsArmyFile(file) || IsRaceFile(file) || IsSystemFile(file);
+		}
+		
+		protected bool IsArmyFile(FileInfo file)
+		{
+			return ArmyFileExtension!=null && file.Name.ToLower().EndsWith(ArmyFileExtension);
+		}
+		
+		protected bool IsRaceFile(FileInfo file)
+		{
+			return RaceFileExtension!=null && file.Name.ToLower().EndsWith(RaceFileExtension);
+		}
+		
+		protected bool IsSystemFile(FileInfo file)
+		{
+			return GameSystemFileExtension!=null && file.Name.ToLower().EndsWith(GameSystemFileExtension);
+		}
+		
+		protected override FileInfo GetFileAsSupportedType (FileInfo file)
+		{
+			return file;
+		} 
+		
+		
+		protected abstract Army CreateArmyFromFile(FileInfo file);
+		protected abstract Race CreateRaceFromFile(FileInfo file);
+		protected abstract GameSystem CreateGameSystemFromFile(FileInfo file);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/AbstractNonNativeWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,31 @@
+// AbstractNonNativeWarFoundryFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.IO;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public abstract class AbstractNonNativeWarFoundryFactory<FILE_TYPE> : AbstractWarFoundryFactory<FILE_TYPE>, INonNativeWarFoundryFactory
+	{
+		public abstract string NonNativeDataType { get;	}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/AbstractWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,73 @@
+// AbstractWarFoundryFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public abstract class AbstractWarFoundryFactory<FILE_TYPE> : IWarFoundryFactory
+	{
+		public bool CanHandleFileFormat (FileInfo file)
+		{
+			return CheckCanHandleFileFormat(GetFileAsSupportedType(file));
+		}
+		
+		/// <summary>
+		/// Converts the <see cref="FileInfo"/> object in to the appropriate type for this class so that it can perform its checks. If no conversion is required (the test can be performed on a <see cref="FileInfo"/> object) the object should be returned with no modification. 
+		/// </summary>
+		/// <param name="file">
+		/// A <see cref="FileInfo"/> to get the supported source object from.
+		/// </param>
+		/// <returns>
+		/// An object of type <see cref="FILE_TYPE"/> that has been converted from the input <see cref="FileInfo"/> object, or <code>null</code> if the conversion cannot be made.
+		/// </returns>
+		protected abstract FILE_TYPE GetFileAsSupportedType(FileInfo file);
+		
+		/// <summary>
+		/// Checks whether the factory thinks it can load data from the file in its paramaterised type.
+		/// </summary>
+		/// <param name="file">
+		/// An object of the converted <see cref="FILE_TYPE"/> to check support for
+		/// </param>
+		/// <returns>
+		/// <code>true</code> if the factory thinks it can support the file, else <code>false</code>
+		/// </returns>
+		protected abstract bool CheckCanHandleFileFormat(FILE_TYPE file);
+		
+		public ICollection<IWarFoundryObject> CreateObjectsFromFile(FileInfo file)
+		{
+			return DoCreateObjectsFromFile(GetFileAsSupportedType(file));
+		}
+		
+		/// <summary>
+		/// Reads the data from the supplied converted <see cref="FILE_TYPE"/> object and returns it as a collection of loadable objects.
+		/// </summary>
+		/// <param name="file">
+		/// An object of the converted <see cref="FILE_TYPE"/> for the file to load data from
+		/// </param>
+		/// <returns>
+		/// A <see cref="ICollection`1"/> of <see cref="IWarFoundryObject"/>s that were loaded from the file object
+		/// </returns>
+		protected abstract ICollection<IWarFoundryObject> DoCreateObjectsFromFile(FILE_TYPE file);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/INativeWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,29 @@
+// INativeFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public interface INativeWarFoundryFactory : IWarFoundryFactory
+	{
+		//Marker interface
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/INonNativeWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,29 @@
+// INonNativeFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public interface INonNativeWarFoundryFactory : IWarFoundryFactory
+	{
+		string NonNativeDataType { get; } 
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/IWarFoundryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,52 @@
+// IWarFoundryFactory.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public interface IWarFoundryFactory
+	{
+		/// <summary>
+		/// Checks if the factory thinks it can handle the supplied file. Checks can be performed on file extension or some basic check of file content, or some other method.
+		/// </summary>
+		/// <param name="file">
+		/// A <see cref="FileInfo"/> for the file to check support for.
+		/// </param>
+		/// <returns>
+		/// <code>true</code> if the file appears to be supported for loading by this factory, else returns <code>false</code>
+		/// </returns>
+		bool CanHandleFileFormat(FileInfo file);	
+		
+		/// <summary>
+		/// Reads the data from the supplied file and returns it as a collection of loadable objects.
+		/// </summary>
+		/// <param name="file">
+		/// A <see cref="FileInfo"/> for the file to load data from
+		/// </param>
+		/// <returns>
+		/// A <see cref="ICollection`1"/> of <see cref="IWarFoundryObject"/>s that were loaded from the file
+		/// </returns>
+		ICollection<IWarFoundryObject> CreateObjectsFromFile(FileInfo file);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/WarFoundryFactoryFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,117 @@
+// AbstractNativeWarFoundryFactory.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using IBBoard;
+using IBBoard.Logging;
+
+namespace IBBoard.WarFoundry.API.Factories
+{
+	public class WarFoundryFactoryFactory
+	{
+		private Dictionary<Type, IWarFoundryFactory> factories = new Dictionary<Type, IWarFoundryFactory>();
+		private Type defaultType;
+		private static WarFoundryFactoryFactory factoryFactory;
+		
+		private WarFoundryFactoryFactory()
+		{
+		}
+		
+		public static WarFoundryFactoryFactory GetFactoryFactory()
+		{
+			if (factoryFactory == null)
+			{
+				factoryFactory = new WarFoundryFactoryFactory();
+			}
+			
+			return factoryFactory;
+		}
+		
+		public IWarFoundryFactory GetFactory()
+		{
+			return GetFactory(DefaultType);
+		}
+		
+		public IWarFoundryFactory GetFactory(Type cls)
+		{
+			cls = CheckType(cls);
+			
+			IWarFoundryFactory factory = null;	
+			factories.TryGetValue(cls, out factory);
+			
+			if (factory == null)
+			{
+				factory = null;
+				MethodInfo method = cls.GetMethod("CreateFactory");
+				
+				if (method!=null)
+				{
+					LogNotifier.Debug(GetType(), "Found CreateFactory method on " + cls.Name);
+					object temp = method.Invoke(null, new object[]{});
+					
+					if (temp is IWarFoundryFactory)
+					{
+						factory = (IWarFoundryFactory)temp; 
+						factories.Add(cls, factory);
+					}
+				}
+			
+				if (factory == null)
+				{
+					throw new ArgumentException("Could not create factory for class "+cls.FullName);
+				}
+			}
+		
+			return factory;
+		}
+		
+		public Type DefaultType
+		{
+			get { return defaultType; }
+			set {
+				value = CheckType(value);
+				defaultType = value;
+			}
+		}
+		
+		private Type CheckType(Type cls)
+		{
+			if (cls == null)
+			{
+				if (DefaultType!=null)
+				{
+					return DefaultType;
+				}
+				else
+				{
+					throw new InvalidOperationException("Class cannot be null when no default class is set");
+				}
+			}
+			else if (!typeof(IWarFoundryFactory).IsAssignableFrom(cls))
+			{
+				throw new ArgumentException("Class "+cls.FullName+" was not a subtype of "+typeof(IWarFoundryFactory).FullName);
+			}
+			
+			return cls;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/Xml/WarFoundryXmlElementName.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,82 @@
+// WarFoundryXmlElementNames.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using IBBoard.Xml;
+
+namespace IBBoard.WarFoundry.API.Factories.Xml
+{
+	/// <summary>
+	/// An enumeration class for valid WarFoundry XML elements, designed to imitate Java's extensible complex object enumerations. 
+	/// </summary>
+	public class WarFoundryXmlElementName : IXmlElementName, IExtendedEnum<string>
+	{
+		public static WarFoundryXmlElementName SYSTEM_ELEMENT = new WarFoundryXmlElementName("SYSTEM_ELEMENT", "system");
+		public static WarFoundryXmlElementName ARMY_ELEMENT = new WarFoundryXmlElementName("ARMY_ELEMENT", "army");
+		public static WarFoundryXmlElementName RACE_ELEMENT = new WarFoundryXmlElementName("RACE_ELEMENT", "race");
+		public static WarFoundryXmlElementName CATEGORIES_ELEMENT = new WarFoundryXmlElementName("CATEGORIES_ELEMENT", "categories");
+		public static WarFoundryXmlElementName CATEGORY_ELEMENT = new WarFoundryXmlElementName("CATEGORY_ELEMENT", "cat");
+		public static WarFoundryXmlElementName UNITTYPES_ELEMENT = new WarFoundryXmlElementName("UNITTYPES_ELEMENT", "units");
+		public static WarFoundryXmlElementName UNITTYPE_ELEMENT = new WarFoundryXmlElementName("UNITTYPE_ELEMENT", "unit");
+		public static WarFoundryXmlElementName RACE_EQUIPMENT_ITEMS_ELEMENT = new WarFoundryXmlElementName("RACE_EQUIPMENT_ITEMS_ELEMENT", "equipment");
+		public static WarFoundryXmlElementName RACE_EQUIPMENT_ITEM_ELEMENT = new WarFoundryXmlElementName("RACE_EQUIPMENT_ITEMS_ELEMENT", "equipmentItem");
+		
+		private static ICollection<WarFoundryXmlElementName> enumValues;
+		private string name;
+		private string val;
+		
+		private WarFoundryXmlElementName(string elemName, string elemVal)
+		{
+			name = elemName;
+			val = elemVal;
+		}
+		
+		public string Name
+		{
+			get {
+				return name;
+			}
+		}
+		
+		public string Value
+		{
+			get {
+				return val;
+			}
+		}
+		
+		/// <summary>
+		/// Gets an ICollection of the values so that they can be looped over like a standard enumeration.
+		/// </summary>
+		/// <returns>
+		/// A <see cref="ICollection`1"/> of all of the static 'enumeration' values of the class.
+		/// </returns>
+		public static ICollection<WarFoundryXmlElementName> GetEnumValues()
+		{
+			if (enumValues == null)
+			{
+				enumValues = new WarFoundryXmlElementName[]{SYSTEM_ELEMENT, ARMY_ELEMENT, RACE_ELEMENT, CATEGORIES_ELEMENT, CATEGORY_ELEMENT, UNITTYPES_ELEMENT, UNITTYPE_ELEMENT};
+			}
+			
+			return enumValues;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/Xml/WarFoundryXmlFactory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,696 @@
+// WarFoundryXmlFactory.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Collections.Generic;
+using System.Text;
+using IBBoard;
+using IBBoard.IO;
+using IBBoard.Lang;
+using IBBoard.Logging;
+using IBBoard.Xml;
+using IBBoard.WarFoundry.API.Requirements;
+using IBBoard.WarFoundry.API.Objects;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry.API.Factories.Xml
+{
+	/// <summary>
+	/// Summary description for WarFoundryXmlFactory.
+	/// </summary>
+	public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
+	{
+		private Dictionary<IWarFoundryObject, XmlDocument> extraData = new Dictionary<IWarFoundryObject, XmlDocument>();
+		private XmlResolver xmlResolver;
+
+		public static AbstractNativeWarFoundryFactory CreateFactory()
+		{
+			return new WarFoundryXmlFactory();
+		}
+		
+		protected WarFoundryXmlFactory() : base()
+		{
+			xmlResolver = new IBBXmlResolver(Constants.ExecutablePath);
+		}
+		
+		protected override bool CheckCanFindArmyFileContent(ZipFile file)
+		{
+			return file.FindEntry("data.armyx", true) > -1;
+		}
+		
+		protected override bool CheckCanFindSystemFileContent(ZipFile file)
+		{
+			return file.FindEntry("data.systemx", true) > -1;
+		}
+		
+		protected override bool CheckCanFindRaceFileContent(ZipFile file)
+		{
+			return file.FindEntry("data.racex", true) > -1;
+		}
+		
+		protected XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
+		{
+			XmlDocument doc = CreateXmlDocumentFromStream(stream);			
+			XmlElement elem = (XmlElement)doc.LastChild;
+			
+			if (!elem.Name.Equals(elementName.Value))
+			{
+				throw new InvalidFileException(String.Format("Root element of XML was not valid. Expected {0} but got {1}", elementName.Value, elem.Name));
+			}
+			
+			return elem;
+		}
+		
+		protected override Stream GetArmyDataStream(ZipFile file)
+		{
+			return file.GetInputStream(file.FindEntry("data.armyx", true));
+		}
+		
+		protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
+			return CreateArmyFromElement(file, elem);
+		}
+		
+		private Army CreateArmyFromElement(ZipFile file, XmlElement elem)
+		{
+			string name = elem.GetAttribute("name");
+			string systemID = elem.GetAttribute("gameSystem");
+			GameSystem system = WarFoundryLoader.GetDefault().GetGameSystem(systemID);
+			string raceID = elem.GetAttribute("race");
+			Race race = WarFoundryLoader.GetDefault().GetRace(system, raceID);
+			string pointsString = elem.GetAttribute("maxPoints");
+			int points = 0;
+			
+			try
+			{
+				points = int.Parse(pointsString);
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxPoints' of army '"+name+"' was not a valid number");
+			}
+			
+			Army army = new Army(race, name, points, file);//, this);
+			extraData[army] = elem.OwnerDocument;
+			return army;
+		}
+
+		protected override Stream GetGameSystemDataStream (ZipFile file)
+		{
+			return file.GetInputStream(file.FindEntry("data.systemx", true));
+		}
+		
+		protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
+			LogNotifier.Debug(GetType(), "Create GameSystem");
+			return CreateSystemFromElement(file, elem);
+		}
+		
+		private GameSystem CreateSystemFromElement(ZipFile file, XmlElement elem)
+		{
+			string id = elem.GetAttribute("id");
+			string name = elem.GetAttribute("name");
+			GameSystem system = new StagedLoadingGameSystem(id, name, this);
+			//system.SourceZipFile = file.;
+			extraData[system] = elem.OwnerDocument;
+			return system;
+		}
+		
+		protected override Stream GetRaceDataStream (ZipFile file)
+		{
+			return file.GetInputStream(file.FindEntry("data.racex", true));
+		}
+		
+		protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
+			LogNotifier.Debug(GetType(), "Create Race");
+			return CreateRaceFromElement(file, elem);
+		}
+		
+		private Race CreateRaceFromElement(ZipFile file, XmlElement elem)
+		{
+			string id = elem.GetAttribute("id");
+			string subid = elem.GetAttribute("subid");
+			string systemID = elem.GetAttribute("system");
+			string name = elem.GetAttribute("name");
+			Race race = new StagedLoadingRace(id, subid, name, systemID, this);
+			//race.SourceZipFile = file; //TODO reference source file
+			extraData[race] = elem.OwnerDocument;
+			return race;
+		}
+
+		/*public WarFoundryObject CreateObjectFromStream(ZipFile file, Stream stream)
+		{
+			try
+			{
+				WarFoundryObject obj = LoadFileObjectFromElement(file, elem);
+				
+				if (obj != null)
+				{			
+					extraData[obj] = doc;
+					return obj;
+				}
+				else
+				{
+					throw new InvalidFileException(String.Format(Translation.GetTranslation("ErrorInvalidXmlFile", "XML file '{0}' was not a loadable XML file. Please ensure it is a valid and supported WarFoundry XML file."), file.Name));
+				}
+			}
+			catch (XmlSchemaException ex)
+			{
+				throw new InvalidFileException(String.Format(Translation.GetTranslation("ErrorInvalidXmlFile", "Failed to parse invalid XML data file in {0}. Error at line {1} position {2}: {3}"), file.Name, ex.LineNumber, ex.LinePosition, ex.Message.Substring(0, ex.Message.IndexOf(".")+1)), ex);
+			}
+			catch (InvalidFileException ex)
+			{
+				throw new InvalidFileException(String.Format(Translation.GetTranslation("ErrorInvalidNamedXmlFile", "XML data file in '{0}' was not a valid XML file. It should contain three child nodes - XML definition, DocType and root node."), file.Name), ex);
+			}
+		}
+		
+		private WarFoundryObject LoadFileObjectFromElement(ZipFile file, XmlElement elem)
+		{
+			WarFoundryObject obj = null;
+				
+			if (elem.Name.Equals(WarFoundryXmlElementName.SYSTEM_ELEMENT.Value))
+			{
+				logger.Debug("Create GameSystem");
+				obj = CreateSystemFromElement(file, elem);
+			}
+			else if (elem.Name.Equals(WarFoundryXmlElementName.RACE_ELEMENT.Value))
+			{
+				logger.Debug("Create Race");
+				obj = CreateRaceFromElement(file, elem);
+			}
+			
+			return obj;
+		}*/
+
+		public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
+		{		
+			LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID);
+				
+			if (!obj.IsFullyLoaded)
+			{			
+				XmlDocument extra = extraData[obj];
+				
+				if (obj is GameSystem)
+				{
+					GameSystem system = (GameSystem)obj;
+					XmlNode elem = extra.LastChild;
+					
+					XmlNode catsElem = elem.FirstChild;					
+					Category[] cats;
+					List<Category> catList = new List<Category>();
+					WarFoundryObject tempObj;
+					
+					foreach (XmlElement cat in catsElem.ChildNodes)
+					{
+						tempObj = CreateObjectFromElement(cat);
+						
+						if (tempObj is Category)
+						{
+							catList.Add((Category)tempObj);
+						}
+						else
+						{
+							LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml);
+						}
+					}
+					
+					cats = catList.ToArray();
+					LogNotifier.DebugFormat(GetType(), "Found {0} categories", cats.Length);
+					
+					XmlElement statsElem = (XmlElement)catsElem.NextSibling;					
+					Dictionary<string, SystemStats> sysStats = CreateSystemStatsSetFromElement(statsElem);
+					string defaultStatsID = statsElem.GetAttribute("defaultStats");
+										
+					LogNotifier.DebugFormat(GetType(), "Complete loading of {0}", system.Name);
+					system.Categories = cats;
+					system.SystemStats = new SystemStatsSet(sysStats); 
+					system.StandardSystemStatsID = defaultStatsID;
+				}
+				else if (obj is Race)
+				{
+					Race race = (Race)obj;
+					XmlNode elem = extra.LastChild;
+					XmlNode colNode = elem.FirstChild;
+					
+					Dictionary<string, UnitType> unitTypes = new Dictionary<string, UnitType>();
+					
+					foreach (XmlElement node in colNode.ChildNodes)
+					{
+						UnitType type = CreateUnitTypeFromElement(node, race, race.GameSystem);
+						unitTypes.Add(type.ID, type);
+					}
+					
+					colNode = colNode.NextSibling;
+					List<Category> catOverrides = new List<Category>();
+					
+					if (colNode!=null && colNode.Name == WarFoundryXmlElementName.CATEGORIES_ELEMENT.Value)
+					{
+						foreach (XmlElement node in colNode.ChildNodes)
+						{
+							catOverrides.Add(CreateCategoryFromElement(node));
+						}
+						
+						colNode = colNode.NextSibling;
+					}
+						
+					Dictionary<string, EquipmentItem> raceEquipment = new Dictionary<string, EquipmentItem>();
+					
+					if (colNode!=null && colNode.Name == WarFoundryXmlElementName.RACE_EQUIPMENT_ITEMS_ELEMENT.Value)
+					{
+						foreach (XmlElement node in colNode.ChildNodes)
+						{
+							EquipmentItem item = CreateEquipmentItemFromElement(node, race);
+							raceEquipment.Add(item.ID, item);
+						}
+					}
+					
+					Dictionary<string, Ability> raceAbilities = new Dictionary<string, Ability>();
+					//TODO: Load abilities
+					
+					LogNotifier.DebugFormat(GetType(), "Complete loading of {0}", race.Name);
+					race.Categories = catOverrides.ToArray();
+					race.SetUnitTypes(unitTypes);
+					race.SetEquipmentItems(raceEquipment);
+					race.SetAbilities(raceAbilities);
+				}
+			}
+			else
+			{
+				LogNotifier.Debug(GetType(), "Object is already fully loaded");
+			}
+		}
+		
+		protected XmlDocument CreateXmlDocumentFromStream(Stream stream)
+		{
+			XmlDocument doc = new XmlDocument();
+			XmlReaderSettings settings = new XmlReaderSettings();
+			settings.XmlResolver = xmlResolver;
+			settings.ValidationType = ValidationType.DTD;
+			settings.ProhibitDtd = false;
+			settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
+			XmlReader reader = XmlReader.Create(stream, settings);
+			
+			try
+			{
+				doc.Load(reader);			
+			}
+			//Don't catch XMLSchemaExceptions - let them get thrown out
+			finally
+			{
+				reader.Close();
+			}
+			
+			if (doc.ChildNodes.Count!=3)
+			{
+				throw new InvalidFileException(Translation.GetTranslation("ErrorInvalidXmlFile", "XML file was not a valid XML file. It should contain three child nodes - XML definition, DocType and root node."));
+			}
+
+			return doc;
+		}
+
+		protected XmlDocument CreateXmlDocumentFromString(string xmlString)
+		{			
+			XmlReaderSettings settings = new XmlReaderSettings();
+			settings.XmlResolver = xmlResolver;
+			settings.ValidationType = ValidationType.DTD;
+			settings.ProhibitDtd = false;
+			settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
+			XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xmlString)), settings);
+			XmlDocument doc = new XmlDocument();
+
+			try
+			{
+				doc.Load(reader);
+			}
+			catch(XmlSchemaException ex)
+			{
+				throw new InvalidFileException(Translation.GetTranslation("ErrorInvalidXmlString", "Failed to parse invalid XML string"), ex);
+			}
+			finally
+			{
+				//We might not need to make sure the memory stream is closed, but do it just in case
+				reader.Close();
+			}
+			
+			if (doc.ChildNodes.Count!=3)
+			{
+				throw new InvalidFileException(String.Format(Translation.GetTranslation("ErrorInvalidXmlFile", "XML string was not a valid XML file. It should contain three child nodes - XML definition, DocType and root node.")));
+			}
+
+			return doc;
+		}
+					
+		private WarFoundryObject CreateObjectFromElement(XmlElement elem)
+		{
+			WarFoundryObject obj = null;
+			LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name);
+			
+			if (elem.Name.Equals(WarFoundryXmlElementName.CATEGORY_ELEMENT.Value))
+			{
+				LogNotifier.Debug(GetType(), "Create Category");
+				obj = CreateCategoryFromElement(elem);
+			}
+			else
+			{
+				LogNotifier.Debug(GetType(), "No match");
+			}
+			
+			return obj;
+		}
+		
+		private Category CreateCategoryFromElement(XmlElement elem)
+		{
+			string id = elem.GetAttribute("id");
+			string name = elem.GetAttribute("name");
+			int minPc, maxPc, minPts, maxPts, minChoices, maxChoices, baseValue, incValue, incAmount;
+			
+			try
+			{
+				minPc = int.Parse(elem.GetAttribute("minPercentage"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minPercentage' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				maxPc = int.Parse(elem.GetAttribute("maxPercentage"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxPercentage' of category "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				minPts = int.Parse(elem.GetAttribute("minPoints"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minPoints' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				maxPts = int.Parse(elem.GetAttribute("maxPoints"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxPoints' of category "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				minChoices = int.Parse(elem.GetAttribute("minChoices"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minChoices' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				maxChoices = int.Parse(elem.GetAttribute("maxChoices"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxChoices' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				baseValue = int.Parse(elem.GetAttribute("baseValue"));
+			
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'baseValue' of category "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				incValue = int.Parse(elem.GetAttribute("incValue"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'incValue' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				incAmount = int.Parse(elem.GetAttribute("incAmount"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'incAmount' of category "+id+" was not a valid number");
+			}
+			
+			return new Category(id, name, minPts, maxPts, minPc, maxPc, minChoices, maxChoices, baseValue, incValue, incAmount);
+		}
+						
+		private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system)
+		{
+			string id = elem.GetAttribute("id");
+			string name = elem.GetAttribute("typeName");
+			string mainCatID = elem.GetAttribute("cat");
+			int minNum, maxNum, minSize, maxSize, baseSize;//TODO: Add base size
+			float points, unitPoints;
+			Stats stats;
+			List<UnitRequirement> unitRequirements = new List<UnitRequirement>();
+			bool found = false;
+			List<string> catIDs = new List<string>();
+			string catID;
+			
+			try
+			{
+				minNum = int.Parse(elem.GetAttribute("minNum"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minNum' of unit "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				maxNum = int.Parse(elem.GetAttribute("maxNum"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxNum' of unit "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				minSize = int.Parse(elem.GetAttribute("minSize"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minSize' of unit "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				maxSize = int.Parse(elem.GetAttribute("maxSize"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maxSize' of unit "+id+" was not a valid number");
+			}
+			
+			if (minSize > maxSize && maxSize!=-1)
+			{
+				minSize = maxSize;
+			}
+			
+			try
+			{
+				points = int.Parse(elem.GetAttribute("points"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'points' of unit "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				unitPoints = int.Parse(elem.GetAttribute("unitPoints"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'trooperPoints' of unit "+id+" was not a valid number");
+			}
+			
+			XmlNode node = elem.FirstChild;
+			
+			foreach(XmlElement cat in node.ChildNodes)
+			{
+				catID = cat.GetAttribute("catID");
+				catIDs.Add(catID);
+				
+				if (catID == mainCatID)
+				{
+					found = true;
+				}
+			}
+			
+			if (!found)
+			{
+				throw new InvalidFileException("The main cat "+mainCatID+" was not found in the list of categories for unit "+id);
+			}
+			
+			node = node.NextSibling;			
+			stats = ParseUnitStats((XmlElement)node, system);
+			//TODO: Add unit requirements
+			UnitType type = new UnitType(id, name, mainCatID, catIDs.ToArray(), minNum, maxNum, minSize, maxSize, unitPoints, points, stats, unitRequirements.ToArray(), parentRace);
+			
+			return type;
+		}
+		
+		private Stats ParseUnitStats(XmlElement elem, GameSystem system)
+		{
+			List<Stat> statsList = new List<Stat>();
+			String statsID = elem.GetAttribute("statSet");
+			SystemStats statsSet;
+			
+			if (statsID == "")
+			{
+				statsSet = system.StandardSystemStats;
+			}
+			else
+			{
+				statsSet = system.SystemStats[statsID];
+			}
+			
+			Stats stats = new Stats(statsSet);
+			
+			foreach (XmlElement stat in elem.ChildNodes)
+			{
+				String statID = stat.GetAttribute("name");
+				StatSlot slot = statsSet[statID];
+				
+				if (slot!=null)
+				{
+					statsList.Add(new Stat(slot, stat.InnerText));
+				}
+				else
+				{
+					throw new InvalidFileException("The stat "+statID+" was not found in stats set "+statsID);
+				}
+			}
+			
+			stats.SetStats(statsList);
+			
+			return stats;
+		}
+		
+		private Dictionary<string, SystemStats> CreateSystemStatsSetFromElement(XmlElement elem)
+		{
+			Dictionary<string, SystemStats> dict = new Dictionary<string,SystemStats>();
+			
+			foreach (XmlElement stats in elem.ChildNodes)
+			{
+				SystemStats sysStats = CreateSystemStatsFromElement(stats);
+				dict.Add(sysStats.ID, sysStats);
+			}
+			
+			return dict;
+		}
+		
+		private SystemStats CreateSystemStatsFromElement(XmlElement elem)
+		{
+			List<StatSlot> slots = new List<StatSlot>();
+			string id = elem.GetAttribute("id");	
+			
+			foreach (XmlElement slot in elem.ChildNodes)
+			{
+				StatSlot statSlot = new StatSlot(slot.GetAttribute("name"));
+				slots.Add(statSlot);
+			}
+			
+			return new SystemStats(id, slots.ToArray());
+		}
+		
+		private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race)
+		{
+			string id = elem.GetAttribute("id");
+			string name = elem.GetAttribute("name");
+			float cost = 0, min = 0, max = 0;
+			ArmourType armourType;
+			
+			try
+			{
+				cost = float.Parse(elem.GetAttribute("cost"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'cost' of equipment item "+id+" was not a valid number");
+			}			
+			
+			try
+			{
+				min = float.Parse(elem.GetAttribute("min"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'min' of equipment item "+id+" was not a valid number");
+			}			
+			
+			try
+			{
+				max = float.Parse(elem.GetAttribute("max"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'max' of equipment item "+id+" was not a valid number");
+			}
+			
+			try
+			{
+				armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType"));
+			}
+			catch(FormatException)
+			{
+				throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration");
+			}
+			
+			if (elem.ChildNodes.Count>0)
+			{
+				//It has stats!
+				//TODO: Parse equipment stats
+			}
+			
+			return new EquipmentItem(id, name, cost, min, max, armourType, race);
+		}
+		
+		private void ValidationEventMethod(object sender, ValidationEventArgs e)
+		{
+			//TODO: Fire a validation failure event
+    		LogNotifier.WarnFormat(GetType(), "Validation Error: {0}", e.Message);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Factories/Xml/WarFoundryXmlSaver.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Factories.Xml
+{
+	public class WarFoundryXmlSaver
+	{
+		//FIXME: Rework to saving files in Zips
+		private static WarFoundryXmlSaver saver;
+		private static List<Type> saveAsTypes;
+		private Dictionary<WarFoundryObject, string> savePaths = new Dictionary<WarFoundryObject,string>();
+		
+		public static WarFoundryXmlSaver GetSaver()
+		{
+			if (saver == null)
+			{
+				saveAsTypes = new List<Type>();
+				saveAsTypes.Add(typeof(Army));
+				saver = new WarFoundryXmlSaver();
+			}
+			
+			return saver;
+		}
+		
+		public bool SaveAs(WarFoundryObject toSave, string saveAsPath)
+		{
+			if (CanSaveType(toSave))
+			{
+				FileStream fs = null;
+				bool success = false;
+				
+				try
+				{
+					fs = new FileStream(saveAsPath, FileMode.Create, FileAccess.Write);
+					byte[] bytes = StringManipulation.StringToBytes(CreateXmlString(toSave));
+					fs.Write(bytes, 0, bytes.Length);
+					fs.Flush();
+					savePaths.Add(toSave, saveAsPath);
+					success = true;
+				}
+				finally
+				{
+					if (fs!=null && fs.CanWrite)
+					{
+						fs.Close();
+					}
+				}
+
+				return success;
+			}
+			else
+			{
+				throw new ArgumentException("Cannot directly save objects of type "+toSave.GetType());
+			}
+		}
+		
+		public bool Save(WarFoundryObject toSave)
+		{
+			if (CanSave(toSave))
+			{
+				return SaveAs(toSave, savePaths[toSave]);
+			}
+			else
+			{
+				throw new InvalidOperationException("Cannot save an object that has not previously been saved using SaveAs");
+			}
+		}
+		
+		private string CreateXmlString(WarFoundryObject toSave)
+		{
+			return ""; //TODO: Create XML string as appropriate
+		}
+		
+		public bool CanSaveAs(WarFoundryObject obj)
+		{
+			return CanSaveType(obj);
+		}
+		
+		public bool CanSave(WarFoundryObject obj)
+		{
+			return savePaths.ContainsKey(obj);
+		}
+		
+		public bool CanSaveType(WarFoundryObject obj)
+		{
+			return saveAsTypes.Contains(obj.GetType());
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Ability.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,12 @@
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public class Ability : WarFoundryObject
+	{
+		public Ability()
+		{
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/ArmourType.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,29 @@
+// ArmourType.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public enum ArmourType
+	{
+		None = 0, Shield = 1, LightArmour = 2, LightArmourShield = 3, HeavyArmour = 4, HeavyArmourShield = 5, Barding = 8, BardingShield = 9, BardingLightArmour = 10, BardingLightArmourShield = 11, BardingHeavyArmour = 12, BardingHeavyArmourShield = 13
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Army.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,261 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+using IBBoard.WarFoundry.API;
+using IBBoard.WarFoundry.API.Factories;
+using IBBoard.WarFoundry.API.Requirements;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for Army.
+	/// </summary>
+	public class Army : WarFoundryObject
+	{
+		//private GameSystem system;
+		private Race armyRace;
+		private int maxPoints;
+		private double pointsTotal;
+		private ArmyCategory[] categories;
+
+		public event ObjectAddDelegate UnitAdded;
+		public event ObjectRemoveDelegate UnitRemoved;
+		public event FailedUnitRequirementDelegate FailedRequirement;
+		public event DoubleValChangedDelegate PointsValueChanged;
+		private DoubleValChangedDelegate PointsValueChangedMethod;
+		
+		public Army(Race race, string armyName, int maxArmyPoints/*, AbstractNativeWarFoundryFactory factory*/) : this(race, armyName, maxArmyPoints, null/*, factory*/)
+		{
+		}
+
+		public Army(Race race, string armyName, int maxArmyPoints, ZipFile file/*, AbstractNativeWarFoundryFactory factory*/) : base(armyName/*, factory*/)
+		{
+			armyRace = race;
+			Name = armyName;
+			maxPoints = maxArmyPoints;
+			PointsValueChangedMethod = new DoubleValChangedDelegate(PointsValueChangedHandler);
+		}
+		
+		public ArmyCategory GetCategory(Category cat)
+		{
+			foreach (ArmyCategory armyCat in Categories)
+			{
+				if (armyCat.Category.Equals(cat))
+				{
+					return armyCat;
+				}
+			}
+
+			return null;
+		}
+
+		public ArmyCategory[] Categories
+		{
+			get 
+			{
+				if (categories==null)
+				{
+					Category[] raceCats = Race.Categories;
+					ArmyCategory cat;
+					int raceCatCount = raceCats.Length;
+					categories = new ArmyCategory[raceCatCount];
+
+					for (int i = 0; i < raceCatCount; i++)
+					{
+						cat = new ArmyCategory(this, raceCats[i]);
+						categories[i] = cat;
+						cat.PointsValueChanged+= PointsValueChangedMethod;
+						cat.UnitAdded+=new ObjectAddDelegate(Army_UnitAdded);
+						cat.UnitRemoved+=new ObjectRemoveDelegate(Army_UnitRemoved);
+						cat.RequirementsFailed+=new FailedUnitRequirementDelegate(Army_FailedRequirement);
+					}
+				}
+
+				return categories;
+			}
+		}
+
+		public Race Race
+		{
+			get { return armyRace; }
+		}
+
+		public GameSystem GameSystem
+		{
+			get { return (armyRace!=null ? armyRace.GameSystem : null); }
+		}
+
+		protected void OnUnitAdded(Unit unit)
+		{
+			OnUnitAdded(unit, null);
+		}
+
+		protected void OnUnitAdded(Unit unit, List<FailedUnitRequirement> failedReqs)
+		{
+			if (UnitAdded!=null)
+			{
+				UnitAdded(unit);
+			}
+
+			if (FailedRequirement!=null && failedReqs!=null && failedReqs.Count > 0)
+			{
+				FailedRequirement(failedReqs);
+			}
+		}
+
+		protected void OnUnitRemoved(Unit unit)
+		{
+			OnUnitRemoved(unit, null);
+		}
+
+		protected void OnUnitRemoved(Unit unit, List<FailedUnitRequirement> failedReqs)
+		{
+			if (UnitRemoved!=null)
+			{
+				UnitRemoved(unit);
+			}
+
+			if (FailedRequirement!=null && failedReqs!=null && failedReqs.Count > 0)
+			{
+				FailedRequirement(failedReqs);
+			}
+		}
+
+		private void OnPointsValueChanged(double oldValue, double newValue)
+		{
+			if (PointsValueChanged!=null)
+			{
+				PointsValueChanged(this, oldValue, newValue);
+			}
+		}
+		
+		private double TotalPoints
+		{
+			get { return pointsTotal; }
+			set
+			{
+				double oldPoints = pointsTotal;
+				pointsTotal = value;
+
+				if (oldPoints!=pointsTotal)
+				{
+					OnPointsValueChanged(oldPoints, pointsTotal);
+				}
+			}
+		}
+
+		public double PointsTotal
+		{
+			get { return TotalPoints; }
+		}
+
+		public Unit[] GetUnits(Category cat)
+		{
+			return GetUnits(this.GetCategory(cat));
+		}
+
+		public Unit[] GetUnits(ArmyCategory cat)
+		{
+			return cat.GetUnits();
+		}
+
+		public Unit[] GetUnits()
+		{
+			ArrayList fullList = new ArrayList();
+
+			foreach(ArmyCategory cat in Categories)
+			{
+				foreach(Unit unit in cat.GetUnits())
+				{
+					if (!fullList.Contains(unit))
+					{
+						fullList.Add(unit);
+					}
+				}
+			}
+
+			return (Unit[])fullList.ToArray(typeof(Unit));
+		}
+
+		public int MaxPoints
+		{
+			get { return maxPoints; }
+			set 
+			{
+				if (value > 0)
+				{
+					maxPoints = value;
+				}
+			}
+		}
+
+		private void PointsValueChangedHandler(WarFoundryObject obj, double oldVal, double newVal)
+		{
+			if (obj is ArmyCategory)
+			{
+				double points = 0;
+
+				foreach (ArmyCategory cat in Categories)
+				{
+					points+= cat.PointsTotal;
+				}
+
+				TotalPoints = points;
+			}
+		}
+
+		public List<FailedUnitRequirement> CanAddUnit(Unit unit)
+		{
+			return CanAddUnitType(unit.UnitType);
+		}
+
+		public List<FailedUnitRequirement> CanAddUnitType(UnitType unitType)
+		{
+			return unitType.CanAddToArmy(this);
+		}
+
+		public List<FailedUnitRequirement> CanRemoveUnit(Unit unit)
+		{
+			return CanRemoveUnitType(unit.UnitType);
+		}
+
+		public List<FailedUnitRequirement> CanRemoveUnitType(UnitType unitType)
+		{
+			return unitType.CanRemoveFromArmy(this);
+		}
+
+		public int GetUnitTypeCount(UnitType unitType)
+		{
+			int count = 0;
+
+			foreach (ArmyCategory cat in Categories)
+			{
+				count+= cat.GetUnitTypeCount(unitType);
+			}
+
+			return count;
+		}
+
+		private void Army_UnitAdded(object val)
+		{
+			OnUnitAdded((Unit)val);
+		}
+
+		private void Army_UnitRemoved(object val)
+		{
+			OnUnitRemoved((Unit)val);
+		}
+
+		private void Army_FailedRequirement(List<FailedUnitRequirement> failedRequirements)
+		{
+			if (FailedRequirement!=null)
+			{
+				FailedRequirement(failedRequirements);
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/ArmyCategory.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Requirements;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for ArmyCategory.
+	/// </summary>
+	public class ArmyCategory : WarFoundryObject
+	{
+		private Category category;
+		private Army parentArmy;
+		private double pointsTotal;
+		private List<Unit> units;
+		private Dictionary<string, int> unitTypes;
+		private DoubleValChangedDelegate PointsValueChangedMethod;
+		public event DoubleValChangedDelegate PointsValueChanged;
+		public event ObjectAddDelegate UnitAdded;
+		public event ObjectRemoveDelegate UnitRemoved;
+		public event FailedUnitRequirementDelegate RequirementsFailed;
+
+		public ArmyCategory(Army army, Category cat) : base()
+		{
+			parentArmy = army;
+			category = cat;
+			cat.NameChanged+=new StringValChangedDelegate(cat_NameChanged);
+			PointsValueChangedMethod = new DoubleValChangedDelegate(PointsValueChangedHandler);
+			units = new List<Unit>();
+			unitTypes = new Dictionary<string,int>();
+		}
+
+		public Category Category
+		{
+			get { return category; }
+		}
+
+		public Army ParentArmy
+		{
+			get { return parentArmy; }
+		}
+
+		public override string ID
+		{
+			get
+			{
+				return Category.ID;
+			}
+			set
+			{
+				Category.ID = value;
+			}
+		}
+
+		public override string Name
+		{
+			get { return category.Name; }
+			set 
+			{
+				category.Name = value;
+			}
+		}
+
+		public void AddUnit(Unit unit)
+		{
+			List<FailedUnitRequirement> failedReqs = ParentArmy.CanAddUnit(unit);
+
+			units.Add(unit);
+			unit.Army = ParentArmy;
+			unit.Category = this;
+			unit.PointsValueChanged+= PointsValueChangedMethod;
+			int unitTypeCount;
+			unitTypes.TryGetValue(unit.UnitType.ID, out unitTypeCount);
+			unitTypes[unit.UnitType.ID] = (int)unitTypeCount + 1;
+			TotalPoints+= unit.PointsValue;
+			OnUnitAdded(unit, failedReqs);
+		}
+
+		public void RemoveUnit(Unit unit)
+		{
+			List<FailedUnitRequirement> failedReqs = ParentArmy.CanRemoveUnit(unit);
+			units.Remove(unit);
+			unit.Army = null;
+			unitTypes[unit.UnitType.ID] = ((int)unitTypes[unit.UnitType.ID])-1;
+			TotalPoints-= unit.PointsValue;
+			unit.PointsValueChanged-= PointsValueChangedMethod;
+			OnUnitRemoved(unit, failedReqs);
+		}
+
+		public int GetUnitTypeCount(UnitType unitType)
+		{
+			return unitTypes.ContainsKey(unitType.ID) ? (int)unitTypes[unitType.ID] : 0;
+		}
+
+		public Unit[] GetUnits()
+		{
+			return units.ToArray();
+		}
+
+		private double TotalPoints
+		{
+			get { return pointsTotal; }
+			set 
+			{
+				double oldVal = pointsTotal;
+				pointsTotal = value;
+
+				if (oldVal!=pointsTotal)
+				{
+					OnPointsValueChanged(oldVal, pointsTotal);
+				}
+			}
+		}
+
+		public double PointsTotal
+		{
+			get { return TotalPoints; }
+		}
+
+		private void PointsValueChangedHandler(WarFoundryObject obj, double oldVal, double newVal)
+		{
+			if (obj is Unit)
+			{
+				double diff = newVal - oldVal;
+				TotalPoints+= diff;
+			}
+		}
+
+		private void OnUnitAdded(Unit unit, List<FailedUnitRequirement> failedReqs)
+		{
+			if (UnitAdded!=null)
+			{
+				UnitAdded(unit);
+			}
+
+			if (RequirementsFailed!=null && failedReqs!=null && failedReqs.Count > 0)
+			{
+				RequirementsFailed(failedReqs);
+			}
+		}
+
+		private void OnUnitRemoved(Unit unit, List<FailedUnitRequirement> failedReqs)
+		{
+			if (UnitRemoved!=null)
+			{
+				UnitRemoved(unit);
+			}
+
+			if (RequirementsFailed!=null && failedReqs!=null && failedReqs.Count>0)
+			{
+				RequirementsFailed(failedReqs);
+			}
+		}
+
+		protected virtual void OnPointsValueChanged(double oldValue, double newValue)
+		{
+			if (PointsValueChanged!=null)
+			{
+				PointsValueChanged(this, oldValue, newValue);
+			}
+		}
+
+		protected void cat_NameChanged(WarFoundryObject obj, string oldValue, string newValue)
+		{
+			OnNameChanged(oldValue, newValue);
+		}
+				
+		public int GetPointsPercentage()
+		{
+			return (int)Math.Round((PointsTotal / ParentArmy.MaxPoints) * 100, 0);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Category.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,158 @@
+using System;
+using System.Xml;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for Category.
+	/// </summary>
+	public class Category : WarFoundryObject
+	{
+		private int minPts, maxPts, minPc, maxPc, minChoice, maxChoice, baseVal, incVal, incAmount;
+		/*private GameSystem system;*/
+		
+		public Category(string id, string name, int minPoints, int maxPoints, int minPercent, int maxPercent, int minChoices, int maxChoices, int baseValue, int incrementValue, int incrementAmount) : base(id, name)
+		{
+			minPts = minPoints;
+			maxPts = maxPoints;
+			minPc = minPercent;
+			maxPc = maxPercent;
+			baseVal = baseValue;
+			incVal = incrementValue;
+			incAmount = incrementAmount;
+		}
+		
+		/*public Category(XmlElement node, GameSystem gameSystem, AbstractNativeWarFoundryFactory factory) : base(factory)
+		{
+			//system = gameSystem;
+			ID = node.GetAttribute("id");
+			Name = node.GetAttribute("name");
+
+			try
+			{
+				min = int.Parse(node.GetAttribute("minimum"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'minimum' of category "+id+" was not a valid number");
+			}
+
+			try
+			{
+				max = int.Parse(node.GetAttribute("maximum"));
+			}
+			catch(FormatException)
+			{
+				throw new FormatException("Attribute 'maximum' of category "+id+" was not a valid number");
+			}
+
+			string val = "";
+			val = node.GetAttribute("baseValue");
+
+			if (val!="")
+			{
+				try
+				{
+					baseValue = int.Parse(val);
+				
+				}
+				catch(FormatException)
+				{
+					throw new FormatException("Attribute 'baseValue' of category "+id+" was not a valid number");
+				}
+			}
+
+			val = node.GetAttribute("incValue");
+
+			if (val!="")
+			{
+				try
+				{
+					incValue = int.Parse(val);
+				}
+				catch(FormatException)
+				{
+					throw new FormatException("Attribute 'incValue' of category "+id+" was not a valid number");
+				}
+			}
+
+			val = node.GetAttribute("incAmount");
+
+			if (val!="")
+			{
+				try
+				{
+					incAmount = int.Parse(val);
+				}
+				catch(FormatException)
+				{
+					throw new FormatException("Attribute 'incAmount' of category "+id+" was not a valid number");
+				}
+			}
+		}*/
+
+		protected override string DefaultName()
+		{
+			return "";
+		}
+
+		/*public GameSystem GameSystem
+		{
+			get { return system; }
+		}*/
+
+		public int MinimumPoints
+		{
+			get { return minPts; }
+			set { minPts = value; }
+		}
+
+		public int MaximumPoints
+		{
+			get { return maxPts; }
+			set { maxPts = value; }
+		}
+		
+		public int MinimumPercentage
+		{
+			get { return minPc; }
+			set { minPc = value; }
+		}
+
+		public int MaximumPercentage
+		{
+			get { return maxPc; }
+			set { maxPc = value; }
+		}
+
+		public int MinimumChoices
+		{
+			get { return minChoice; }
+			set { minChoice = value; }
+		}
+
+		public int MaximumChoices
+		{
+			get { return maxChoice; }
+			set { maxChoice = value; }
+		}
+
+		public int BaseValue
+		{
+			get { return baseVal; }
+			set { baseVal = value; }
+		}
+
+		public int IncrementValue
+		{
+			get { return incVal; }
+			set { incVal = value; }
+		}
+
+		public int IncrementAmount
+		{
+			get { return incAmount; }
+			set { incAmount = value; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/EquipmentItem.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,84 @@
+using System;
+using System.Xml;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for EquipmentItem.
+	/// </summary>
+	public class EquipmentItem : WarFoundryObject
+	{
+		private float cost, min, max;
+		private ArmourType armourType;
+		private Race equipForRace;
+
+		public EquipmentItem(string id, string name, float itemCost, float minimum, float maximum, ArmourType itemArmourType, Race race) : base(id, name)
+		{
+			cost = itemCost;
+			min = minimum;
+			max = maximum;
+			armourType = itemArmourType;
+			equipForRace = race;
+		}
+
+		public bool IsRatioLimit
+		{
+			get { return ((MaxNumber < 1 && MaxNumber > 0) || (MaxNumber == 1 && MinNumber > 0)); }
+		}
+
+		public float MinNumber
+		{
+			get { return min; }
+			set 
+			{
+				min = (value >= 0 || value == -1) ? value : 0; 
+
+				if (MaxNumber != -1 && min > MaxNumber)
+				{
+					MaxNumber = min;
+				}
+			}
+		}
+
+		public float MaxNumber
+		{
+			get { return max; }
+			set 
+			{
+				max = (value > 0 || value == -1) ? value : -1; 
+
+				if (max != -1 && MinNumber > max)
+				{
+					MinNumber = max;
+				}
+			}
+		}
+
+		public ArmourType ItemArmourType
+		{
+			get { return armourType; }
+			set { armourType = value; }
+		}
+
+		public float Cost
+		{
+			get { return cost; }
+			set { cost = value; }
+		}
+		
+		public Race EquipmentForRace
+		{
+			get { return equipForRace; }
+		}
+
+		public bool CanBeUsedWithItem(EquipmentItem item)
+		{
+			return CanBeUsedWithArmourType(item.ItemArmourType);
+		}
+
+		public bool CanBeUsedWithArmourType(ArmourType otherItemType)
+		{
+			return (this.ItemArmourType & otherItemType) == 0;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/GameSystem.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,274 @@
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.IO;
+using IBBoard.Logging;
+using IBBoard.WarFoundry.API.Factories;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for GameSystem.
+	/// </summary>
+	public class GameSystem : WarFoundryObject // WarFoundryStagedLoadSourceObject
+	{
+		private bool warnOnError;
+		private Category[] categories;
+		private SystemStatsSet stats;
+		private string defaultStats;
+		private FileInfo sourceFile;
+
+		public GameSystem(string systemID, string systemName) : base(systemID, systemName)
+		{
+		}
+				
+		/*public void CompleteLoading(Category[] cats, Dictionary<string, SystemStats> sysStats, string defaultStatsID)
+		{
+			categories = cats;
+			stats = new SystemStatsSet(sysStats); 
+			defaultStats = defaultStatsID;
+			base.CompleteLoading();
+		}*/
+		
+		public FileInfo SourceFile
+		{
+			get { return sourceFile; }
+			set { sourceFile = value; }
+		}
+		
+		public int GetCategoryCount()
+		{
+			return categories.Length;
+		}
+
+		public Category GetCategory(int index)
+		{
+			return categories[index];
+		}
+
+		public Category GetCategory(string id)
+		{
+			for (int i = 0; i<categories.Length; i++)
+			{
+				if (categories[i].ID == id)
+				{
+					return categories[i];
+				}
+			}
+
+			return null;
+		}
+
+		public Category[] Categories
+		{
+			get 
+			{ 
+				return SystemCategories; 
+			}
+			set 
+			{
+				SystemCategories = value;
+			}
+		}
+		
+		protected virtual Category[] SystemCategories
+		{
+			get 
+			{
+				return RawSystemCategories;
+			}
+			set
+			{
+				RawSystemCategories = value;
+			}
+		}
+		
+		protected Category[] RawSystemCategories
+		{
+			get 
+			{ 
+				return categories; 
+			}
+			set 
+			{
+				if (value!=null)
+				{
+					categories = value;
+				}
+			}
+		}
+
+		public bool WarnOnError
+		{
+			get
+			{
+				return warnOnError;
+			}
+			set { warnOnError = value; }
+		}
+		
+		public SystemStats StandardSystemStats
+		{
+			get
+			{
+				return SystemStats[defaultStats];
+			}
+		}
+		
+		public string StandardSystemStatsID
+		{
+			get
+			{				
+				return defaultStats;
+			}
+			
+			set
+			{
+				if (value != null && value.Trim().Length > 0)
+				{
+					defaultStats = value;
+				}
+			}
+		}
+
+		public SystemStatsSet SystemStats
+		{
+			get 
+			{ 
+				return stats;
+			}
+			set
+			{
+				stats = value;
+			}
+		}
+		
+		public Race SystemDefaultRace
+		{
+			get { return WarFoundryLoader.GetDefault().GetRace(this, Race.SYSTEM_DEFAULT_RACE_ID); }
+		}
+
+		public bool Matches(GameSystem otherSystem)
+		{
+			if (otherSystem==null)
+			{
+				return false;
+			}
+
+			return this.ID == otherSystem.ID;
+		}
+
+		public override bool Equals(object obj)
+		{
+			if (obj == null)
+			{
+				return false;		
+			}
+			
+			if (obj.GetType().Equals(this.GetType()))
+			{
+				GameSystem otherSystem = (GameSystem)obj;
+
+				return this.ID == otherSystem.ID && this.Name == otherSystem.Name && ((this.RawSystemCategories == null && otherSystem.RawSystemCategories == null) || this.RawSystemCategories.Equals(otherSystem.RawSystemCategories));
+			}
+			else
+			{
+				return false;
+			}
+		}
+
+		public override int GetHashCode()
+		{
+			return ID.GetHashCode() + Name.GetHashCode() + (RawSystemCategories!=null ? RawSystemCategories.GetHashCode() : 0) + warnOnError.GetHashCode();
+		}
+
+		public bool UnitTypeMaxed(UnitType unitType, Army army)
+		{
+			return unitType.MaxNumber!=-1 && army.GetUnitTypeCount(unitType) >= unitType.MaxNumber;
+		}
+
+		public bool UnitTypeMinned(UnitType unitType, Army army)
+		{
+			return army.GetUnitTypeCount(unitType) <= unitType.MinNumber;
+		}
+		
+		public List<EquipmentItem> GetSystemEquipmentList()
+		{
+			List<EquipmentItem> items = new List<EquipmentItem>();
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				items = defaultRace.GetEquipmentList();
+			}
+			
+			return items;
+		}
+				
+		public EquipmentItem GetSystemEquipmentItem(string id)
+		{
+			EquipmentItem item = null;
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				item = defaultRace.GetEquipmentItem(id);
+			}
+			
+			return item;
+		}
+		
+		public UnitType[] GetSystemUnitTypes(Category cat)
+		{
+			UnitType[] items = new UnitType[0];
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				items = defaultRace.GetUnitTypes(cat);
+			}
+			
+			return items;
+		}
+				
+		public UnitType GetSystemUnitType(string id)
+		{
+			UnitType unit = null;
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				unit = defaultRace.GetUnitType(id);
+			}
+			
+			return unit;
+		}
+		
+		public List<Ability> GetSystemAbilityList()
+		{
+			List<Ability> items = new List<Ability>();
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				items = defaultRace.GetAbilityList();
+			}
+			
+			return items;
+		}
+				
+		public Ability GetSystemAbility(string id)
+		{
+			Ability ability = null;
+			Race defaultRace = SystemDefaultRace;
+			
+			if (defaultRace!=null)
+			{				
+				ability = defaultRace.GetAbility(id);
+			}
+			
+			return ability;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/IWarFoundryNativeSourceObject.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,33 @@
+// IWarFoundrySourceObject.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry
+{
+	/// <summary>
+	/// Interface for native WarFoundry objects that are the main object in a file and need to reference the file at a later date.
+	/// </summary>
+	public interface IWarFoundryNativeSourceObject : IWarFoundryObject
+	{
+		ZipFile SourceFile { get; set; }
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/IWarFoundryObject.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,31 @@
+// IWarFoundryObject.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry
+{
+	public interface IWarFoundryObject
+	{
+		string ID { get; set; }
+
+		string Name { get; set;	}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/IWarFoundryStagedLoadObject.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,25 @@
+using System;
+using ICSharpCode.SharpZipLib.Zip;
+using IBBoard.WarFoundry.API.Factories;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public interface IWarFoundryStagedLoadObject : IWarFoundryObject
+	{	
+		/// <summary>
+		/// Checks whether the object has been fully loaded or whether only the first stage of loading has been performed.
+		/// If the object is not fully loaded then the method must finish loading the object.
+		/// </summary>
+		void EnsureFullyLoaded();
+		
+		/// <value>
+		/// Gets the <code>AbstractNativeWarFoundryFactory</code> that created the object.
+		/// </value>
+		AbstractNativeWarFoundryFactory Factory	{ get; }
+		
+		/// <value>
+		/// Returns <code>true</code> if the object has been fully loaded with all data, else returns <code>false</code>
+		/// </value>
+		bool IsFullyLoaded { get; }
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Race.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,339 @@
+// Race.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using IBBoard.IO;
+using IBBoard.WarFoundry.API.Factories;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public class Race : WarFoundryObject
+	{		
+		public static string SYSTEM_DEFAULT_RACE_ID = "GameDefault"; 
+		
+		private string subID;
+		private string systemID;
+		private GameSystem system;
+		private Dictionary<Category, Dictionary<string, UnitType>> unitTypesByCat;
+		private Dictionary<string, UnitType> unitTypes;
+		private Dictionary<string, EquipmentItem> equipment;
+		private Dictionary<string, Ability> abilities;
+		private Category[] cats;
+		private FileInfo sourceFile;
+		
+		public Race(string raceID, string raceName, string gameSystemID) : this(raceID, "", raceName, gameSystemID)
+		{
+		}
+		
+		public Race(string raceID, string raceSubID, string raceName, string gameSystemID) : base(raceID + (raceSubID!="" ? "_"+raceSubID : ""), raceName)
+		{
+			subID = (raceSubID == null ? "" : raceSubID);
+			systemID = gameSystemID;
+		}
+
+		public string SubID
+		{
+			get { return subID; }
+			set { subID = (value == null ? "" : value.Trim()); }
+		}
+		
+		public FileInfo SourceFile
+		{
+			get { return sourceFile; }
+			set { sourceFile = value; }
+		}
+
+		public GameSystem GameSystem
+		{
+			get
+			{
+				if (system == null)
+				{
+					system = WarFoundryLoader.GetDefault().GetGameSystem(systemID);
+				}
+				
+				return system;
+			}
+			set
+			{
+				if (value == null)
+				{
+					throw new ArgumentException("Game system for a race cannot be null");
+				}
+				
+				system = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets a category from its ID. Attempts to get the category from the race's overrides, or else it falls back to getting the Game System's category with that ID.
+		/// </summary>
+		/// <param name="id">
+		/// The ID of the category to get
+		/// </param>
+		/// <returns>
+		/// The <code>Category</code> with the specified ID, or null if one doesn't exist. 
+		/// </returns>
+		public Category GetCategory(string id)
+		{
+			Category[] categories = RaceCategories;
+			Category cat = null;
+		
+			for (int i = 0; i<categories.Length; i++)
+			{
+				if (categories[i].ID == id)
+				{
+					cat = categories[i];
+					break;
+				}
+			}
+			
+			return cat;
+		}
+
+		/// <summary>
+		/// Gets a category based on its index within the list. Ordering is defined by the game system definition or by the race's overrides.
+		/// </summary>
+		/// <param name="index">
+		/// A <see cref="System.Int32"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="Category"/>
+		/// </returns>
+		public virtual Category GetCategory(int index)
+		{
+			if (cats == null)
+			{
+				return GameSystem.GetCategory(index);
+			}
+			else
+			{
+				return Categories[index];
+			}
+		}
+		
+		public Category[] Categories
+		{
+			get 
+			{ 
+				return RaceCategories;
+			}
+			
+			set 
+			{
+				RaceOverrideCategories = value;
+			}
+		}
+		
+		/*private virtual Category[] GetCategories()
+		{
+			if (cats==null)
+			{
+				return GameSystem.Categories;
+			}
+			else
+			{
+				return cats; 
+			}
+		}*/
+		
+		public void SetEquipmentItems(Dictionary<string, EquipmentItem> items)
+		{
+			equipment = items;
+		}
+
+		public virtual EquipmentItem GetEquipmentItem(string id)
+		{
+			return (EquipmentItem)equipment[id];
+		}
+		
+		public List<EquipmentItem> GetEquipmentList()
+		{
+			List<EquipmentItem> items = new List<EquipmentItem>();
+			
+			foreach (EquipmentItem item in equipment.Values)
+			{
+				items.Add(item);
+			}
+			
+			return items;
+		}
+
+		public virtual bool HasCategoryOverrides()
+		{
+			return cats!=null;
+		}
+		
+		public void SetUnitTypes(Dictionary<string, UnitType> types)
+		{
+			unitTypes = types;
+		}
+
+		public UnitType[] GetUnitTypes(Category cat)
+		{
+			if (unitTypesByCat==null)
+			{				
+				unitTypesByCat = new Dictionary<Category,Dictionary<string,UnitType>>();
+				
+				foreach (Category category in RaceCategories)
+				{ 
+					unitTypesByCat.Add(category, new Dictionary<string, UnitType>());
+				}
+				
+				Dictionary<string,UnitType> catUnitTypes;
+				
+				foreach (UnitType unit in unitTypes.Values)
+				{
+					unitTypesByCat.TryGetValue(unit.MainCategory, out catUnitTypes);
+
+					if (catUnitTypes == null)
+					{
+						throw new InvalidFileException(String.Format("Unit type {0} with name {1} is a unit of an undefined category", unit.ID, unit.Name));
+					}
+
+					catUnitTypes.Add(unit.ID, unit);
+				}
+			}
+
+			ICollection<UnitType> col = unitTypesByCat[cat].Values;
+			UnitType[] toRet = new UnitType[col.Count];
+			int i = 0;
+
+			foreach (UnitType type in col)
+			{
+				toRet[i++] = type;
+			}
+
+			return toRet;
+		}
+
+		public UnitType GetUnitType(string id)
+		{
+			return (UnitType)unitTypes[id];
+		}
+		
+		public List<Ability> GetAbilityList()
+		{
+			List<Ability> items = new List<Ability>();
+			
+			foreach (Ability ability in abilities.Values)
+			{
+				items.Add(ability);
+			}
+			
+			return items;
+		}
+		
+		public void SetAbilities(Dictionary<string, Ability> newAbilities)
+		{
+			abilities = newAbilities;
+		}
+				
+		public Ability GetAbility(string id)
+		{
+			Ability ability = null;
+			abilities.TryGetValue(id, out ability);
+			return ability;
+		}
+		
+		protected Category[] RaceCategories
+		{
+			get
+			{
+				Category[] cats = RaceOverrideCategories;
+				
+				if (cats == null)
+				{
+					//No overrides, so load system categories
+					cats = GameSystem.Categories;
+				}
+				
+				return cats;
+			}
+		}
+		
+		protected virtual Category[] RaceOverrideCategories
+		{
+			get
+			{
+				return RaceRawOverrideCategories;
+			}
+			set
+			{
+				RaceRawOverrideCategories = value;
+			}
+		}
+		
+		protected Category[] RaceRawOverrideCategories
+		{
+			get { return cats; }
+			set
+			{
+				if (value!=null && value.Length>0)
+				{
+					cats = value;
+				}
+				else
+				{
+					cats = null;
+				}
+			}
+		}
+		
+		protected virtual Dictionary<string, UnitType> RaceUnitTypes
+		{
+			get { return RaceRawUnitTypes; }
+			set	{ RaceRawUnitTypes = value; }
+		}
+		
+		protected virtual Dictionary<string, EquipmentItem> RaceEquipment
+		{
+			get { return RaceRawEquipment; }
+			set { RaceRawEquipment = value; }
+		}
+		
+		protected virtual Dictionary<string, Ability> RaceAbilities
+		{
+			get { return RaceRawAbilities; }
+			set { RaceRawAbilities = value; }
+		}
+		
+		protected Dictionary<string, UnitType> RaceRawUnitTypes
+		{
+			get { return unitTypes; }
+			set	{ unitTypes = value; }
+		}
+		
+		protected Dictionary<string, EquipmentItem> RaceRawEquipment
+		{
+			get { return equipment; }
+			set { equipment = value; }
+		}
+		
+		protected Dictionary<string, Ability> RaceRawAbilities
+		{
+			get { return abilities; }
+			set { abilities = value; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/StagedLoadingGameSystem.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,64 @@
+// StagedLoadingGameSystem.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Factories;
+
+namespace IBBoard.WarFoundry.API.Objects
+{	
+	public class StagedLoadingGameSystem : GameSystem, IWarFoundryStagedLoadObject
+	{		
+		private AbstractNativeWarFoundryFactory creatingFactory;
+		
+		public StagedLoadingGameSystem(string systemID, string systemName, AbstractNativeWarFoundryFactory factory) : base(systemID, systemName)
+		{
+			creatingFactory = factory;
+		}
+		
+		public AbstractNativeWarFoundryFactory Factory
+		{
+			get { return creatingFactory; }
+		}
+		
+		public void EnsureFullyLoaded ()
+		{
+			if (!IsFullyLoaded)
+			{
+				Factory.CompleteLoading(this);
+			}
+		}
+		
+		public bool IsFullyLoaded
+		{
+			get { return RawSystemCategories != null && base.StandardSystemStatsID != null && base.SystemStats != null; }
+		}
+		
+		protected override Category[] SystemCategories
+		{
+			get
+			{
+				EnsureFullyLoaded();
+				return base.SystemCategories;
+			}
+			set { base.SystemCategories = value; }
+		}
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/StagedLoadingRace.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,150 @@
+// StagedLoadingRace.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Factories;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for StagedLoadingRace.
+	/// </summary>
+	public class StagedLoadingRace : Race, IWarFoundryStagedLoadObject
+	{	
+		private AbstractNativeWarFoundryFactory creatingFactory;
+		
+		public StagedLoadingRace(string raceID, string raceName, string gameSystemID, AbstractNativeWarFoundryFactory factory) : this(raceID, "", raceName, gameSystemID, factory)
+		{
+		}
+		
+		public StagedLoadingRace(string raceID, string raceSubID, string raceName, string gameSystemID, AbstractNativeWarFoundryFactory factory) : base(raceID, raceName, gameSystemID)
+		{
+			creatingFactory = factory;
+		}
+		
+		public AbstractNativeWarFoundryFactory Factory
+		{
+			get { return creatingFactory; }
+		}
+		
+		public void EnsureFullyLoaded ()
+		{
+			if (!IsFullyLoaded)
+			{
+				Factory.CompleteLoading(this);
+			}
+		}
+		
+		public bool IsFullyLoaded
+		{
+			get { return RaceRawOverrideCategories != null && RaceRawUnitTypes != null && RaceRawEquipment != null && RaceRawAbilities != null; }
+		}
+		
+		protected override Category[] RaceOverrideCategories
+		{
+			get
+			{
+				EnsureFullyLoaded();
+				return base.RaceOverrideCategories;
+			}
+		}
+		
+		protected override Dictionary<string, Ability> RaceAbilities
+		{
+			get
+			{
+				EnsureFullyLoaded();
+				return base.RaceAbilities;
+			}
+			set
+			{
+				base.RaceAbilities = value;
+			}
+		}
+		
+		protected override Dictionary<string, EquipmentItem> RaceEquipment 
+		{
+			get
+			{
+				EnsureFullyLoaded();
+				return base.RaceEquipment;
+			}
+			set
+			{
+				base.RaceEquipment = value;
+			}
+		}
+
+		protected override Dictionary<string, UnitType> RaceUnitTypes
+		{
+			get
+			{
+				EnsureFullyLoaded();
+				return base.RaceUnitTypes;
+			}
+			set
+			{
+				base.RaceUnitTypes = value;
+			}
+		}
+
+
+
+		
+ 
+		
+		/*public void CompleteLoading(List<Category> categoriesList, Dictionary<string,UnitType> unitTypesList, Dictionary<string,EquipmentItem> equipmentList, Dictionary<string, Ability> abilityList)
+		{
+			logger.Debug("Preparing dictionaries");
+			
+			if (categoriesList != null && categoriesList.Count > 0)
+			{
+				cats = categoriesList.ToArray();
+			}
+			
+			logger.Debug("Loading equipment");
+			equipment = new Dictionary<string,EquipmentItem>();
+
+			foreach (string equipID in equipmentList.Keys)
+			{
+				equipment.Add(equipID, equipmentList[equipID]);
+			}
+			
+			logger.Debug("Loading abilities");
+			abilities = new Dictionary<string,Ability>();
+			
+			foreach (string abilityID in abilityList.Keys)
+			{
+				abilities.Add(abilityID, abilityList[abilityID]);
+			}
+			
+			logger.Debug("Loading units");
+			unitTypes = new Dictionary<string,UnitType>();
+			
+			foreach (string unitID in unitTypesList.Keys)
+			{
+				unitTypes.Add(unitID, unitTypesList[unitID]);
+			}
+			
+			base.CompleteLoading();
+		}*/
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Stat.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,31 @@
+using System;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for Stat.
+	/// </summary>
+	public class Stat
+	{
+		private StatSlot parentStatSlot;
+		private string statString;
+
+		public Stat(StatSlot parentSlot, string statValue)
+		{
+				parentStatSlot = parentSlot;
+				statString = statValue;
+		}
+
+		public StatSlot ParentSlot
+		{
+			get { return parentStatSlot; }
+			set { parentStatSlot = value; }
+		}
+
+		public string SlotValueString
+		{
+			get { return statString; }
+			set { statString = (value == null ? "" : value); }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/StatSlot.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,33 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Xml;
+using IBBoard;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for StatSlot.
+	/// </summary>
+	public class StatSlot
+	{
+		private string name;
+		private SystemStats sysStats;
+
+		public StatSlot(String statName)
+		{
+			name = statName;
+		}
+
+		public string Name
+		{
+			get { return name; }
+			set { value = name; }
+		}
+		
+		public SystemStats SystemStats
+		{
+			get { return sysStats; }
+			set { sysStats = value; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Stats.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,94 @@
+// Stats.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using IBBoard.Lang;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public class Stats
+	{
+		private Stat[] stats;
+		private List<string> statOrder;
+		private SystemStats sysStats;
+		
+		public Stats(SystemStats systemStats)
+		{
+			sysStats = systemStats;
+		}
+		
+		public Stat[] StatsArray
+		{
+			get { return (Stat[])stats.Clone(); }
+		}
+		
+		protected internal void SetStats(List<Stat> statList)
+		{
+			stats = statList.ToArray();
+			statOrder = new List<string>();
+			
+			foreach (Stat stat in statList)
+			{
+				statOrder.Add(stat.ParentSlot.Name);
+			}
+		}
+		
+		public Stat this[string id]
+		{
+			get
+			{
+				Stat stat = null;
+				int pos = statOrder.IndexOf(id);
+				
+				try
+				{
+					stat = this[pos];
+				}
+				catch (ArgumentException ex)
+				{
+					throw new ArgumentException(Translation.GetTranslation("InvalidStatPos", "Invalid statistic ID {0} for stats based on system stats set {1}", new object[]{id, sysStats.ID}), ex);
+				}
+				
+				return stat;
+			}
+		}
+		
+		public Stat this[int pos]
+		{
+			get
+			{
+				if (pos < stats.Length && pos >= 0)
+				{
+					return stats[pos];
+				}
+				else
+				{
+					throw new ArgumentException(Translation.GetTranslation("InvalidStatPos", "Invalid statistic position {0} for stats based on system stats set {1}", new object[]{pos, sysStats.ID})); 
+				}
+			}
+		}
+		
+		public int StatCount
+		{
+			get { return stats.Length; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/SystemStats.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for SystemStats.
+	/// </summary>
+	public class SystemStats
+	{
+		private Dictionary<string, StatSlot> stats;
+		private string id;
+
+		public SystemStats(string statsID, StatSlot[] statSlots)
+		{
+			id = statsID;
+			stats = new Dictionary<string, StatSlot>();
+			
+			foreach (StatSlot slot in statSlots)
+			{
+				slot.SystemStats = this;
+				stats[slot.Name] = slot;
+			}
+		}
+
+		public StatSlot[] StatSlots
+		{
+			get
+			{
+				StatSlot[] slots = new StatSlot[stats.Count];
+				stats.Values.CopyTo(slots, 0);
+				return slots;
+			}
+		}
+		
+		public StatSlot this[string key]
+		{
+			get 
+			{
+				StatSlot slot = null;
+				stats.TryGetValue(key, out slot);
+				return slot;
+			}
+		}
+		
+        public int SlotCount
+        {
+            get { return stats.Count; }
+        }
+		
+		public string ID
+		{
+			get { return id; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/SystemStatsSet.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	public class SystemStatsSet
+	{
+		private Dictionary<string, SystemStats> statsMap;
+		public SystemStatsSet(Dictionary<string, SystemStats> stats)
+		{
+			statsMap = stats;
+		}
+		
+		public SystemStats this[string key]
+		{
+			get { return statsMap[key]; }
+		
+			set
+			{
+				if (statsMap.ContainsKey(key))
+				{
+					statsMap[key] = value;
+				}
+				else
+				{
+					throw new ArgumentException("Key must already exist for values to be set");
+				}
+			}
+		}
+		
+		public string[] GetSystemStatsIDs()
+		{
+			string[] ids = new string[statsMap.Count];
+			statsMap.Keys.CopyTo(ids, 0);
+			return ids;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/Unit.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,405 @@
+using System;
+using System.Collections;
+using System.Text;
+using System.Xml;
+using IBBoard.Lang;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for UnitInstance.
+	/// </summary>
+	public class Unit : WarFoundryObject
+	{
+		private UnitType type;
+		private int size;
+		private Army army;
+		private Race race;
+		private double points;
+		private ArmyCategory cat;
+		private Hashtable equipment = new Hashtable();
+		public event DoubleValChangedDelegate PointsValueChanged;
+		public event IntValChangedDelegate UnitSizeChanged;
+		public event FloatValChangedDelegate UnitEquipmentAmountChanged;
+
+		public Unit(UnitType unitType, Army parentArmy) : this(unitType, unitType.MinSize, parentArmy){}
+
+		public Unit(UnitType unitType, int startSize, Army parentArmy)
+		{
+			Army = parentArmy;
+			type = unitType;
+			Size = startSize;
+			setInitialEquipment();
+			CalcCost();
+		}
+
+		protected override string DefaultName()
+		{
+			if (type != null)
+			{
+				if (size == 1)
+				{
+					return type.Name;
+				}
+				else
+				{
+					return String.Format(Translation.GetTranslation("defaultUnitName"), size, type.Name);
+				}
+			}
+			else
+			{
+				return "Unknown Unit";
+			}
+		}
+
+		private void setInitialEquipment()
+		{
+			foreach (UnitEquipmentItem unitEquip in UnitType.GetEquipmentItems())
+			{
+				if (unitEquip.IsRequired)
+				{
+					if (CanEquipWithItem(unitEquip.ID))
+					{
+						EquipmentItem equipItem = unitEquip.EquipmentItem;
+						equipment[unitEquip.ID] = equipItem.MinNumber;
+					}
+				}
+			}
+		}
+
+		private void CalcCost()
+		{
+			String oldName = HasDefaultName() ? Name : null;
+			double oldpoints = points;
+			points = type.CostPerTrooper * AdditionalTroopers + type.BaseUnitCost;
+			UnitEquipmentItem unitEquipItem;
+			EquipmentItem equipItem;
+			float count;
+
+			foreach (string key in equipment.Keys)
+			{
+				unitEquipItem = UnitType.GetEquipmentItem(key);
+				equipItem = unitEquipItem.EquipmentItem;
+				count = (float)equipment[key];
+				
+				if (equipItem.IsRatioLimit)
+				{
+					if (unitEquipItem.RoundNumberUp)
+					{
+						points+= Math.Ceiling(size * count) * equipItem.Cost;
+					}
+					else
+					{
+						points+= Math.Floor(size * count) * equipItem.Cost;
+					}
+				}
+				else
+				{
+					if (count == -1)
+					{
+						points+= size * equipItem.Cost;
+					}
+					else
+					{
+						points+= count * equipItem.Cost;
+					}
+				}
+			}
+
+			if (oldpoints!=points)
+			{
+				OnPointsValueChanged(oldpoints, points);
+			}
+
+			if (oldName!=null)
+			{
+				OnNameChanged(oldName, Name);
+			}
+		}
+		
+		public int AdditionalTroopers
+		{
+			get { return Math.Max(Size - type.BaseSize, 0); }
+		}
+
+		public int Size
+		{
+			get { return size; }
+			set 
+			{
+				if (value!=size)
+				{
+					int oldValue = size;
+					size = (value>0 ? value : 1);
+					CalcCost();
+					OnUnitSizeChanged(oldValue, size);
+				}
+			}
+		}
+
+		public UnitType UnitType
+		{
+			get { return type; }
+		}
+
+		public Army Army
+		{
+			get { return army; }
+			set 
+			{
+				army = value;
+
+				if (army == null)
+				{
+					Category = null;
+				}
+			}
+		}
+
+		public Race Race
+		{
+			get { return race; }
+			set { race = value; }
+		}
+
+		public ArmyCategory Category
+		{
+			get 
+			{ 
+				if (cat==null)
+				{
+					if (Army!=null)
+					{
+						return Army.GetCategory(UnitType.MainCategory);
+					}
+					else
+					{
+						return null;
+					}
+				}
+				else
+				{
+					return cat; 
+				}
+			}
+			set { cat = value; }
+		}
+
+		public double PointsValue
+		{
+			get 
+			{
+				if (points == 0)
+				{
+					CalcCost();
+				}
+
+				return points;
+			}
+		}
+
+		public UnitEquipmentItem[] GetAllowedOptionalEquipment()
+		{
+			ArrayList list = new ArrayList();
+
+			foreach (UnitEquipmentItem item in UnitType.GetEquipmentItems())
+			{
+				if (!item.IsRequired)
+				{
+					list.Add(item);
+				}
+			}
+
+			return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
+		}
+
+		public UnitEquipmentItem[] GetEquipment()
+		{
+			UnitEquipmentItem[] items = new UnitEquipmentItem[equipment.Count];
+			int i = 0;
+
+			foreach (String itemID in equipment.Keys)
+			{
+				items[i++] = UnitType.GetEquipmentItem(itemID);
+			}
+
+			return items;
+		}
+
+		public UnitEquipmentItem[] GetRequiredEquipment()
+		{
+			ArrayList list = new ArrayList();
+			UnitEquipmentItem item;
+
+			foreach(String itemID in equipment.Keys)
+			{
+				item = UnitType.GetEquipmentItem(itemID);
+
+				if (item.IsRequired)
+				{
+					list.Add(item);
+				}
+			}
+
+			return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
+		}
+
+		public float GetEquipmentAmount(UnitEquipmentItem item)
+		{
+			return GetEquipmentAmount(item.EquipmentItem.ID);
+		}
+
+		public float GetEquipmentAmount(string equipID)
+		{
+			if (equipment.ContainsKey(equipID))
+			{
+				return (float)equipment[equipID];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		public void SetEquipmentAmount(string equipID, float amount)
+		{
+			UnitEquipmentItem equip = UnitType.GetEquipmentItem(equipID);
+
+			if (equip == null)
+			{
+				throw new InvalidOperationException("No such equipment ID "+equipID+" for unit "+ID);
+			}
+
+			if (equip.EquipmentItem.IsRatioLimit)
+			{
+				if (amount > 1)
+				{
+					amount = 1;
+				}
+				else if (amount < 0)
+				{
+					amount = 0;
+				}
+				//else what was passed in was okay
+			}
+			else
+			{
+				if (amount >=1 || amount == -1)
+				{
+					amount = (float)Math.Round(amount);
+				}
+				else
+				{
+					amount = 0;
+				}
+			}
+
+			float oldAmount = 0;
+
+			if (equipment.ContainsKey(equipID))
+			{
+				oldAmount = (float)equipment[equipID];
+			}
+
+			if (amount!=oldAmount)
+			{
+				if (amount > 0 || amount == -1)
+				{
+					equipment[equipID] = amount;
+				}
+				else
+				{
+					equipment.Remove(equipID);
+				}
+
+				OnUnitEquipmentAmountChanged(equip, oldAmount, amount);
+				CalcCost();
+			}
+		}
+
+		public bool CanEquipWithItem(string equipID)
+		{
+			string mutex = UnitType.GetEquipmentItem(equipID).MutexGroup;
+
+			if (mutex == "")
+			{
+				return true;
+			}
+
+			foreach (string itemID in equipment.Keys)
+			{
+				if (UnitType.GetEquipmentItem(itemID).MutexGroup == mutex)
+				{
+					return false;
+				}
+			}
+
+			return true;
+		}
+
+		private void OnPointsValueChanged(double oldValue, double newValue)
+		{
+			if (PointsValueChanged!=null)
+			{
+				PointsValueChanged(this, oldValue, newValue);
+			}
+		}
+
+		private void OnUnitSizeChanged(int oldValue, int newValue)
+		{
+			if (UnitSizeChanged!=null)
+			{
+				UnitSizeChanged(this, oldValue, newValue);
+			}
+		}
+
+		private void OnUnitEquipmentAmountChanged(UnitEquipmentItem equip, float oldValue, float newValue)
+		{
+			if (UnitEquipmentAmountChanged!=null)
+			{
+				UnitEquipmentAmountChanged(equip, oldValue, newValue);
+			}
+		}
+
+		public Stats UnitStats
+		{
+			get { return UnitType.UnitStats; }
+		}
+
+		/*public override string ToXmlString()
+		{
+			StringBuilder sb = new StringBuilder();
+			float amount;
+
+			foreach(string key in equipment.Keys)
+			{
+				amount = (float)equipment[key];
+
+				if (amount > 0 || amount == -1)
+				{
+					sb.Append("<equipItem id=\""+key+"\" amount=\""+amount+"\" />");
+				}
+			}
+
+			string equipmentString;
+
+			if (sb.Length > 0)
+			{
+				equipmentString = "<equipment>"+sb.ToString()+"</equipment>";
+			}
+			else
+			{
+				equipmentString = "";
+			}
+
+			if (equipmentString == "")
+			{
+				return "<unit id=\""+ID+"\" unitType=\""+UnitType.ID+"\" unitName=\""+name+"\" size=\""+Size+"\" />";
+			}
+			else
+			{
+				return "<unit id=\""+ID+"\" unitType=\""+UnitType.ID+"\" unitName=\""+name+"\" size=\""+Size+"\">"+equipmentString+"</unit>";
+			}
+		}*/
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/UnitEquipmentItem.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,81 @@
+using System;
+using System.Xml;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for UnitEquipmentItem.
+	/// </summary>
+	public class UnitEquipmentItem : WarFoundryObject
+	{
+		private bool required, roundUp;
+		private string mutexGroup;
+		private UnitType unitType;
+
+		/*public UnitEquipmentItem(XmlElement node, UnitType equipForType)
+		{
+			EquipmentForUnit = equipForType;
+			ID = node.GetAttribute("id");
+			IsRequired = bool.Parse(node.GetAttribute("required"));
+			RoundNumberUp = "up".Equals(node.GetAttribute("roundDirection").ToLower());
+			MutexGroup = node.GetAttribute("exclusivityGroup");
+		}*/
+		protected UnitEquipmentItem(UnitType equipForType)
+		{
+			EquipmentForUnit = equipForType;
+		}
+
+		public bool IsRequired
+		{
+			get { return required; }
+			set { required = value; }
+		}
+
+		public bool RoundNumberUp
+		{
+			get { return roundUp; }
+			set { roundUp = value; }
+		}
+
+		public string MutexGroup
+		{
+			get { return mutexGroup; }
+			set { mutexGroup = (value == null ? "" : value.Trim()); }
+		}
+
+		public UnitType EquipmentForUnit
+		{
+			get { return unitType; }
+			set 
+			{ 
+				if (value != null)
+				{
+					unitType = value;
+				}
+			}
+		}
+
+		public EquipmentItem EquipmentItem
+		{
+			get { return EquipmentForUnit == null ? null : EquipmentForUnit.Race.GetEquipmentItem(ID); }
+		}
+
+		public override string ToString()
+		{
+			return EquipmentItem.Name+ " ("+EquipmentItem.Cost+"pts each)";
+		}
+
+		public bool HasAlternatives()
+		{
+			if (MutexGroup=="")
+			{
+				return false;
+			}
+			else
+			{
+				//If the number of items in the MutEx group is greater than one then it must be this item plus another
+				return EquipmentForUnit.GetEquipmentItemsByExclusionGroup(MutexGroup).Length > 1;
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/UnitEquipmentItemObj.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,68 @@
+using System;
+using System.Collections;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for UnitEquipmentItemObj.
+	/// </summary>
+	public class UnitEquipmentItemObj
+	{
+		private Unit unit;
+		private UnitEquipmentItem item;
+		private EquipmentItem equip;
+
+		private static Hashtable equipObjs = new Hashtable();
+
+		private UnitEquipmentItemObj(Unit unit, UnitEquipmentItem unitItem)
+		{
+			this.unit = unit;
+			item = unitItem;
+			equip = item.EquipmentItem;
+		}
+
+		public static UnitEquipmentItemObj GetEquipObj(Unit unit, UnitEquipmentItem unitItem)
+		{
+			if (!equipObjs.ContainsKey(unitItem))
+			{
+				equipObjs[unitItem] = new UnitEquipmentItemObj(unit, unitItem);
+			}
+			
+			return (UnitEquipmentItemObj)equipObjs[unitItem];
+		}
+
+		public override string ToString()
+		{
+			return String.Format("{0} (For {1} at {2}pts each)", equip.Name, FormatEquipmentAmount(unit, equip), equip.Cost);
+		}
+
+		public UnitEquipmentItem Item
+		{
+			get { return item; }
+		}
+
+		public static string FormatEquipmentAmount(Unit unit, EquipmentItem equip)
+		{
+			return FormatEquipmentAmount(equip, unit.GetEquipmentAmount(equip.ID));
+		}
+
+		public static string FormatEquipmentAmount(EquipmentItem equip, float amount)
+		{
+			if (equip.IsRatioLimit)
+			{
+				return Math.Round(amount * 100) + "%";
+			}
+			else
+			{
+				if (amount == -1)
+				{
+					return "all";
+				}
+				else
+				{
+					return amount.ToString();
+				}
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/UnitType.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,222 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+using IBBoard.Logging;
+using IBBoard.WarFoundry.API.Requirements;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for Unit.
+	/// </summary>
+	public class UnitType : WarFoundryObject
+	{
+		protected Category mainCat;
+		protected string mainCatID;
+		protected Category[] categories;
+		protected string[] categoryIDs;
+		protected Race race;
+		protected int min, max, baseSize = 0;
+		protected int minSize, maxSize;
+		protected double baseUnitCost;
+		protected double costPerTrooper;
+		protected Stats stats;
+		protected UnitRequirement[] requirements;
+		protected Hashtable equipment = new Hashtable();
+		protected Hashtable equipmentExclusionGroups = new Hashtable();
+		protected ArrayList equipmentKeyOrder = new ArrayList();
+
+		public UnitType(string id, string typeName, string mainCategoryID, string[] allCategoryIDs, int minNum, int maxNum, int minimumSize, int maximumSize, double unitCost, double trooperCost, Stats unitStats, UnitRequirement[] unitRequirements, Race parentRace) : base(id, typeName)
+		{
+			mainCatID = mainCategoryID;
+			categoryIDs = allCategoryIDs;
+			race = parentRace;
+			
+			if (minNum > maxNum && maxNum!=-1)
+			{
+				min = maxNum;
+				LogNotifier.WarnFormat(GetType(), "Unit type {0} ({1}) had a minimum number greater than their maximum number.", typeName, id);
+			}
+			else
+			{
+				min = (minNum >= 0 ? minNum : 0);
+			}
+			
+			max = maxNum;
+			
+			if (minimumSize > maximumSize && maximumSize!=-1)
+			{
+				minSize = maximumSize;
+				LogNotifier.WarnFormat(GetType(), "Unit type {0} ({1}) had a minimum size greater than their maximum size.", typeName, id);
+			}
+			else
+			{
+				minSize = (minimumSize >= 0 ? minimumSize : 0);
+			}
+			
+			maxSize = maximumSize;
+			baseUnitCost = unitCost;
+			costPerTrooper = trooperCost;
+			requirements = unitRequirements;
+			stats = unitStats;
+		}
+
+		public Race Race
+		{
+			get { return race; }
+		}
+
+		public virtual Category MainCategory
+		{
+			get
+			{
+				if (mainCat == null)
+				{
+					LogNotifier.Debug(GetType(), Name+" main category: "+mainCatID);
+					mainCat = Race.GetCategory(mainCatID);
+				}
+					
+				return mainCat;
+			}
+		}
+		
+		public virtual Category[] Categories
+		{
+			get 
+			{
+				if (categories == null)
+				{
+					categories = new Category[categoryIDs.Length];
+					
+					for (int i = 0; i<categoryIDs.Length; i++)
+					{
+						categories[i] = Race.GetCategory(categoryIDs[i]);
+					}
+				}
+				
+				return categories;
+			}
+		}
+
+		public int MinSize
+		{
+			get { return minSize; }
+		}
+
+		public int MaxSize
+		{
+			get { return maxSize; }
+		}
+		
+		public int BaseSize
+		{
+			get { return baseSize; }
+		}
+
+		public int MinNumber
+		{
+			get { return min; }
+		}
+
+		public int MaxNumber
+		{
+			get { return max; }
+		}
+		
+		public double BaseUnitCost
+		{
+			get { return baseUnitCost; }
+		}
+
+		public double CostPerTrooper
+		{
+			get { return costPerTrooper; }
+		}
+
+		protected override string DefaultName()
+		{
+			throw new InvalidOperationException("Unit type with id "+id+" did not have a name specified");
+		}
+
+		public Stats UnitStats
+		{
+			get 
+			{
+				return stats;
+			}
+		}
+
+		public UnitEquipmentItem GetEquipmentItem(string id)
+		{
+			return (UnitEquipmentItem)equipment[id];
+		}
+
+		public UnitEquipmentItem[] GetEquipmentItems()
+		{
+			UnitEquipmentItem[] items = new UnitEquipmentItem[equipment.Count];
+			int i = 0;
+
+			foreach (string itemID in equipmentKeyOrder)
+			{
+				items[i++] = (UnitEquipmentItem)equipment[itemID];
+			}
+
+			return items;
+		}
+		
+		public List<FailedUnitRequirement> CanAddToArmy(Army army)
+		{
+			List<FailedUnitRequirement> failures = new List<FailedUnitRequirement>();
+			
+			if (requirements!=null && requirements.Length > 0)
+			{
+				foreach (UnitRequirement requirement in requirements)
+				{
+					FailedUnitRequirement failure = (FailedUnitRequirement)requirement.CanAddToWarFoundryObject(army);
+					
+					if (failure!=null)
+					{
+						failures.Add(failure);
+					}
+				}
+			}
+			
+			return failures;
+		}
+		
+		public List<FailedUnitRequirement> CanRemoveFromArmy(Army army)
+		{
+			List<FailedUnitRequirement> failures = new List<FailedUnitRequirement>();
+			
+			if (requirements!=null && requirements.Length > 0)
+			{
+				foreach (UnitRequirement requirement in requirements)
+				{
+					FailedUnitRequirement failure = (FailedUnitRequirement)requirement.CanRemoveFromWarFoundryObject(army);
+					
+					if (failure!=null)
+					{
+						failures.Add(failure);
+					}
+				}
+			}
+			
+			return failures;
+		}
+
+		public UnitEquipmentItem[] GetEquipmentItemsByExclusionGroup(string group)
+		{
+			ArrayList list = (ArrayList)equipmentExclusionGroups[group];
+
+			if (list == null)
+			{
+				return new UnitEquipmentItem[0];
+			}
+			else
+			{
+				return (UnitEquipmentItem[])list.ToArray(typeof(UnitEquipmentItem));
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Objects/WarFoundryObject.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,88 @@
+using System;
+
+namespace IBBoard.WarFoundry.API.Objects
+{
+	/// <summary>
+	/// Summary description for WarFoundryObject.
+	/// </summary>
+	public abstract class WarFoundryObject : IWarFoundryObject
+	{
+		protected string name, id;
+		public event StringValChangedDelegate NameChanged;
+		
+		protected WarFoundryObject(){}
+				
+		protected WarFoundryObject(string objName) : this()
+		{
+			Name = objName;
+		}
+		
+		protected WarFoundryObject(string objId, string objName) : this(objName)
+		{
+			ID = objId;
+		}	
+
+		public virtual string ID
+		{
+			get
+			{
+				if (id == null)
+				{
+					id = GenerateID();
+				}
+				
+				return id;
+			}
+			
+			set { id = (value == null ? GenerateID() : value.Trim()); }
+		}
+
+		public virtual string Name
+		{
+			get 
+			{
+				if (HasDefaultName())
+				{
+					return DefaultName();
+				}
+				else
+				{
+					return name;
+				} 
+			}
+			set 
+			{ 
+				string oldValue = name;
+				name = value;
+
+				if (name!=oldValue)
+				{
+					OnNameChanged(oldValue, name);
+				}
+			}
+		}
+
+		protected bool HasDefaultName()
+		{
+			return (name == null || name == "");
+		}
+
+		protected void OnNameChanged(string oldValue, string newValue)
+		{
+			if (NameChanged!=null)
+			{
+				NameChanged(this, oldValue, newValue);
+			}
+		}
+
+		protected virtual string DefaultName()
+		{
+			return "-";
+		}
+
+		protected string GenerateID()
+		{
+			return "ID" + UnixTimestamp.GetTimestamp(DateTime.Now) + "." + DateTime.Now.Millisecond;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/AbstractArmyRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,68 @@
+// Requirement.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects;
+
+
+namespace IBBoard.WarFoundry.API.Requirements
+{	
+	/// <summary>
+	/// Abstract class for any requirement for adding an object to an army, e.g. adding units.
+	/// </summary>
+	public abstract class AbstractArmyRequirement : AbstractRequirement
+	{		
+		protected abstract AbstractFailedRequirement CanAddToArmy(Army army);
+		protected abstract AbstractFailedRequirement CanRemoveFromArmy(Army army);
+		
+		public override AbstractFailedRequirement CanAddToWarFoundryObject (WarFoundryObject obj)
+		{
+			AbstractFailedRequirement fail = null;
+			
+			if (obj is Army)
+			{
+				fail = CanAddToArmy((Army)obj);
+			}
+			else
+			{
+				fail = new FailedRequirement(this);
+			}
+			
+			return fail;
+		}
+		
+		public override AbstractFailedRequirement CanRemoveFromWarFoundryObject (WarFoundryObject obj)
+		{
+			AbstractFailedRequirement fail = null;
+			
+			if (obj is Army)
+			{
+				fail = CanRemoveFromArmy((Army)obj);
+			}
+			else
+			{
+				fail = new FailedRequirement(this);
+			}
+			
+			return fail;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/AbstractFailedRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,36 @@
+// AbstractFailedRequirement.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	public abstract class AbstractFailedRequirement
+	{	
+		protected AbstractRequirement failedReq;
+		
+		public AbstractFailedRequirement(AbstractRequirement req)
+		{
+			failedReq = req;
+		}
+		
+		public abstract string Description { get; }
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/AbstractRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,35 @@
+// AbstractRequirement.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{	
+	/// <summary>
+	/// The base class for Requirements. Specific types of abstract requirement should extend this class.
+	/// </summary>
+	public abstract class AbstractRequirement
+	{				
+		public abstract string Description { get; }
+		public abstract AbstractFailedRequirement CanAddToWarFoundryObject(WarFoundryObject obj);
+		public abstract AbstractFailedRequirement CanRemoveFromWarFoundryObject(WarFoundryObject obj);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/AbstractUnitRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,66 @@
+// AbstractUnitRequirement.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Base abstract class for all requirements related to adding/removing something from a Unit (e.g. adding equipment or abilities)
+	/// </summary>
+	public abstract class AbstractUnitRequirement : AbstractRequirement
+	{		
+		protected abstract AbstractFailedRequirement CanAddToUnit(Unit unit);
+		protected abstract AbstractFailedRequirement CanRemoveFromUnit(Unit unit);
+		
+		public override AbstractFailedRequirement CanAddToWarFoundryObject (WarFoundryObject obj)
+		{
+			AbstractFailedRequirement fail = null;
+			
+			if (obj is Unit)
+			{
+				fail = CanAddToUnit((Unit)obj);
+			}
+			else
+			{
+				fail = new FailedRequirement(this);
+			}
+			
+			return fail;
+		}
+		
+		public override AbstractFailedRequirement CanRemoveFromWarFoundryObject (WarFoundryObject obj)
+		{
+			AbstractFailedRequirement fail = null;
+			
+			if (obj is Unit)
+			{
+				fail = CanRemoveFromUnit((Unit)obj);
+			}
+			else
+			{
+				fail = new FailedRequirement(this);
+			}
+			
+			return fail;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/Delegates.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,27 @@
+// Delegates.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	public delegate void FailedUnitRequirementDelegate(List<FailedUnitRequirement> failedRequirements);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/FailedRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,36 @@
+// FailedRequirement.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	public class FailedRequirement : AbstractFailedRequirement
+	{	
+		public FailedRequirement(AbstractRequirement req) : base(req)
+		{
+		}
+		
+		public override string Description
+		{
+			get { return failedReq.Description; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/FailedUnitRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,20 @@
+using System;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitRequirement.
+	/// </summary>
+	public class FailedUnitRequirement : AbstractFailedRequirement
+	{
+		public FailedUnitRequirement(UnitRequirement requirement) : base(requirement)
+		{
+		}
+		
+		public override string Description
+		{
+			get { return failedReq.Description; }
+		}
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/RequirementAND.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for RequirementAND.
+	/// </summary>
+	public class RequirementAND : AbstractRequirement
+	{
+		private static string and;
+
+		static RequirementAND()
+		{
+			and = Translation.GetTranslation("requirement_and", true);
+
+			if (and == null)
+			{
+				and = "{0}; and {1}";
+			}
+		}
+
+		private AbstractRequirement reqA, reqB;
+
+		public RequirementAND(AbstractRequirement requirementA, AbstractRequirement requirementB)
+		{
+			reqA = requirementA;
+			reqB = requirementB;
+		}
+
+		public override AbstractFailedRequirement CanAddToWarFoundryObject(WarFoundryObject obj)
+		{	
+			FailedRequirement failed = null;
+			
+			if (reqA.CanAddToWarFoundryObject(obj) !=null || reqB.CanAddToWarFoundryObject(obj)!=null)
+			{
+				failed = new FailedRequirement(this);
+			}
+			
+			return failed;
+		}
+
+		public override AbstractFailedRequirement CanRemoveFromWarFoundryObject(WarFoundryObject obj)
+		{
+			FailedRequirement failed = null;
+			
+			if (reqA.CanRemoveFromWarFoundryObject(obj) !=null || reqB.CanRemoveFromWarFoundryObject(obj)!=null)
+			{
+				failed = new FailedRequirement(this);
+			}
+			
+			return failed;
+		}
+
+		public override string Description 
+		{
+			get { return String.Format(and, reqA.Description, reqB.Description); }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/RequirementOR.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitRequirementOR.
+	/// </summary>
+	public class RequirementOR : AbstractRequirement
+	{
+		private static string or;
+
+		static RequirementOR()
+		{
+			or = Translation.GetTranslation("requirement_or", true);
+
+			if (or == null)
+			{
+				or = "{0} or {1}";
+			}
+		}
+
+		private AbstractRequirement reqA, reqB;
+
+		public RequirementOR(AbstractRequirement requirementA, AbstractRequirement requirementB)
+		{
+			reqA = requirementA;
+			reqB = requirementB;
+		}
+
+		public override AbstractFailedRequirement CanAddToWarFoundryObject(WarFoundryObject obj)
+		{		
+			FailedRequirement failed = null;
+			
+			if (reqA.CanAddToWarFoundryObject(obj) !=null && reqB.CanAddToWarFoundryObject(obj)!=null)
+			{
+				failed = new FailedRequirement(this);
+			}
+			
+			return failed;
+		}
+
+		public override AbstractFailedRequirement CanRemoveFromWarFoundryObject(WarFoundryObject obj)
+		{		
+			FailedRequirement failed = null;
+			
+			if (reqA.CanRemoveFromWarFoundryObject(obj)!=null && reqB.CanRemoveFromWarFoundryObject(obj)!=null)
+			{
+				failed = new FailedRequirement(this);
+			}
+			
+			return failed;
+		}
+
+		public override string Description 
+		{
+			get { return String.Format(or, reqA.Description, reqB.Description); }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitExcludesRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitExcludesRequirement.
+	/// </summary>
+	public class UnitExcludesRequirement : UnitRequirement
+	{
+		private UnitRequirementItem[] excludingTypes;
+
+		public UnitExcludesRequirement(UnitType type, UnitRequirementItem[] excludingUnitTypes) : base(type)
+		{
+			excludingTypes = excludingUnitTypes;
+		}
+
+		public override string Description
+		{
+			get 
+			{
+				return "Some units are already included that excluded this unit";
+			}
+		}
+
+		protected override AbstractFailedRequirement CanAddToArmy(Army army, UnitType type)
+		{		
+			FailedUnitRequirement failed = null;
+
+			for (int i = 0; i<excludingTypes.Length; i++)
+			{
+				if (army.GetUnitTypeCount(excludingTypes[i].UnitType) > 0)
+				{
+					failed = new FailedUnitRequirement(this);
+					break;
+				}
+			}
+			
+			return failed;
+		}
+
+		protected override AbstractFailedRequirement CanRemoveFromArmy(Army army, UnitType type)
+		{
+			return null;
+		}
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitExclusion.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,41 @@
+using System;
+using System.Text;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitMaxNumberRequirement.
+	/// </summary>
+	public class UnitExclusion : FailedUnitRequirement
+	{
+		private string unitList;
+		private UnitType type;
+
+		public UnitExclusion(UnitRequirement req, UnitType unitType, UnitType[] excludingTypes) : base(req)
+		{
+			type = unitType;
+
+			if (excludingTypes.Length > 1)
+			{
+				StringBuilder sb = new StringBuilder(excludingTypes[0].Name);
+
+				for (int i = 1; i<excludingTypes.Length; i++)
+				{
+					sb.Append(", "+excludingTypes[i].Name);
+				}
+
+				unitList = sb.ToString();
+			}
+			else
+			{
+				unitList = excludingTypes[0].Name;
+			}
+		}
+
+		public override string Description
+		{
+			get { return "The army cannot have any of the following units to include a unit of type "+type.Name+": "+unitList; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitMaxNumberReached.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,25 @@
+using System;
+using IBBoard;
+using IBBoard.Lang;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitMaxNumberRequirement.
+	/// </summary>
+	public class UnitMaxNumberReached : FailedUnitRequirement
+	{
+		private UnitType type;
+
+		public UnitMaxNumberReached(UnitType unitType, UnitRequirementMaxNumber requirement) : base(requirement)
+		{
+			type = unitType;
+		}
+
+		public override string Description
+		{
+			get { return String.Format(Translation.GetTranslation("ErrorUnitMaxNumberReached", "The maximum number of units of type \"{0}\" has already been reached or exceeded."), type.Name); }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitMinNumberReached.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,23 @@
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitMaxNumberRequirement.
+	/// </summary>
+	public class UnitMinNumberReached : FailedUnitRequirement
+	{
+		private UnitType type;
+
+		public UnitMinNumberReached(UnitType unitType, UnitRequirementMinNumber requirement) : base(requirement)
+		{
+			type = unitType;
+		}
+
+		public override string Description
+		{
+			get { return "The minimum number of units of type "+type.Name+" is not currently met"; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using IBBoard.WarFoundry.API;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitRequirement.
+	/// </summary>
+	public abstract class UnitRequirement : AbstractArmyRequirement
+	{
+		protected UnitType unitType;
+		
+		protected UnitRequirement(UnitType requirementFor)
+		{
+			unitType = requirementFor;	
+		}		
+		
+		/// <summary>
+		/// Checks whether the specified unit type can be added to the specified army. Returns a <see cref="FailedRequirement"> obejct if a unit of that type cannot legally be added, or no failure (null) if it can be added. 
+		/// </summary>
+		/// <param name="army">
+		/// The <see cref="Army"/> that the unit should be checked for adding to
+		/// </param>
+		/// <param name="type">
+		/// The <see cref="UnitType"/> that is being checked.
+		/// </param>
+		/// <returns>
+		/// A <see cref="AbstractFailedRequirement"/> if the requirement means the <see cref="UnitType"/> cannot be legally added, else <code>null</code>.
+		/// </returns>
+		protected abstract AbstractFailedRequirement CanAddToArmy(Army army, UnitType type);
+		
+		/// <summary>
+		/// Checks whether the specified unit can be added to the specified army. Returns a <see cref="FailedRequirement"> obejct if the unit cannot legally be added, or no failure (null) if it can be added. 
+		/// </summary>
+		/// <param name="army">
+		/// The <see cref="Army"/> that the unit should be checked for adding to
+		/// </param>
+		/// <param name="type">
+		/// The <see cref="Unit"/> that is being checked.
+		/// </param>
+		/// <returns>
+		/// A <see cref="AbstractFailedRequirement"/> if the requirement means the <see cref="Unit"/> cannot be legally added, else <code>null</code>.
+		/// </returns>
+		protected AbstractFailedRequirement CanAddToArmy(Army army, Unit unit)
+		{
+			return CanAddToArmy(army, unit.UnitType);
+		}
+		
+		/// <summary>
+		/// Checks whether the specified unit type can be removed from the specified army. Returns a <see cref="FailedRequirement"> obejct if a unit of that type cannot legally be removed, or no failure (null) if it can be removed. 
+		/// </summary>
+		/// <param name="army">
+		/// The <see cref="Army"/> that the unit should be checked for adding to
+		/// </param>
+		/// <param name="type">
+		/// The <see cref="UnitType"/> that is being checked.
+		/// </param>
+		/// <returns>
+		/// A <see cref="AbstractFailedRequirement"/> if the requirement means the <see cref="UnitType"/> cannot be legally added, else <code>null</code>.
+		/// </returns>
+		protected abstract AbstractFailedRequirement CanRemoveFromArmy(Army army, UnitType type);
+		
+		/// <summary>
+		/// Checks whether the specified unit can be removed from the specified army. Returns a <see cref="FailedRequirement"> obejct if the unit cannot legally be removed, or no failure (null) if it can be removed. 
+		/// </summary>
+		/// <param name="army">
+		/// The <see cref="Army"/> that the unit should be checked for adding to
+		/// </param>
+		/// <param name="type">
+		/// The <see cref="Unit"/> that is being checked.
+		/// </param>
+		/// <returns>
+		/// A <see cref="AbstractFailedRequirement"/> if the requirement means the <see cref="Unit"/> cannot be legally removed, else <code>null</code>.
+		/// </returns>
+		protected AbstractFailedRequirement CanRemoveFromArmy(Army army, Unit unit)
+		{
+			return CanRemoveFromArmy(army, unit.UnitType);
+		}
+				
+		protected override AbstractFailedRequirement CanAddToArmy(Army army)
+		{
+			return CanAddToArmy(army, unitType);
+		}
+		
+		protected override AbstractFailedRequirement CanRemoveFromArmy(Army army)
+		{
+			return CanRemoveFromArmy(army, unitType);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitRequirementItem.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,32 @@
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitRequirementItem.
+	/// </summary>
+	public class UnitRequirementItem
+	{
+		private UnitType type;
+		private int requiredNum;
+
+		public UnitRequirementItem(UnitType unitType, int reqNumber)
+		{
+			type = unitType;
+			requiredNum = reqNumber;
+		}
+
+		public UnitRequirementItem(UnitType type) : this(type, 1) { }
+
+		public UnitType UnitType
+		{
+			get { return type; }
+		}
+
+		public int Amount
+		{
+			get { return requiredNum; }
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitRequirementMaxNumber.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,57 @@
+// UnitRequirementMaxNumber.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	public class UnitRequirementMaxNumber : UnitRequirement
+	{		
+		private int maxUnitCount;
+		
+		public UnitRequirementMaxNumber(UnitType type, int maxNumber) : base(type)
+		{
+			maxUnitCount = maxNumber;
+		}
+		
+		public override string Description
+		{
+			get { return "You may only include up to "+maxUnitCount+" "+unitType.Name+" units in an army"; }
+		}
+		
+		protected override AbstractFailedRequirement CanAddToArmy (Army army, UnitType type)
+		{
+			FailedUnitRequirement failed = null;
+			
+			if (army.GetUnitTypeCount(type) >= maxUnitCount)
+			{
+				failed = new FailedUnitRequirement(this);
+			}
+			
+			return failed;
+		}
+
+		protected override AbstractFailedRequirement CanRemoveFromArmy (Army army, UnitType type)
+		{
+			return null;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitRequirementMinNumber.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,57 @@
+// UnitRequirementMinNumber.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	public class UnitRequirementMinNumber : UnitRequirement
+	{
+		private int minUnitCount;
+		
+		public UnitRequirementMinNumber(UnitType type, int minNumber) : base(type)
+		{
+			minUnitCount = minNumber;
+		}
+		
+		public override string Description
+		{
+			get { return "You must include at least "+minUnitCount+" "+unitType.Name+" units in an army"; }
+		}
+		
+		protected override AbstractFailedRequirement CanAddToArmy(Army army, UnitType type)
+		{
+			return null;
+		}
+
+		protected override AbstractFailedRequirement CanRemoveFromArmy (Army army, UnitType type)
+		{
+			FailedUnitRequirement failed = null;
+			
+			if (army.GetUnitTypeCount(type) <= minUnitCount)
+			{
+				failed = new FailedUnitRequirement(this);
+			}
+			
+			return failed;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Requirements/UnitRequiresAtLeastRequirement.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IBBoard.WarFoundry.API;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Requirements
+{
+	/// <summary>
+	/// Summary description for UnitRequiresRequirement.
+	/// </summary>
+	public class UnitRequiresAtLeastRequirement : UnitRequirement
+	{
+		private UnitType[] requiredTypes;
+		private int[] requiredCounts;
+		private String unitList;
+
+		public UnitRequiresAtLeastRequirement(UnitType type, UnitType requiredUnitType) : this(type, new UnitType[]{requiredUnitType}, new int[]{1})
+		{
+		}
+		
+		public UnitRequiresAtLeastRequirement(UnitType type, UnitType[] requiredUnitTypes, int[] minNumsRequired) : base(type)
+		{
+			if (requiredUnitTypes.Length != minNumsRequired.Length)
+			{
+				throw new ArgumentException("List of required unit types and list of number of units required must be equal");
+			}
+			else if (requiredUnitTypes.Length == 1)
+			{
+				throw new ArgumentException("List of required unit types must not be empty");
+			}
+			
+			requiredTypes = requiredUnitTypes;
+			requiredCounts = minNumsRequired;
+
+			if (requiredTypes.Length > 1)
+			{
+				StringBuilder sb = new StringBuilder(requiredCounts[0]+" x "+requiredTypes[0].Name);
+
+				for (int i = 1; i<requiredTypes.Length; i++)
+				{
+					sb.Append(", "+requiredCounts[i]+" x "+requiredTypes[i].Name);
+				}
+
+				unitList = sb.ToString();
+			}
+			else
+			{
+				unitList = requiredTypes[0].Name;
+			}
+		}
+
+		public override string Description
+		{
+			get { return "The army must include at least the following units to include a unit of type "+unitType.Name+": "+unitList; }
+		}
+
+		protected override AbstractFailedRequirement CanRemoveFromArmy(Army army, UnitType type)
+		{
+			return null;
+		}
+
+		protected override AbstractFailedRequirement CanAddToArmy(Army army, UnitType type)
+		{
+			FailedRequirement failure = null;
+			int count = requiredTypes.Length;
+			
+			for (int i = 0; i < count; i++)
+			{
+				if (army.GetUnitTypeCount(requiredTypes[i]) < requiredCounts[i])
+				{				
+					failure = new FailedRequirement(this);
+					break;
+				}
+			}
+						
+			return failure;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Savers/IWarFoundryFileSaver.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,42 @@
+// IWarFoundryFileSaver.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API.Savers
+{
+	public interface IWarFoundryFileSaver
+	{
+		/// <summary>
+		/// Saves an <see cref="Army"/> to a file on disk.
+		/// </summary>
+		/// <param name="army">
+		/// The <see cref="Army"/> to save
+		/// </param>
+		/// <param name="path">
+		/// The path to save the army to
+		/// </param>
+		/// <returns>
+		/// TRUE if saving succedes, else FALSE
+		/// </returns>
+		bool Save(Army army, string path);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/Savers/WarFoundrySaver.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,39 @@
+// WarFoundrySaver.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// 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 
+//
+//
+
+using System;
+
+namespace IBBoard.WarFoundry.API.Savers
+{
+	public class WarFoundrySaver
+	{
+		private static IWarFoundryFileSaver fileSaver;
+		
+		public static IWarFoundryFileSaver GetSaver()
+		{
+			return fileSaver;
+		}
+		
+		public static void SetFileSaver(IWarFoundryFileSaver newFileSaver)
+		{
+			fileSaver = newFileSaver;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/WarFoundryCore.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,103 @@
+// WarFoundry.cs
+//
+//  Copyright (C) 2008 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using IBBoard.Logging;
+using IBBoard.WarFoundry.API.Objects;
+
+namespace IBBoard.WarFoundry.API
+{
+	public class WarFoundryCore
+	{		
+		public static event GameSystemChangedDelegate GameSystemChanged;
+		public static event ArmyChangedDelegate ArmyChanged;
+		
+		private static GameSystem system;
+		private static Army currentArmy;
+				
+		public static GameSystem CurrentGameSystem
+		{
+			get { return system; }
+			set
+			{
+				if (system==null || !system.Equals(value))
+				{
+					GameSystem oldSystem = system;
+					system = value;
+					
+					if (system==null)
+					{
+						LogNotifier.Debug(typeof(WarFoundryCore), "Game system set to null");
+					}
+					else
+					{
+						LogNotifier.DebugFormat(typeof(WarFoundryCore), "Game system set to {0} with ID {1}", system.Name, system.ID); 
+					}
+
+					if (GameSystemChanged!=null)
+					{
+						GameSystemChanged(oldSystem, system);
+					}
+					
+					//If we've changed the game system then we can't keep the current army
+					CurrentArmy = null;
+				}
+			}
+		}
+		
+		public static Army CurrentArmy
+		{
+			get { return currentArmy; }
+			set
+			{
+				if (currentArmy==null || !currentArmy.Equals(value))
+				{
+					/*if (currentArmy!=null)
+					{
+						currentArmy.UnitAdded-= UnitAddedMethod;
+						currentArmy.UnitRemoved-= UnitRemovedMethod;
+						currentArmy.PointsValueChanged-= PointsValueChangedMethod;
+						currentArmy.FailedRequirement-=FailedUnitRequirementMethod;
+					}*/
+					Army oldArmy = currentArmy;
+					currentArmy = value;
+					
+					if (currentArmy!=null)
+					{
+						CurrentGameSystem = currentArmy.GameSystem; //Set the game system in case the new army is from a different system
+					}
+
+					/*if (currentArmy!=null)
+					{
+						currentArmy.UnitAdded+= UnitAddedMethod;
+						currentArmy.UnitRemoved+= UnitRemovedMethod;
+						currentArmy.PointsValueChanged+= PointsValueChangedMethod;
+						currentArmy.FailedRequirement+=FailedUnitRequirementMethod;
+					}*/
+
+					if (ArmyChanged!=null)
+					{
+						ArmyChanged(oldArmy, currentArmy);
+					}
+				}
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/api/WarFoundryLoader.cs	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,664 @@
+// WarFoundryLoader.cs
+//
+//  Copyright (C) 2007 IBBoard
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 of the License as published by the Free
+// Software Foundation.
+//
+// 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 
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using IBBoard.Collections;
+using IBBoard.IO;
+using IBBoard.Logging;
+using IBBoard.WarFoundry.API.Factories;
+using IBBoard.WarFoundry.API.Objects;
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace IBBoard.WarFoundry.API
+{
+	public class WarFoundryLoader
+	{		
+		private static WarFoundryLoader loader;
+		
+		/// <summary>
+		/// Gets the default <see cref="WarFoundryLoader"/> used to load WarFoundry data files.
+		/// </summary>
+		/// <returns>
+		/// The default <see cref="WarFoundryLoader"/>
+		/// </returns>
+		public static WarFoundryLoader GetDefault()
+		{
+			if (loader == null)
+			{
+				loader = new WarFoundryLoader();
+			}
+			
+			return loader;
+		}
+		
+		private ICollection<DirectoryInfo> directories;
+		private ICollection<INativeWarFoundryFactory> factories;
+		private ICollection<INonNativeWarFoundryFactory> nonNativeFactories;
+		private Dictionary<string, GameSystem> systemsTable;
+		private Dictionary<string, Dictionary<string, Dictionary<string, Race>>> racesTable; //Keys are: System, Race, SubRace
+		private Dictionary<IWarFoundryFactory, SimpleSet<IWarFoundryObject>> loadedObjects;
+		
+		protected WarFoundryLoader()
+		{
+			directories = new List<DirectoryInfo>();
+			factories = new List<INativeWarFoundryFactory>();
+			nonNativeFactories = new List<INonNativeWarFoundryFactory>();
+			loadedObjects = new Dictionary<IWarFoundryFactory,SimpleSet<IWarFoundryObject>>();
+		}
+		
+		/// <summary>
+		/// Adds a directory to the collection of directories that will be searched for WarFoundry data files.
+		/// </summary>
+		/// <param name="directory">
+		/// The <see cref="DirectoryInfo"/> to add to the list for searching for data files
+		/// </param>
+		public void AddLoadDirectory(DirectoryInfo directory)
+		{
+			if (!directories.Contains(directory))
+			{
+				directories.Add(directory);
+			}
+		}
+		
+		/// <summary>
+		/// Removes a directory from the collection of directories that will be searched for WarFoundry data files.
+		/// </summary>
+		/// <param name="directory">
+		/// A <see cref="DirectoryInfo"/>
+		/// </param>
+		public void RemoveLoadDirectory(DirectoryInfo directory)
+		{
+			if (directories.Contains(directory))
+			{
+				directories.Remove(directory);
+			}
+		}
+		
+		/// <summary>
+		/// Registers a <see cref="INativeWarFoundryFactory"/> as a factory that can parse native data files.
+		/// </summary>
+		/// <param name="factory">
+		/// The <see cref="INativeWarFoundryFactory"/> to register to parse native data files.
+		/// </param>
+		public void RegisterFactory(INativeWarFoundryFactory factory)
+		{
+			if (!factories.Contains(factory))
+			{
+				factories.Add(factory);
+			}
+		}
+		
+		/// <summary>
+		/// Unregisters a <see cref="INativeWarFoundryFactory"/> so that it will no longer be used to try to parse native data files.
+		/// </summary>
+		/// <param name="factory">
+		/// The <see cref="INativeWarFoundryFactory"/> to remove from the collection of factories that are used to try to parse native data files.
+		/// </param>
+		public void UnregisterFactory(INativeWarFoundryFactory factory)
+		{
+			if (factories.Contains(factory))
+			{
+				factories.Remove(factory);
+			}
+		}
+		
+		/// <summary>
+		/// Registers a <see cref="INonNativeWarFoundryFactory"/> so that it will be used to try to parse non-native data files from other applications.
+		/// </summary>
+		/// <param name="factory">
+		/// The <see cref="INonNativeWarFoundryFactory"/> to register to parse non-native data files.
+		/// </param>
+		public void RegisterNonNativeFactory(INonNativeWarFoundryFactory factory)
+		{
+			if (!nonNativeFactories.Contains(factory))
+			{
+				nonNativeFactories.Add(factory);
+			}
+		}
+		
+		/// <summary>
+		/// Unregisters a <see cref="INonNativeWarFoundryFactory"/> so that it will no longer be used to try to parse non-native data files from other applications.
+		/// </summary>
+		/// <param name="factory">
+		/// The <see cref="INonNativeWarFoundryFactory"/> to remove from the collection of factories that are used to try to parse non-native data files.
+		/// </param>
+		public void UnregisterNonNativeFactory(INonNativeWarFoundryFactory factory)
+		{
+			if (nonNativeFactories.Contains(factory))
+			{
+				nonNativeFactories.Remove(factory);
+			}
+		}
+		
+		/// <summary>
+		/// Loads all of the data files in the registered directories.
+		/// </summary>
+		public void LoadFiles()
+		{
+			LogNotifier.Debug(GetType(), "Load files");
+			PrepareForFileLoad();
+			
+			foreach (DirectoryInfo directory in directories)
+			{
+				LogNotifier.Debug(GetType(), "Load from "+directory.FullName);
+				
+				foreach (FileInfo file in directory.GetFiles())
+				{
+					LoadFile(file);
+				}
+			}
+			
+			ICollection<Race> races = new List<Race>(); 
+			
+			foreach (SimpleSet<IWarFoundryObject> objs in loadedObjects.Values)
+			{			
+				foreach (IWarFoundryObject obj in  objs)
+				{
+					if (obj is Race)
+					{
+						races.Add((Race)obj);
+					}
+					else if (obj is GameSystem)
+					{
+						StoreGameSystem((GameSystem)obj);
+					}
+				}
+			}
+			
+			foreach (Race race in races)
+			{
+				StoreRace(race);
+			}					
+		}
+		
+		protected void PrepareForFileLoad()
+		{
+			//Just set up blank dictionaries for now - may try different and more complex handling in future
+			systemsTable = new Dictionary<string,GameSystem>();
+			racesTable = new Dictionary<string,Dictionary<string,Dictionary<string,Race>>>();
+		}
+		
+		/// <summary>
+		/// Loads a single file through the registered WarFoundryFactories, if a factory exists that supports the file format.
+		/// </summary>
+		/// <param name="file">
+		/// A <see cref="FileInfo"/> for the file to attempt to load
+		/// </param>
+		protected void LoadFile(FileInfo file)
+		{
+			bool handled = false;
+			
+			if (!handled)
+			{
+				ICollection<IWarFoundryObject> objs = null;
+				IWarFoundryFactory loadFactory = null;
+				
+				if (nonNativeFactories.Count > 0)
+				{
+					LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as a non-native file");
+					
+					foreach (INonNativeWarFoundryFactory factory in nonNativeFactories)
+					{
+						LogNotifier.Debug(GetType(), "Load using "+factory.GetType().AssemblyQualifiedName+"? " + (factory.CanHandleFileFormat(file) ? "yes" : "no"));
+						
+						if (factory.CanHandleFileFormat(file))
+						{
+							objs = factory.CreateObjectsFromFile(file);
+							
+							if (objs!=null)
+							{
+								loadFactory = factory;
+								break;
+							}
+						}			         
+					}
+				}
+				
+				if (objs == null)
+				{
+					LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as native file");
+					
+					foreach (INativeWarFoundryFactory factory in factories)
+					{
+						if (factory.CanHandleFileFormat(file))
+						{
+							objs = factory.CreateObjectsFromFile(file);
+							
+							if (objs!=null)
+							{
+								loadFactory = factory;
+								break;
+							}
+						}
+					}
+				}
+					
+				if (objs!=null)
+				{
+					AddLoadedObjects(objs, loadFactory);
+				}
+			}
+		}
+		
+		private void AddLoadedObjects(ICollection<IWarFoundryObject> loadedObjs, IWarFoundryFactory factory)
+		{
+			SimpleSet<IWarFoundryObject> objs;
+			loadedObjects.TryGetValue(factory, out objs);
+			
+			if (objs == null)
+			{
+				objs = new SimpleSet<IWarFoundryObject>();
+				loadedObjects.Add(factory, objs);
+			}
+				
+			objs.AddRange(loadedObjs);
+		}
+		
+		private void AddLoadedObject(IWarFoundryObject obj, IWarFoundryFactory factory)
+		{
+			SimpleSet<IWarFoundryObject> objs;
+			loadedObjects.TryGetValue(factory, out objs);
+			
+			if (objs == null)
+			{
+				objs = new SimpleSet<IWarFoundryObject>();
+				loadedObjects.Add(factory, objs);
+			}
+				
+			objs.Add(obj);
+		}
+		
+		protected virtual ZipFile MakeZipFile(FileInfo file)
+		{
+			return new ZipFile(file.FullName);
+		}
+		
+		protected void StoreGameSystem(GameSystem system)
+		{
+			string sysid = system.ID.ToLower();
+					
+			if (systemsTable.ContainsKey(sysid))
+			{
+				LogNotifier.WarnFormat(GetType(), "System {0} ({1}) has already been loaded. Duplicate file ({3}) discarded", system.Name, system.ID, system.SourceFile.FullName);
+			}
+			else
+			{
+				systemsTable.Add(sysid, (GameSystem)system);
+			}
+		}
+		
+		
+		/// <summary>
+		/// Stores a loaded <see cref="GameSystem"/> that has been generated outside the core loading structure.
+		/// 
+		/// Note: Calls to this function should be made before calls to StoreRace(Race, IWarFoundryFactory).
+		/// </summary>
+		/// <param name="system">
+		/// The <see cref="GameSystem"/> to register as loaded.
+		/// </param>
+		/// <param name="factory">
+		/// The <see cref="IWarFoundryFactory"/> that created it.
+		/// </param>
+		public void StoreGameSystem(GameSystem system, IWarFoundryFactory factory)
+		{
+			AddLoadedObject(system, factory);	
+			StoreGameSystem(system);
+		}
+		
+		protected void StoreRace(Race race)
+		{
+			Dictionary<string, Dictionary<string, Race>> systemRaces;
+
+			if (race.GameSystem == null)
+			{
+				throw new InvalidOperationException("Race cannot have null game system. Game system should be loaded before race.");
+			}
+			
+			string systemID = race.GameSystem.ID.ToLower();
+			racesTable.TryGetValue(systemID, out systemRaces);
+			
+			if (systemRaces==null)
+			{
+				systemRaces = new Dictionary<string,Dictionary<string,Race>>();
+				racesTable.Add(systemID, systemRaces);
+			}
+			
+			Dictionary<string, Race> subRaces;
+			systemRaces.TryGetValue(race.ID.ToLower(), out subRaces);
+			
+			if (subRaces==null)
+			{
+				subRaces = new Dictionary<string,Race>();
+				systemRaces.Add(race.ID.ToLower(), subRaces);
+			}
+
+			if (subRaces.ContainsKey(race.SubID.ToLower()))
+			{
+				LogNotifier.WarnFormat(GetType(), "Race {0} ({1} - {2}) for system {3} ({4}) has already been loaded. Duplicate file ({5}) discarded", race.Name, race.ID, race.SubID, race.GameSystem.ID, race.GameSystem.Name, race.SourceFile.Name);
+				race = null;
+			}
+			else
+			{
+				subRaces.Add(race.SubID.ToLower(), race);
+			}
+		}
+		
+		/// <summary>
+		/// Stores a loaded <see cref="Race"/> that has been generated outside the core loading structure.
+		/// 
+		/// Note: Calls to this function should ensure that the relevant <see cref="GameSystem"> has been created first.
+		/// </summary>
+		/// <param name="race">
+		/// The <see cref="Race"/> to register as loaded.
+		/// </param>
+		/// <param name="factory">
+		/// The <see cref="IWarFoundryFactory"/> that created it
+		/// </param>
+		public void StoreRace(Race race, IWarFoundryFactory factory)
+		{
+			AddLoadedObject(race, factory);
+			StoreRace(race);
+		}
+		
+		/// <summary>
+		/// Gets all <see cref="GameSystem"/>s that are currently available, determined by those that can be loaded with the current <see cref="IWarFoundryFactory"/>s. 
+		/// </summary>
+		/// <returns>
+		/// An array of <see cref="GameSystem"/>s that are currently available.
+		/// </returns>
+		public GameSystem[] GetGameSystems()
+		{
+			if (systemsTable==null)
+			{
+				LoadFiles();
+			}
+			
+			GameSystem[] systems = new GameSystem[systemsTable.Count];
+			int iSys = 0;
+			
+			foreach (GameSystem sys in systemsTable.Values)
+			{
+				systems[iSys++] = sys;
+			}
+			
+			return systems;
+		}
+
+		/// <summary>
+		/// Gets a single <see cref="GameSystem"/> with a given ID. 
+		/// </summary>
+		/// <param name="systemID">
+		/// The ID of the <see cref="GameSystem"/> to get, as a <see cref="System.String"/>.
+		/// </param>
+		/// <returns>
+		/// The <see cref="GameSystem"/> with the given ID, or <code>null</code> if one doesn't exist.
+		/// </returns>
+		public GameSystem GetGameSystem(string systemID)
+		{
+			if (systemsTable==null)
+			{
+				LoadFiles();
+			}
+			
+			GameSystem system;
+			systemsTable.TryGetValue(systemID.ToLower(), out system);
+			return system;
+		}
+
+		/// <summary>
+		/// Gets an array of the races for the specified <see cref="GameSystem"/>.
+		/// </summary>
+		/// <param name="system">
+		/// The <see cref="GameSystem"/> to get the available races for.
+		/// </param>
+		/// <returns>
+		/// An array of <see cref="Race"/>s for the <see cref="GameSystem"/>
+		/// </returns>
+		public Race[] GetRaces(GameSystem system)
+		{
+			return GetRaces(system.ID);
+		}
+
+		/// <summary>
+		/// Gets an array of the races for a game system by ID.
+		/// </summary>
+		/// <param name="systemID">
+		/// The <see cref="System.String"/> ID of the game system to get races for
+		/// </param>
+		/// <returns>
+		/// An array of <see cref="Race"/>s for the specified game system
+		/// </returns>
+		public Race[] GetRaces(string systemID)
+		{
+			if (racesTable==null)
+			{
+				LoadFiles();
+			}
+			
+			systemID = systemID.ToLower();
+			
+			foreach (string key in racesTable.Keys)
+			{
+				Console.WriteLine(key);
+			}
+
+			Dictionary<string, Dictionary<string, Race>> system;
+			racesTable.TryGetValue(systemID, out system);
+			
+			if (system==null)
+			{
+				return new Race[0];
+			}
+
+			int count = 0;
+
+			foreach (Dictionary<string, Race> racesDict in system.Values)
+			{
+				count+= racesDict.Count;
+			}
+
+			Race[] races = new Race[count];
+			int i = 0;
+
+			foreach (string raceID in system.Keys)
+			{
+				foreach (string raceSubId in system[raceID].Keys)
+				{
+					races[i++] = GetRace(systemID, raceID, raceSubId);
+				}
+			}
+
+			return races;
+		}
+
+		/// <summary>
+		/// Gets a single race for a given <see cref="GameSystem"/> by ID of the race.
+		/// </summary>
+		/// <param name="system">
+		/// The <see cref="GameSystem"/> that the race is part of.
+		/// </param>
+		/// <param name="raceID">
+		/// A <see cref="System.String"/> ID for the race to load.
+		/// </param>
+		/// <returns>
+		/// A <see cref="Race"/> with the specified ID from the <see cref="GameSystem"/>, or <code>null</code> if one doesn't exist.
+		/// </returns>
+		public Race GetRace(GameSystem system, string raceID)
+		{
+			return GetRace(system.ID, raceID);
+		}
+
+		/// <summary>
+		/// Gets a single race for a given game system by ID of the game system and race.
+		/// </summary>
+		/// <param name="systemID">
+		/// The <see cref="System.String"/> ID of the game system that the race is part of.
+		/// </param>
+		/// <param name="raceID">
+		/// The <see cref="System.String"/> ID for the race to load.
+		/// </param>
+		/// <returns>
+		/// A <see cref="Race"/> with the specified ID from the game system with the specified ID, or <code>null</code> if there is no race or game system with those IDs.
+		/// </returns>
+		public Race GetRace(string systemID, string raceID)
+		{
+			return GetRace(systemID, raceID, "");
+		}
+
+		/// <summary>
+		/// Gets a single race for a given <see cref="GameSystem"/> by the race's ID and sub-race ID.
+		/// </summary>
+		/// <param name="system">
+		/// The <see cref="GameSystem"/> that the race is part of.
+		/// </param>
+		/// <param name="raceID">
+		/// The <see cref="System.String"/> ID for the race to load.
+		/// </param>
+		/// <param name="raceSubID">
+		/// A <see cref="System.String"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="Race"/>
+		/// </returns>
+		public Race GetRace(GameSystem system, string raceID, string raceSubID)
+		{
+			return GetRace(system.ID, raceID, raceSubID);
+		}
+
+		/// <summary>
+		/// Gets a single race for a given game system by the game system's ID and the race's ID and sub-race ID.
+		/// </summary>
+		/// <param name="systemID">
+		/// The <see cref="System.String"/> ID of the game system that the race is part of.
+		/// </param>
+		/// <param name="raceID">
+		/// The <see cref="System.String"/> ID for the race to load.
+		/// </param>
+		/// <param name="raceSubID">
+		/// A <see cref="System.String"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="Race"/>
+		/// </returns>
+		public Race GetRace(string systemID, string raceID, string raceSubID)
+		{
+			if (racesTable==null)
+			{
+				LoadFiles();
+			}
+			
+			Race race = null;
+			
+			systemID = systemID.ToLower();
+
+			Dictionary<string, Dictionary<string, Race>> races;
+			racesTable.TryGetValue(systemID, out races);
+
+			if (races!=null)
+			{
+				Dictionary<string, Race> subraces;
+				races.TryGetValue(raceID, out subraces);
+
+				if (subraces!=null)
+				{
+					subraces.TryGetValue(raceSubID, out race);
+				}
+			}
+			
+			return race;
+		}
+
+		/// <summary>
+		/// Gets the IDs of all of the game systems currently available.
+		/// </summary>
+		/// <returns>
+		/// An array of <see cref="System.String"/>s representing the IDs of the game systems.
+		/// </returns>
+		public string[] GetGameSystemIDs()
+		{
+			if (systemsTable==null)
+			{
+				LoadFiles();
+			}
+
+			string[] keys = new string[systemsTable.Keys.Count];
+			int i = 0;
+
+			foreach (string key in systemsTable.Keys)
+			{
+				keys[i++] = key;
+			}
+
+			return keys;
+		}
+		
+		/// <summary>
+		/// Gets the IDs of all of the races of a specified game system.
+		/// </summary>
+		/// <param name="system">
+		/// The <see cref="GameSystem"/> to get the available races for.
+		/// </param>
+		/// <returns>
+		/// An array of <see cref="System.String"/>s representing the IDs of the races of the specified game system.
+		/// </returns>
+		public string[] GetSystemRaceIDs(GameSystem system)
+		{
+			return GetSystemRaceIDs(system.ID);
+		}
+
+		/// <summary>
+		/// Gets the IDs of all of the races of a specified game system.
+		/// </summary>
+		/// <param name="systemID">
+		/// The <see cref="System.String"/> ID of the game system to get the available races for.
+		/// </param>
+		/// <returns>
+		/// An array of <see cref="System.String"/>s representing the IDs of the races of the specified game system.
+		/// </returns>
+		public string[] GetSystemRaceIDs(string systemID)
+		{
+			if (racesTable == null)
+			{
+				LoadFiles();
+			}
+
+			Dictionary<string, Dictionary<string, Race>> races = racesTable[systemID.ToLower()];
+
+			if (races==null)
+			{
+				return new string[0];
+			}
+			else
+			{
+				string[] keys = new string[races.Keys.Count];
+				int i = 0;
+
+				foreach (string key in races.Keys)
+				{
+					keys[i++] = key;
+				}
+
+				return keys;
+			}
+		}
+	}
+}
Binary file libs/ICSharpCode.SharpZipLib.dll has changed
Binary file libs/log4net.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/log4net.xml	Fri Dec 19 15:57:51 2008 +0000
@@ -0,0 +1,27658 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>log4net</name>
+    </assembly>
+    <members>
+        <member name="T:log4net.Appender.AdoNetAppender">
+            <summary>
+            Appender that logs to a database.
+            </summary>
+            <remarks>
+            <para>
+            <see cref="T:log4net.Appender.AdoNetAppender"/> appends logging events to a table within a
+            database. The appender can be configured to specify the connection 
+            string by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionString"/> property. 
+            The connection type (provider) can be specified by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/>
+            property. For more information on database connection strings for
+            your specific database see <a href="http://www.connectionstrings.com/">http://www.connectionstrings.com/</a>.
+            </para>
+            <para>
+            Records are written into the database either using a prepared
+            statement or a stored procedure. The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property
+            is set to <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify a prepared statement
+            or to <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify a stored
+            procedure.
+            </para>
+            <para>
+            The prepared statement text or the name of the stored procedure
+            must be set in the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property.
+            </para>
+            <para>
+            The prepared statement or stored procedure can take a number
+            of parameters. Parameters are added using the <see cref="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)"/>
+            method. This adds a single <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> to the
+            ordered list of parameters. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/>
+            type may be subclassed if required to provide database specific
+            functionality. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> specifies
+            the parameter name, database type, size, and how the value should
+            be generated using a <see cref="T:log4net.Layout.ILayout"/>.
+            </para>
+            </remarks>
+            <example>
+            An example of a SQL Server table that could be logged to:
+            <code lang="SQL">
+            CREATE TABLE [dbo].[Log] ( 
+              [ID] [int] IDENTITY (1, 1) NOT NULL ,
+              [Date] [datetime] NOT NULL ,
+              [Thread] [varchar] (255) NOT NULL ,
+              [Level] [varchar] (20) NOT NULL ,
+              [Logger] [varchar] (255) NOT NULL ,
+              [Message] [varchar] (4000) NOT NULL 
+            ) ON [PRIMARY]
+            </code>
+            </example>
+            <example>
+            An example configuration to log to the above table:
+            <code lang="XML" escaped="true">
+            <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
+              <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
+              <connectionString value="data source=SQLSVR;initial catalog=test_log4net;integrated security=false;persist security info=True;User ID=sa;Password=sa"/>
+              <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)"/>
+              <parameter>
+                <parameterName value="@log_date"/>
+                <dbType value="DateTime"/>
+                <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}"/>
+              </parameter>
+              <parameter>
+                <parameterName value="@thread"/>
+                <dbType value="String"/>
+                <size value="255"/>
+                <layout type="log4net.Layout.PatternLayout" value="%thread"/>
+              </parameter>
+              <parameter>
+                <parameterName value="@log_level"/>
+                <dbType value="String"/>
+                <size value="50"/>
+                <layout type="log4net.Layout.PatternLayout" value="%level"/>
+              </parameter>
+              <parameter>
+                <parameterName value="@logger"/>
+                <dbType value="String"/>
+                <size value="255"/>
+                <layout type="log4net.Layout.PatternLayout" value="%logger"/>
+              </parameter>
+              <parameter>
+                <parameterName value="@message"/>
+                <dbType value="String"/>
+                <size value="4000"/>
+                <layout type="log4net.Layout.PatternLayout" value="%message"/>
+              </parameter>
+            </appender>
+            </code>
+            </example>
+            <author>Julian Biddle</author>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+            <author>Lance Nehring</author>
+        </member>
+        <member name="T:log4net.Appender.BufferingAppenderSkeleton">
+            <summary>
+            Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/> that 
+            buffers events in a fixed size buffer.
+            </summary>
+            <remarks>
+            <para>
+            This base class should be used by appenders that need to buffer a 
+            number of events before logging them. For example the <see cref="T:log4net.Appender.AdoNetAppender"/> 
+            buffers events and then submits the entire contents of the buffer to 
+            the underlying database in one go.
+            </para>
+            <para>
+            Subclasses should override the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>
+            method to deliver the buffered events.
+            </para>
+            <para>The BufferingAppenderSkeleton maintains a fixed size cyclic 
+            buffer of events. The size of the buffer is set using 
+            the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> property.
+            </para>
+            <para>A <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> is used to inspect 
+            each event as it arrives in the appender. If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> 
+            triggers, then the current buffer is sent immediately 
+            (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>). Otherwise the event 
+            is stored in the buffer. For example, an evaluator can be used to 
+            deliver the events immediately when an ERROR event arrives.
+            </para>
+            <para>
+            The buffering appender can be configured in a <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode. 
+            By default the appender is NOT lossy. When the buffer is full all 
+            the buffered events are sent with <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+            If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property is set to <c>true</c> then the 
+            buffer will not be sent when it is full, and new events arriving 
+            in the appender will overwrite the oldest event in the buffer. 
+            In lossy mode the buffer will only be sent when the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/>
+            triggers. This can be useful behavior when you need to know about 
+            ERROR events but not about events with a lower level, configure an 
+            evaluator that will trigger when an ERROR event arrives, the whole 
+            buffer will be sent which gives a history of events leading up to
+            the ERROR event.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="T:log4net.Appender.AppenderSkeleton">
+            <summary>
+            Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/>. 
+            </summary>
+            <remarks>
+            <para>
+            This class provides the code for common functionality, such 
+            as support for threshold filtering and support for general filters.
+            </para>
+            <para>
+            Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+            they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+            be called after the appenders properties have been configured.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="T:log4net.Appender.IAppender">
+            <summary>
+            Implement this interface for your own strategies for printing log statements.
+            </summary>
+            <remarks>
+            <para>
+            Implementors should consider extending the <see cref="T:log4net.Appender.AppenderSkeleton"/>
+            class which provides a default implementation of this interface.
+            </para>
+            <para>
+            Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+            they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+            be called after the appenders properties have been configured.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="M:log4net.Appender.IAppender.Close">
+            <summary>
+            Closes the appender and releases resources.
+            </summary>
+            <remarks>
+            <para>
+            Releases any resources allocated within the appender such as file handles, 
+            network connections, etc.
+            </para>
+            <para>
+            It is a programming error to append to a closed appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)">
+            <summary>
+            Log the logging event in Appender specific way.
+            </summary>
+            <param name="loggingEvent">The event to log</param>
+            <remarks>
+            <para>
+            This method is called to log a message into this appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.IAppender.Name">
+            <summary>
+            Gets or sets the name of this appender.
+            </summary>
+            <value>The name of the appender.</value>
+            <remarks>
+            <para>The name uniquely identifies the appender.</para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Appender.IBulkAppender">
+            <summary>
+            Interface for appenders that support bulk logging.
+            </summary>
+            <remarks>
+            <para>
+            This interface extends the <see cref="T:log4net.Appender.IAppender"/> interface to
+            support bulk logging of <see cref="T:log4net.Core.LoggingEvent"/> objects. Appenders
+            should only implement this interface if they can bulk log efficiently.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+        </member>
+        <member name="M:log4net.Appender.IBulkAppender.DoAppend(log4net.Core.LoggingEvent[])">
+            <summary>
+            Log the array of logging events in Appender specific way.
+            </summary>
+            <param name="loggingEvents">The events to log</param>
+            <remarks>
+            <para>
+            This method is called to log an array of events into this appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Core.IOptionHandler">
+            <summary>
+            Interface used to delay activate a configured object.
+            </summary>
+            <remarks>
+            <para>
+            This allows an object to defer activation of its options until all
+            options have been set. This is required for components which have
+            related options that remain ambiguous until all are set.
+            </para>
+            <para>
+            If a component implements this interface then the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method 
+            must be called by the container after its all the configured properties have been set 
+            and before the component can be used.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+        </member>
+        <member name="M:log4net.Core.IOptionHandler.ActivateOptions">
+            <summary>
+            Activate the options that were previously set with calls to properties.
+            </summary>
+            <remarks>
+            <para>
+            This allows an object to defer activation of its options until all
+            options have been set. This is required for components which have
+            related options that remain ambiguous until all are set.
+            </para>
+            <para>
+            If a component implements this interface then this method must be called
+            after its properties have been set before the component can be used.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferSize">
+            <summary>
+            Initial buffer size
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferMaxCapacity">
+            <summary>
+            Maximum buffer size before it is recycled
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.#ctor">
+            <summary>
+            Default constructor
+            </summary>
+            <remarks>
+            <para>Empty default constructor</para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.Finalize">
+            <summary>
+            Finalizes this appender by calling the implementation's 
+            <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> method.
+            </summary>
+            <remarks>
+            <para>
+            If this appender has not been closed then the <c>Finalize</c> method
+            will call <see cref="M:log4net.Appender.AppenderSkeleton.Close"/>.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.ActivateOptions">
+            <summary>
+            Initialize the appender based on the options set
+            </summary>
+            <remarks>
+            <para>
+            This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+            activation scheme. The <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> method must 
+            be called on this object after the configuration properties have
+            been set. Until <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> is called this
+            object is in an undefined state and must not be used. 
+            </para>
+            <para>
+            If any of the configuration properties are modified then 
+            <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> must be called again.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.Close">
+            <summary>
+            Closes the appender and release resources.
+            </summary>
+            <remarks>
+            <para>
+            Release any resources allocated within the appender such as file handles, 
+            network connections, etc.
+            </para>
+            <para>
+            It is a programming error to append to a closed appender.
+            </para>
+            <para>
+            This method cannot be overridden by subclasses. This method 
+            delegates the closing of the appender to the <see cref="M:log4net.Appender.AppenderSkeleton.OnClose"/>
+            method which must be overridden in the subclass.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)">
+            <summary>
+            Performs threshold checks and invokes filters before 
+            delegating actual logging to the subclasses specific 
+            <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+            </summary>
+            <param name="loggingEvent">The event to log.</param>
+            <remarks>
+            <para>
+            This method cannot be overridden by derived classes. A
+            derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method
+            which is called by this method.
+            </para>
+            <para>
+            The implementation of this method is as follows:
+            </para>
+            <para>
+            <list type="bullet">
+            	<item>
+            		<description>
+            		Checks that the severity of the <paramref name="loggingEvent"/>
+            		is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+            		appender.</description>
+            	</item>
+            	<item>
+            		<description>
+            		Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the 
+            		<paramref name="loggingEvent"/>.
+            		</description>
+            	</item>
+            	<item>
+            		<description>
+            		Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that 
+            		it returns <c>true</c>.</description>
+            	</item>
+            </list>
+            </para>
+            <para>
+            If all of the above steps succeed then the <paramref name="loggingEvent"/>
+            will be passed to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])">
+            <summary>
+            Performs threshold checks and invokes filters before 
+            delegating actual logging to the subclasses specific 
+            <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+            </summary>
+            <param name="loggingEvents">The array of events to log.</param>
+            <remarks>
+            <para>
+            This method cannot be overridden by derived classes. A
+            derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method
+            which is called by this method.
+            </para>
+            <para>
+            The implementation of this method is as follows:
+            </para>
+            <para>
+            <list type="bullet">
+            	<item>
+            		<description>
+            		Checks that the severity of the <paramref name="loggingEvent"/>
+            		is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+            		appender.</description>
+            	</item>
+            	<item>
+            		<description>
+            		Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the 
+            		<paramref name="loggingEvent"/>.
+            		</description>
+            	</item>
+            	<item>
+            		<description>
+            		Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that 
+            		it returns <c>true</c>.</description>
+            	</item>
+            </list>
+            </para>
+            <para>
+            If all of the above steps succeed then the <paramref name="loggingEvents"/>
+            will be passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.FilterEvent(log4net.Core.LoggingEvent)">
+            <summary>
+            Test if the logging event should we output by this appender
+            </summary>
+            <param name="loggingEvent">the event to test</param>
+            <returns><c>true</c> if the event should be output, <c>false</c> if the event should be ignored</returns>
+            <remarks>
+            <para>
+            This method checks the logging event against the threshold level set
+            on this appender and also against the filters specified on this
+            appender.
+            </para>
+            <para>
+            The implementation of this method is as follows:
+            </para>
+            <para>
+            <list type="bullet">
+            	<item>
+            		<description>
+            		Checks that the severity of the <paramref name="loggingEvent"/>
+            		is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+            		appender.</description>
+            	</item>
+            	<item>
+            		<description>
+            		Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the 
+            		<paramref name="loggingEvent"/>.
+            		</description>
+            	</item>
+            </list>
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.AddFilter(log4net.Filter.IFilter)">
+            <summary>
+            Adds a filter to the end of the filter chain.
+            </summary>
+            <param name="filter">the filter to add to this appender</param>
+            <remarks>
+            <para>
+            The Filters are organized in a linked list.
+            </para>
+            <para>
+            Setting this property causes the new filter to be pushed onto the 
+            back of the filter chain.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.ClearFilters">
+            <summary>
+            Clears the filter list for this appender.
+            </summary>
+            <remarks>
+            <para>
+            Clears the filter list for this appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.IsAsSevereAsThreshold(log4net.Core.Level)">
+            <summary>
+            Checks if the message level is below this appender's threshold.
+            </summary>
+            <param name="level"><see cref="T:log4net.Core.Level"/> to test against.</param>
+            <remarks>
+            <para>
+            If there is no threshold set, then the return value is always <c>true</c>.
+            </para>
+            </remarks>
+            <returns>
+            <c>true</c> if the <paramref name="level"/> meets the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> 
+            requirements of this appender.
+            </returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.OnClose">
+            <summary>
+            Is called when the appender is closed. Derived classes should override 
+            this method if resources need to be released.
+            </summary>
+            <remarks>
+            <para>
+            Releases any resources allocated within the appender such as file handles, 
+            network connections, etc.
+            </para>
+            <para>
+            It is a programming error to append to a closed appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+            <summary>
+            Subclasses of <see cref="T:log4net.Appender.AppenderSkeleton"/> should implement this method 
+            to perform actual logging.
+            </summary>
+            <param name="loggingEvent">The event to append.</param>
+            <remarks>
+            <para>
+            A subclass must implement this method to perform
+            logging of the <paramref name="loggingEvent"/>.
+            </para>
+            <para>This method will be called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+            if all the conditions listed for that method are met.
+            </para>
+            <para>
+            To restrict the logging of events in the appender
+            override the <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> method.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])">
+            <summary>
+            Append a bulk array of logging events.
+            </summary>
+            <param name="loggingEvents">the array of logging events</param>
+            <remarks>
+            <para>
+            This base class implementation calls the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>
+            method for each element in the bulk array.
+            </para>
+            <para>
+            A sub class that can better process a bulk array of events should
+            override this method in addition to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.PreAppendCheck">
+            <summary>
+            Called before <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> as a precondition.
+            </summary>
+            <remarks>
+            <para>
+            This method is called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+            before the call to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+            </para>
+            <para>
+            This method can be overridden in a subclass to extend the checks 
+            made before the event is passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+            </para>
+            <para>
+            A subclass should ensure that they delegate this call to
+            this base class if it is overridden.
+            </para>
+            </remarks>
+            <returns><c>true</c> if the call to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> should proceed.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)">
+            <summary>
+            Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+            </summary>
+            <param name="loggingEvent">The event to render.</param>
+            <returns>The event rendered as a string.</returns>
+            <remarks>
+            <para>
+            Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to 
+            a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+            set to render the <paramref name="loggingEvent"/> to 
+            a string.
+            </para>
+            <para>If there is exception data in the logging event and 
+            the layout does not process the exception, this method 
+            will append the exception text to the rendered string.
+            </para>
+            <para>
+            Where possible use the alternative version of this method
+            <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)"/>.
+            That method streams the rendering onto an existing Writer
+            which can give better performance if the caller already has
+            a <see cref="T:System.IO.TextWriter"/> open and ready for writing.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+            <summary>
+            Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+            </summary>
+            <param name="loggingEvent">The event to render.</param>
+            <param name="writer">The TextWriter to write the formatted event to</param>
+            <remarks>
+            <para>
+            Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to 
+            a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+            set to render the <paramref name="loggingEvent"/> to 
+            a string.
+            </para>
+            <para>If there is exception data in the logging event and 
+            the layout does not process the exception, this method 
+            will append the exception text to the rendered string.
+            </para>
+            <para>
+            Use this method in preference to <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/>
+            where possible. If, however, the caller needs to render the event
+            to a string then <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/> does
+            provide an efficient mechanism for doing so.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_layout">
+            <summary>
+            The layout of this appender.
+            </summary>
+            <remarks>
+            See <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> for more information.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_name">
+            <summary>
+            The name of this appender.
+            </summary>
+            <remarks>
+            See <see cref="P:log4net.Appender.AppenderSkeleton.Name"/> for more information.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_threshold">
+            <summary>
+            The level threshold of this appender.
+            </summary>
+            <remarks>
+            <para>
+            There is no level threshold filtering by default.
+            </para>
+            <para>
+            See <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> for more information.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_errorHandler">
+            <summary>
+            It is assumed and enforced that errorHandler is never null.
+            </summary>
+            <remarks>
+            <para>
+            It is assumed and enforced that errorHandler is never null.
+            </para>
+            <para>
+            See <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> for more information.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_headFilter">
+            <summary>
+            The first filter in the filter chain.
+            </summary>
+            <remarks>
+            <para>
+            Set to <c>null</c> initially.
+            </para>
+            <para>
+            See <see cref="T:log4net.Filter.IFilter"/> for more information.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_tailFilter">
+            <summary>
+            The last filter in the filter chain.
+            </summary>
+            <remarks>
+            See <see cref="T:log4net.Filter.IFilter"/> for more information.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_closed">
+            <summary>
+            Flag indicating if this appender is closed.
+            </summary>
+            <remarks>
+            See <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> for more information.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_recursiveGuard">
+            <summary>
+            The guard prevents an appender from repeatedly calling its own DoAppend method
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AppenderSkeleton.m_renderWriter">
+            <summary>
+            StringWriter used to render events
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.Threshold">
+            <summary>
+            Gets or sets the threshold <see cref="T:log4net.Core.Level"/> of this appender.
+            </summary>
+            <value>
+            The threshold <see cref="T:log4net.Core.Level"/> of the appender. 
+            </value>
+            <remarks>
+            <para>
+            All log events with lower level than the threshold level are ignored 
+            by the appender.
+            </para>
+            <para>
+            In configuration files this option is specified by setting the
+            value of the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> option to a level
+            string, such as "DEBUG", "INFO" and so on.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.ErrorHandler">
+            <summary>
+            Gets or sets the <see cref="T:log4net.Core.IErrorHandler"/> for this appender.
+            </summary>
+            <value>The <see cref="T:log4net.Core.IErrorHandler"/> of the appender</value>
+            <remarks>
+            <para>
+            The <see cref="T:log4net.Appender.AppenderSkeleton"/> provides a default 
+            implementation for the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> property. 
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.FilterHead">
+            <summary>
+            The filter chain.
+            </summary>
+            <value>The head of the filter chain filter chain.</value>
+            <remarks>
+            <para>
+            Returns the head Filter. The Filters are organized in a linked list
+            and so all Filters on this Appender are available through the result.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.Layout">
+            <summary>
+            Gets or sets the <see cref="T:log4net.Layout.ILayout"/> for this appender.
+            </summary>
+            <value>The layout of the appender.</value>
+            <remarks>
+            <para>
+            See <see cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/> for more information.
+            </para>
+            </remarks>
+            <seealso cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.Name">
+            <summary>
+            Gets or sets the name of this appender.
+            </summary>
+            <value>The name of the appender.</value>
+            <remarks>
+            <para>
+            The name uniquely identifies the appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AppenderSkeleton.RequiresLayout">
+            <summary>
+            Tests if this appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+            </summary>
+            <remarks>
+            <para>
+            In the rather exceptional case, where the appender 
+            implementation admits a layout but can also work without it, 
+            then the appender should return <c>true</c>.
+            </para>
+            <para>
+            This default implementation always returns <c>true</c>.
+            </para>
+            </remarks>
+            <returns>
+            <c>true</c> if the appender requires a layout object, otherwise <c>false</c>.
+            </returns>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE">
+            <summary>
+            The default buffer size.
+            </summary>
+            <remarks>
+            The default size of the cyclic buffer used to store events.
+            This is set to 512 by default.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+            </summary>
+            <remarks>
+            <para>
+            Protected default constructor to allow subclassing.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor(System.Boolean)">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+            </summary>
+            <param name="eventMustBeFixed">the events passed through this appender must be
+            fixed by the time that they arrive in the derived class' <c>SendBuffer</c> method.</param>
+            <remarks>
+            <para>
+            Protected constructor to allow subclassing.
+            </para>
+            <para>
+            The <paramref name="eventMustBeFixed"/> should be set if the subclass
+            expects the events delivered to be fixed even if the 
+            <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to zero, i.e. when no buffering occurs.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush">
+            <summary>
+            Flush the currently buffered events
+            </summary>
+            <remarks>
+            <para>
+            Flushes any events that have been buffered.
+            </para>
+            <para>
+            If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+            of the buffer will NOT be flushed to the appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush(System.Boolean)">
+            <summary>
+            Flush the currently buffered events
+            </summary>
+            <param name="flushLossyBuffer">set to <c>true</c> to flush the buffer of lossy events</param>
+            <remarks>
+            <para>
+            Flushes events that have been buffered. If <paramref name="flushLossyBuffer"/> is
+            <c>false</c> then events will only be flushed if this buffer is non-lossy mode.
+            </para>
+            <para>
+            If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+            of the buffer will only be flushed if <paramref name="flushLossyBuffer"/> is <c>true</c>.
+            In this case the contents of the buffer will be tested against the 
+            <see cref="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator"/> and if triggering will be output. All other buffered
+            events will be discarded.
+            </para>
+            <para>
+            If <paramref name="flushLossyBuffer"/> is <c>true</c> then the buffer will always
+            be emptied by calling this method.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions">
+            <summary>
+            Initialize the appender based on the options set
+            </summary>
+            <remarks>
+            <para>
+            This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+            activation scheme. The <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> method must 
+            be called on this object after the configuration properties have
+            been set. Until <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> is called this
+            object is in an undefined state and must not be used. 
+            </para>
+            <para>
+            If any of the configuration properties are modified then 
+            <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> must be called again.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.OnClose">
+            <summary>
+            Close this appender instance.
+            </summary>
+            <remarks>
+            <para>
+            Close this appender instance. If this appender is marked
+            as not <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> then the remaining events in 
+            the buffer must be sent when the appender is closed.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+            <summary>
+            This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method. 
+            </summary>
+            <param name="loggingEvent">the event to log</param>
+            <remarks>
+            <para>
+            Stores the <paramref name="loggingEvent"/> in the cyclic buffer.
+            </para>
+            <para>
+            The buffer will be sent (i.e. passed to the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/> 
+            method) if one of the following conditions is met:
+            </para>
+            <list type="bullet">
+            	<item>
+            		<description>The cyclic buffer is full and this appender is
+            		marked as not lossy (see <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>)</description>
+            	</item>
+            	<item>
+            		<description>An <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> is set and
+            		it is triggered for the <paramref name="loggingEvent"/>
+            		specified.</description>
+            	</item>
+            </list>
+            <para>
+            Before the event is stored in the buffer it is fixed
+            (see <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/>) to ensure that
+            any data referenced by the event will be valid when the buffer
+            is processed.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendFromBuffer(log4net.Core.LoggingEvent,log4net.Util.CyclicBuffer)">
+            <summary>
+            Sends the contents of the buffer.
+            </summary>
+            <param name="firstLoggingEvent">The first logging event.</param>
+            <param name="buffer">The buffer containing the events that need to be send.</param>
+            <remarks>
+            <para>
+            The subclass must override <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])">
+            <summary>
+            Sends the events.
+            </summary>
+            <param name="events">The events that need to be send.</param>
+            <remarks>
+            <para>
+            The subclass must override this method to process the buffered events.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_bufferSize">
+            <summary>
+            The size of the cyclic buffer used to hold the logging events.
+            </summary>
+            <remarks>
+            Set to <see cref="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE"/> by default.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_cb">
+            <summary>
+            The cyclic buffer used to store the logging events.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_evaluator">
+            <summary>
+            The triggering event evaluator that causes the buffer to be sent immediately.
+            </summary>
+            <remarks>
+            The object that is used to determine if an event causes the entire
+            buffer to be sent immediately. This field can be <c>null</c>, which 
+            indicates that event triggering is not to be done. The evaluator
+            can be set using the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> property. If this appender
+            has the <see cref="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy"/> (<see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property) set to 
+            <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be set.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy">
+            <summary>
+            Indicates if the appender should overwrite events in the cyclic buffer 
+            when it becomes full, or if the buffer should be flushed when the 
+            buffer is full.
+            </summary>
+            <remarks>
+            If this field is set to <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must 
+            be set.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossyEvaluator">
+            <summary>
+            The triggering event evaluator filters discarded events.
+            </summary>
+            <remarks>
+            The object that is used to determine if an event that is discarded should
+            really be discarded or if it should be sent to the appenders. 
+            This field can be <c>null</c>, which indicates that all discarded events will
+            be discarded. 
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_fixFlags">
+            <summary>
+            Value indicating which fields in the event should be fixed
+            </summary>
+            <remarks>
+            By default all fields are fixed
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_eventMustBeFixed">
+            <summary>
+            The events delivered to the subclass must be fixed.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.Lossy">
+            <summary>
+            Gets or sets a value that indicates whether the appender is lossy.
+            </summary>
+            <value>
+            <c>true</c> if the appender is lossy, otherwise <c>false</c>. The default is <c>false</c>.
+            </value>
+            <remarks>
+            <para>
+            This appender uses a buffer to store logging events before 
+            delivering them. A triggering event causes the whole buffer
+            to be send to the remote sink. If the buffer overruns before
+            a triggering event then logging events could be lost. Set
+            <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> to <c>false</c> to prevent logging events 
+            from being lost.
+            </para>
+            <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+            <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize">
+            <summary>
+            Gets or sets the size of the cyclic buffer used to hold the 
+            logging events.
+            </summary>
+            <value>
+            The size of the cyclic buffer used to hold the logging events.
+            </value>
+            <remarks>
+            <para>
+            The <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option takes a positive integer
+            representing the maximum number of logging events to collect in 
+            a cyclic buffer. When the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is reached,
+            oldest events are deleted as new events are added to the
+            buffer. By default the size of the cyclic buffer is 512 events.
+            </para>
+            <para>
+            If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to a value less than
+            or equal to 1 then no buffering will occur. The logging event
+            will be delivered synchronously (depending on the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>
+            and <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> properties). Otherwise the event will
+            be buffered.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator">
+            <summary>
+            Gets or sets the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the 
+            buffer to be sent immediately.
+            </summary>
+            <value>
+            The <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the buffer to be
+            sent immediately.
+            </value>
+            <remarks>
+            <para>
+            The evaluator will be called for each event that is appended to this 
+            appender. If the evaluator triggers then the current buffer will 
+            immediately be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+            </para>
+            <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+            <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator">
+            <summary>
+            Gets or sets the value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+            </summary>
+            <value>
+            The value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+            </value>
+            <remarks>
+            <para>
+            The evaluator will be called for each event that is discarded from this 
+            appender. If the evaluator triggers then the current buffer will immediately 
+            be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.OnlyFixPartialEventData">
+            <summary>
+            Gets or sets a value indicating if only part of the logging event data
+            should be fixed.
+            </summary>
+            <value>
+            <c>true</c> if the appender should only fix part of the logging event 
+            data, otherwise <c>false</c>. The default is <c>false</c>.
+            </value>
+            <remarks>
+            <para>
+            Setting this property to <c>true</c> will cause only part of the
+            event data to be fixed and serialized. This will improve performance.
+            </para>
+            <para>
+            See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/> for more information.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.BufferingAppenderSkeleton.Fix">
+            <summary>
+            Gets or sets a the fields that will be fixed in the event
+            </summary>
+            <value>
+            The event fields that will be fixed before the event is buffered
+            </value>
+            <remarks>
+            <para>
+            The logging event needs to have certain thread specific values 
+            captured before it can be buffered. See <see cref="P:log4net.Core.LoggingEvent.Fix"/>
+            for details.
+            </para>
+            </remarks>
+            <seealso cref="P:log4net.Core.LoggingEvent.Fix"/>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.#ctor">
+            <summary> 
+            Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppender"/> class.
+            </summary>
+            <remarks>
+            Public default constructor to initialize a new instance of this class.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.ActivateOptions">
+            <summary>
+            Initialize the appender based on the options set
+            </summary>
+            <remarks>
+            <para>
+            This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+            activation scheme. The <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> method must 
+            be called on this object after the configuration properties have
+            been set. Until <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> is called this
+            object is in an undefined state and must not be used. 
+            </para>
+            <para>
+            If any of the configuration properties are modified then 
+            <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> must be called again.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.OnClose">
+            <summary>
+            Override the parent method to close the database
+            </summary>
+            <remarks>
+            <para>
+            Closes the database command and database connection.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+            <summary>
+            Inserts the events into the database.
+            </summary>
+            <param name="events">The events to insert into the database.</param>
+            <remarks>
+            <para>
+            Insert all the events specified in the <paramref name="events"/>
+            array into the database.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)">
+            <summary>
+            Adds a parameter to the command.
+            </summary>
+            <param name="parameter">The parameter to add to the command.</param>
+            <remarks>
+            <para>
+            Adds a parameter to the ordered list of command parameters.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(System.Data.IDbTransaction,log4net.Core.LoggingEvent[])">
+            <summary>
+            Writes the events to the database using the transaction specified.
+            </summary>
+            <param name="dbTran">The transaction that the events will be executed under.</param>
+            <param name="events">The array of events to insert into the database.</param>
+            <remarks>
+            <para>
+            The transaction argument can be <c>null</c> if the appender has been
+            configured not to use transactions. See <see cref="P:log4net.Appender.AdoNetAppender.UseTransactions"/>
+            property for more information.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.GetLogStatement(log4net.Core.LoggingEvent)">
+            <summary>
+            Formats the log message into database statement text.
+            </summary>
+            <param name="logEvent">The event being logged.</param>
+            <remarks>
+            This method can be overridden by subclasses to provide 
+            more control over the format of the database statement.
+            </remarks>
+            <returns>
+            Text that can be passed to a <see cref="T:System.Data.IDbCommand"/>.
+            </returns>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseConnection">
+            <summary>
+            Connects to the database.
+            </summary>		
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.ResolveConnectionType">
+            <summary>
+            Retrieves the class type of the ADO.NET provider.
+            </summary>
+            <remarks>
+            <para>
+            Gets the Type of the ADO.NET provider to use to connect to the
+            database. This method resolves the type specified in the 
+            <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> property.
+            </para>
+            <para>
+            Subclasses can override this method to return a different type
+            if necessary.
+            </para>
+            </remarks>
+            <returns>The <see cref="T:System.Type"/> of the ADO.NET provider</returns>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseCommand">
+            <summary>
+            Prepares the database command and initialize the parameters.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_usePreparedCommand">
+            <summary>
+            Flag to indicate if we are using a command object
+            </summary>
+            <remarks>
+            <para>
+            Set to <c>true</c> when the appender is to use a prepared
+            statement or stored procedure to insert into the database.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_parameters">
+            <summary>
+            The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+            </summary>
+            <remarks>
+            <para>
+            The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_securityContext">
+            <summary>
+            The security context to use for privileged calls
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_dbConnection">
+            <summary>
+            The <see cref="T:System.Data.IDbConnection"/> that will be used
+            to insert logging events into a database.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_dbCommand">
+            <summary>
+            The database command.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_connectionString">
+            <summary>
+            Database connection string.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_connectionType">
+            <summary>
+            String type name of the <see cref="T:System.Data.IDbConnection"/> type name.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_commandText">
+            <summary>
+            The text of the command.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_commandType">
+            <summary>
+            The command type.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_useTransactions">
+            <summary>
+            Indicates whether to use transactions when writing to the database.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppender.m_reconnectOnError">
+            <summary>
+            Indicates whether to use transactions when writing to the database.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.ConnectionString">
+            <summary>
+            Gets or sets the database connection string that is used to connect to 
+            the database.
+            </summary>
+            <value>
+            The database connection string used to connect to the database.
+            </value>
+            <remarks>
+            <para>
+            The connections string is specific to the connection type.
+            See <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> for more information.
+            </para>
+            </remarks>
+            <example>Connection string for MS Access via ODBC:
+            <code>"DSN=MS Access Database;UID=admin;PWD=;SystemDB=C:\data\System.mdw;SafeTransactions = 0;FIL=MS Access;DriverID = 25;DBQ=C:\data\train33.mdb"</code>
+            </example>
+            <example>Another connection string for MS Access via ODBC:
+            <code>"Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Work\cvs_root\log4net-1.2\access.mdb;UID=;PWD=;"</code>
+            </example>
+            <example>Connection string for MS Access via OLE DB:
+            <code>"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Work\cvs_root\log4net-1.2\access.mdb;User Id=;Password=;"</code>
+            </example>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.ConnectionType">
+            <summary>
+            Gets or sets the type name of the <see cref="T:System.Data.IDbConnection"/> connection
+            that should be created.
+            </summary>
+            <value>
+            The type name of the <see cref="T:System.Data.IDbConnection"/> connection.
+            </value>
+            <remarks>
+            <para>
+            The type name of the ADO.NET provider to use.
+            </para>
+            <para>
+            The default is to use the OLE DB provider.
+            </para>
+            </remarks>
+            <example>Use the OLE DB Provider. This is the default value.
+            <code>System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+            </example>
+            <example>Use the MS SQL Server Provider. 
+            <code>System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+            </example>
+            <example>Use the ODBC Provider. 
+            <code>Microsoft.Data.Odbc.OdbcConnection,Microsoft.Data.Odbc,version=1.0.3300.0,publicKeyToken=b77a5c561934e089,culture=neutral</code>
+            This is an optional package that you can download from 
+            <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a> 
+            search for <b>ODBC .NET Data Provider</b>.
+            </example>
+            <example>Use the Oracle Provider. 
+            <code>System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+            This is an optional package that you can download from 
+            <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a> 
+            search for <b>.NET Managed Provider for Oracle</b>.
+            </example>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.CommandText">
+            <summary>
+            Gets or sets the command text that is used to insert logging events
+            into the database.
+            </summary>
+            <value>
+            The command text used to insert logging events into the database.
+            </value>
+            <remarks>
+            <para>
+            Either the text of the prepared statement or the
+            name of the stored procedure to execute to write into
+            the database.
+            </para>
+            <para>
+            The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property determines if
+            this text is a prepared statement or a stored procedure.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.CommandType">
+            <summary>
+            Gets or sets the command type to execute.
+            </summary>
+            <value>
+            The command type to execute.
+            </value>
+            <remarks>
+            <para>
+            This value may be either <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify
+            that the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> is a prepared statement to execute, 
+            or <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify that the
+            <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property is the name of a stored procedure
+            to execute.
+            </para>
+            <para>
+            The default value is <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>).
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.UseTransactions">
+            <summary>
+            Should transactions be used to insert logging events in the database.
+            </summary>
+            <value>
+            <c>true</c> if transactions should be used to insert logging events in
+            the database, otherwise <c>false</c>. The default value is <c>true</c>.
+            </value>
+            <remarks>
+            <para>
+            Gets or sets a value that indicates whether transactions should be used
+            to insert logging events in the database.
+            </para>
+            <para>
+            When set a single transaction will be used to insert the buffered events
+            into the database. Otherwise each event will be inserted without using
+            an explicit transaction.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.SecurityContext">
+            <summary>
+            Gets or sets the <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+            </summary>
+            <value>
+            The <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+            </value>
+            <remarks>
+            <para>
+            Unless a <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> specified here for this appender
+            the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+            security context to use. The default behavior is to use the security context
+            of the current thread.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.ReconnectOnError">
+            <summary>
+            Should this appender try to reconnect to the database on error.
+            </summary>
+            <value>
+            <c>true</c> if the appender should try to reconnect to the database after an
+            error has occurred, otherwise <c>false</c>. The default value is <c>false</c>, 
+            i.e. not to try to reconnect.
+            </value>
+            <remarks>
+            <para>
+            The default behaviour is for the appender not to try to reconnect to the
+            database if an error occurs. Subsequent logging events are discarded.
+            </para>
+            <para>
+            To force the appender to attempt to reconnect to the database set this
+            property to <c>true</c>.
+            </para>
+            <note>
+            When the appender attempts to connect to the database there may be a
+            delay of up to the connection timeout specified in the connection string.
+            This delay will block the calling application's thread. 
+            Until the connection can be reestablished this potential delay may occur multiple times.
+            </note>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppender.Connection">
+            <summary>
+            Gets or sets the underlying <see cref="T:System.Data.IDbConnection"/>.
+            </summary>
+            <value>
+            The underlying <see cref="T:System.Data.IDbConnection"/>.
+            </value>
+            <remarks>
+            <see cref="T:log4net.Appender.AdoNetAppender"/> creates a <see cref="T:System.Data.IDbConnection"/> to insert 
+            logging events into a database.  Classes deriving from <see cref="T:log4net.Appender.AdoNetAppender"/> 
+            can use this property to get or set this <see cref="T:System.Data.IDbConnection"/>.  Use the 
+            underlying <see cref="T:System.Data.IDbConnection"/> returned from <see cref="P:log4net.Appender.AdoNetAppender.Connection"/> if 
+            you require access beyond that which <see cref="T:log4net.Appender.AdoNetAppender"/> provides.
+            </remarks>
+        </member>
+        <member name="T:log4net.Appender.AdoNetAppenderParameter">
+            <summary>
+            Parameter type used by the <see cref="T:log4net.Appender.AdoNetAppender"/>.
+            </summary>
+            <remarks>
+            <para>
+            This class provides the basic database parameter properties
+            as defined by the <see cref="T:System.Data.IDbDataParameter"/> interface.
+            </para>
+            <para>This type can be subclassed to provide database specific
+            functionality. The two methods that are called externally are
+            <see cref="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)"/> and <see cref="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)"/>.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppenderParameter.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> class.
+            </summary>
+            <remarks>
+            Default constructor for the AdoNetAppenderParameter class.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)">
+            <summary>
+            Prepare the specified database command object.
+            </summary>
+            <param name="command">The command to prepare.</param>
+            <remarks>
+            <para>
+            Prepares the database command object by adding
+            this parameter to its collection of parameters.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)">
+            <summary>
+            Renders the logging event and set the parameter value in the command.
+            </summary>
+            <param name="command">The command containing the parameter.</param>
+            <param name="loggingEvent">The event to be rendered.</param>
+            <remarks>
+            <para>
+            Renders the logging event using this parameters layout
+            object. Sets the value of the parameter on the command object.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_parameterName">
+            <summary>
+            The name of this parameter.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_dbType">
+            <summary>
+            The database type for this parameter.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_inferType">
+            <summary>
+            Flag to infer type rather than use the DbType
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_precision">
+            <summary>
+            The precision for this parameter.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_scale">
+            <summary>
+            The scale for this parameter.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_size">
+            <summary>
+            The size for this parameter.
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AdoNetAppenderParameter.m_layout">
+            <summary>
+            The <see cref="T:log4net.Layout.IRawLayout"/> to use to render the
+            logging event into an object for this parameter.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.ParameterName">
+            <summary>
+            Gets or sets the name of this parameter.
+            </summary>
+            <value>
+            The name of this parameter.
+            </value>
+            <remarks>
+            <para>
+            The name of this parameter. The parameter name
+            must match up to a named parameter to the SQL stored procedure
+            or prepared statement.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.DbType">
+            <summary>
+            Gets or sets the database type for this parameter.
+            </summary>
+            <value>
+            The database type for this parameter.
+            </value>
+            <remarks>
+            <para>
+            The database type for this parameter. This property should
+            be set to the database type from the <see cref="P:log4net.Appender.AdoNetAppenderParameter.DbType"/>
+            enumeration. See <see cref="P:System.Data.IDataParameter.DbType"/>.
+            </para>
+            <para>
+            This property is optional. If not specified the ADO.NET provider 
+            will attempt to infer the type from the value.
+            </para>
+            </remarks>
+            <seealso cref="P:System.Data.IDataParameter.DbType"/>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.Precision">
+            <summary>
+            Gets or sets the precision for this parameter.
+            </summary>
+            <value>
+            The precision for this parameter.
+            </value>
+            <remarks>
+            <para>
+            The maximum number of digits used to represent the Value.
+            </para>
+            <para>
+            This property is optional. If not specified the ADO.NET provider 
+            will attempt to infer the precision from the value.
+            </para>
+            </remarks>
+            <seealso cref="P:System.Data.IDbDataParameter.Precision"/>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.Scale">
+            <summary>
+            Gets or sets the scale for this parameter.
+            </summary>
+            <value>
+            The scale for this parameter.
+            </value>
+            <remarks>
+            <para>
+            The number of decimal places to which Value is resolved.
+            </para>
+            <para>
+            This property is optional. If not specified the ADO.NET provider 
+            will attempt to infer the scale from the value.
+            </para>
+            </remarks>
+            <seealso cref="P:System.Data.IDbDataParameter.Scale"/>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.Size">
+            <summary>
+            Gets or sets the size for this parameter.
+            </summary>
+            <value>
+            The size for this parameter.
+            </value>
+            <remarks>
+            <para>
+            The maximum size, in bytes, of the data within the column.
+            </para>
+            <para>
+            This property is optional. If not specified the ADO.NET provider 
+            will attempt to infer the size from the value.
+            </para>
+            </remarks>
+            <seealso cref="P:System.Data.IDbDataParameter.Size"/>
+        </member>
+        <member name="P:log4net.Appender.AdoNetAppenderParameter.Layout">
+            <summary>
+            Gets or sets the <see cref="T:log4net.Layout.IRawLayout"/> to use to 
+            render the logging event into an object for this 
+            parameter.
+            </summary>
+            <value>
+            The <see cref="T:log4net.Layout.IRawLayout"/> used to render the
+            logging event into an object for this parameter.
+            </value>
+            <remarks>
+            <para>
+            The <see cref="T:log4net.Layout.IRawLayout"/> that renders the value for this
+            parameter.
+            </para>
+            <para>
+            The <see cref="T:log4net.Layout.RawLayoutConverter"/> can be used to adapt
+            any <see cref="T:log4net.Layout.ILayout"/> into a <see cref="T:log4net.Layout.IRawLayout"/>
+            for use in the property.
+            </para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Appender.AnsiColorTerminalAppender">
+            <summary>
+            Appends logging events to the terminal using ANSI color escape sequences.
+            </summary>
+            <remarks>
+            <para>
+            AnsiColorTerminalAppender appends log events to the standard output stream
+            or the error output stream using a layout specified by the 
+            user. It also allows the color of a specific level of message to be set.
+            </para>
+            <note>
+            This appender expects the terminal to understand the VT100 control set 
+            in order to interpret the color codes. If the terminal or console does not
+            understand the control codes the behavior is not defined.
+            </note>
+            <para>
+            By default, all output is written to the console's standard output stream.
+            The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> property can be set to direct the output to the
+            error stream.
+            </para>
+            <para>
+            NOTE: This appender writes each message to the <c>System.Console.Out</c> or 
+            <c>System.Console.Error</c> that is set at the time the event is appended.
+            Therefore it is possible to programmatically redirect the output of this appender 
+            (for example NUnit does this to capture program output). While this is the desired
+            behavior of this appender it may have security implications in your application. 
+            </para>
+            <para>
+            When configuring the ANSI colored terminal appender, a mapping should be
+            specified to map a logging level to a color. For example:
+            </para>
+            <code lang="XML" escaped="true">
+            <mapping>
+            	<level value="ERROR"/>
+            	<foreColor value="White"/>
+            	<backColor value="Red"/>
+                <attributes value="Bright,Underscore"/>
+            </mapping>
+            <mapping>
+            	<level value="DEBUG"/>
+            	<backColor value="Green"/>
+            </mapping>
+            </code>
+            <para>
+            The Level is the standard log4net logging level and ForeColor and BackColor can be any
+            of the following values:
+            <list type="bullet">
+            <item><term>Blue</term><description></description></item>
+            <item><term>Green</term><description></description></item>
+            <item><term>Red</term><description></description></item>
+            <item><term>White</term><description></description></item>
+            <item><term>Yellow</term><description></description></item>
+            <item><term>Purple</term><description></description></item>
+            <item><term>Cyan</term><description></description></item>
+            </list>
+            These color values cannot be combined together to make new colors.
+            </para>
+            <para>
+            The attributes can be any combination of the following:
+            <list type="bullet">
+            <item><term>Bright</term><description>foreground is brighter</description></item>
+            <item><term>Dim</term><description>foreground is dimmer</description></item>
+            <item><term>Underscore</term><description>message is underlined</description></item>
+            <item><term>Blink</term><description>foreground is blinking (does not work on all terminals)</description></item>
+            <item><term>Reverse</term><description>foreground and background are reversed</description></item>
+            <item><term>Hidden</term><description>output is hidden</description></item>
+            <item><term>Strikethrough</term><description>message has a line through it</description></item>
+            </list>
+            While any of these attributes may be combined together not all combinations
+            work well together, for example setting both <i>Bright</i> and <i>Dim</i> attributes makes
+            no sense.
+            </para>
+            </remarks>
+            <author>Patrick Wagstrom</author>
+            <author>Nicko Cadell</author>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleOut">
+            <summary>
+            The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console 
+            standard output stream.
+            </summary>
+            <remarks>
+            <para>
+            The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console 
+            standard output stream.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleError">
+            <summary>
+            The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console 
+            standard error output stream.
+            </summary>
+            <remarks>
+            <para>
+            The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console 
+            standard error output stream.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.PostEventCodes">
+            <summary>
+            Ansi code to reset terminal
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AnsiColorTerminalAppender.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class.
+            </summary>
+            <remarks>
+            The instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class is set up to write 
+            to the standard output stream.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AnsiColorTerminalAppender.AddMapping(log4net.Appender.AnsiColorTerminalAppender.LevelColors)">
+            <summary>
+            Add a mapping of level to color
+            </summary>
+            <param name="mapping">The mapping to add</param>
+            <remarks>
+            <para>
+            Add a <see cref="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors"/> mapping to this appender.
+            Each mapping defines the foreground and background colours
+            for a level.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AnsiColorTerminalAppender.Append(log4net.Core.LoggingEvent)">
+            <summary>
+            This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+            </summary>
+            <param name="loggingEvent">The event to log.</param>
+            <remarks>
+            <para>
+            Writes the event to the console.
+            </para>
+            <para>
+            The format of the output will depend on the appender's layout.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AnsiColorTerminalAppender.ActivateOptions">
+            <summary>
+            Initialize the options for this appender
+            </summary>
+            <remarks>
+            <para>
+            Initialize the level to color mappings set on this appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_writeToErrorStream">
+            <summary>
+            Flag to write output to the error stream rather than the standard output stream
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_levelMapping">
+            <summary>
+            Mapping from level object to color value
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.Target">
+            <summary>
+            Target is the value of the console output stream.
+            </summary>
+            <value>
+            Target is the value of the console output stream.
+            This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+            </value>
+            <remarks>
+            <para>
+            Target is the value of the console output stream.
+            This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.RequiresLayout">
+            <summary>
+            This appender requires a <see cref="N:log4net.Layout"/> to be set.
+            </summary>
+            <value><c>true</c></value>
+            <remarks>
+            <para>
+            This appender requires a <see cref="N:log4net.Layout"/> to be set.
+            </para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes">
+            <summary>
+            The enum of possible display attributes
+            </summary>
+            <remarks>
+            <para>
+            The following flags can be combined together to
+            form the ANSI color attributes.
+            </para>
+            </remarks>
+            <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Bright">
+            <summary>
+            text is bright
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Dim">
+            <summary>
+            text is dim
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Underscore">
+            <summary>
+            text is underlined
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Blink">
+            <summary>
+            text is blinking
+            </summary>
+            <remarks>
+            Not all terminals support this attribute
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Reverse">
+            <summary>
+            text and background colors are reversed
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Hidden">
+            <summary>
+            text is hidden
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Strikethrough">
+            <summary>
+            text is displayed with a strikethrough
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiColor">
+            <summary>
+            The enum of possible foreground or background color values for 
+            use with the color mapping method
+            </summary>
+            <remarks>
+            <para>
+            The output can be in one for the following ANSI colors.
+            </para>
+            </remarks>
+            <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Black">
+            <summary>
+            color is black
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Red">
+            <summary>
+            color is red
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Green">
+            <summary>
+            color is green
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Yellow">
+            <summary>
+            color is yellow
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Blue">
+            <summary>
+            color is blue
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Magenta">
+            <summary>
+            color is magenta
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Cyan">
+            <summary>
+            color is cyan
+            </summary>
+        </member>
+        <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.White">
+            <summary>
+            color is white
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors">
+            <summary>
+            A class to act as a mapping between the level that a logging call is made at and
+            the color it should be displayed as.
+            </summary>
+            <remarks>
+            <para>
+            Defines the mapping between a level and the color it should be displayed in.
+            </para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Util.LevelMappingEntry">
+            <summary>
+            An entry in the <see cref="T:log4net.Util.LevelMapping"/>
+            </summary>
+            <remarks>
+            <para>
+            This is an abstract base class for types that are stored in the
+            <see cref="T:log4net.Util.LevelMapping"/> object.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+        </member>
+        <member name="M:log4net.Util.LevelMappingEntry.#ctor">
+            <summary>
+            Default protected constructor
+            </summary>
+            <remarks>
+            <para>
+            Default protected constructor
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Util.LevelMappingEntry.ActivateOptions">
+            <summary>
+            Initialize any options defined on this entry
+            </summary>
+            <remarks>
+            <para>
+            Should be overridden by any classes that need to initialise based on their options
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Util.LevelMappingEntry.Level">
+            <summary>
+            The level that is the key for this mapping 
+            </summary>
+            <value>
+            The <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this mapping 
+            </value>
+            <remarks>
+            <para>
+            Get or set the <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this
+            mapping subclass.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ActivateOptions">
+            <summary>
+            Initialize the options for the object
+            </summary>
+            <remarks>
+            <para>
+            Combine the <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> together
+            and append the attributes.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor">
+            <summary>
+            The mapped foreground color for the specified level
+            </summary>
+            <remarks>
+            <para>
+            Required property.
+            The mapped foreground color for the specified level
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor">
+            <summary>
+            The mapped background color for the specified level
+            </summary>
+            <remarks>
+            <para>
+            Required property.
+            The mapped background color for the specified level
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes">
+            <summary>
+            The color attributes for the specified level
+            </summary>
+            <remarks>
+            <para>
+            Required property.
+            The color attributes for the specified level
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.CombinedColor">
+            <summary>
+            The combined <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/>, <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> and
+            <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes"/> suitable for setting the ansi terminal color.
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AppenderCollection">
+            <summary>
+            A strongly-typed collection of <see cref="T:log4net.Appender.IAppender"/> objects.
+            </summary>
+            <author>Nicko Cadell</author>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.ReadOnly(log4net.Appender.AppenderCollection)">
+            <summary>
+            Creates a read-only wrapper for a <c>AppenderCollection</c> instance.
+            </summary>
+            <param name="list">list to create a readonly wrapper arround</param>
+            <returns>
+            An <c>AppenderCollection</c> wrapper that is read-only.
+            </returns>
+        </member>
+        <member name="F:log4net.Appender.AppenderCollection.EmptyCollection">
+            <summary>
+            An empty readonly static AppenderCollection
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor">
+            <summary>
+            Initializes a new instance of the <c>AppenderCollection</c> class
+            that is empty and has the default initial capacity.
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Int32)">
+            <summary>
+            Initializes a new instance of the <c>AppenderCollection</c> class
+            that has the specified initial capacity.
+            </summary>
+            <param name="capacity">
+            The number of elements that the new <c>AppenderCollection</c> is initially capable of storing.
+            </param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection)">
+            <summary>
+            Initializes a new instance of the <c>AppenderCollection</c> class
+            that contains elements copied from the specified <c>AppenderCollection</c>.
+            </summary>
+            <param name="c">The <c>AppenderCollection</c> whose elements are copied to the new collection.</param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.IAppender[])">
+            <summary>
+            Initializes a new instance of the <c>AppenderCollection</c> class
+            that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> array.
+            </summary>
+            <param name="a">The <see cref="T:log4net.Appender.IAppender"/> array whose elements are copied to the new list.</param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Collections.ICollection)">
+            <summary>
+            Initializes a new instance of the <c>AppenderCollection</c> class
+            that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> collection.
+            </summary>
+            <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements are copied to the new list.</param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection.Tag)">
+            <summary>
+            Allow subclasses to avoid our default constructors
+            </summary>
+            <param name="tag"></param>
+            <exclude/>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[])">
+            <summary>
+            Copies the entire <c>AppenderCollection</c> to a one-dimensional
+            <see cref="T:log4net.Appender.IAppender"/> array.
+            </summary>
+            <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[],System.Int32)">
+            <summary>
+            Copies the entire <c>AppenderCollection</c> to a one-dimensional
+            <see cref="T:log4net.Appender.IAppender"/> array, starting at the specified index of the target array.
+            </summary>
+            <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+            <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Add(log4net.Appender.IAppender)">
+            <summary>
+            Adds a <see cref="T:log4net.Appender.IAppender"/> to the end of the <c>AppenderCollection</c>.
+            </summary>
+            <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to be added to the end of the <c>AppenderCollection</c>.</param>
+            <returns>The index at which the value has been added.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Clear">
+            <summary>
+            Removes all elements from the <c>AppenderCollection</c>.
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Clone">
+            <summary>
+            Creates a shallow copy of the <see cref="T:log4net.Appender.AppenderCollection"/>.
+            </summary>
+            <returns>A new <see cref="T:log4net.Appender.AppenderCollection"/> with a shallow copy of the collection data.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Contains(log4net.Appender.IAppender)">
+            <summary>
+            Determines whether a given <see cref="T:log4net.Appender.IAppender"/> is in the <c>AppenderCollection</c>.
+            </summary>
+            <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to check for.</param>
+            <returns><c>true</c> if <paramref name="item"/> is found in the <c>AppenderCollection</c>; otherwise, <c>false</c>.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.IndexOf(log4net.Appender.IAppender)">
+            <summary>
+            Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Appender.IAppender"/>
+            in the <c>AppenderCollection</c>.
+            </summary>
+            <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to locate in the <c>AppenderCollection</c>.</param>
+            <returns>
+            The zero-based index of the first occurrence of <paramref name="item"/> 
+            in the entire <c>AppenderCollection</c>, if found; otherwise, -1.
+            </returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Insert(System.Int32,log4net.Appender.IAppender)">
+            <summary>
+            Inserts an element into the <c>AppenderCollection</c> at the specified index.
+            </summary>
+            <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+            <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to insert.</param>
+            <exception cref="T:System.ArgumentOutOfRangeException">
+            <para><paramref name="index"/> is less than zero</para>
+            <para>-or-</para>
+            <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Remove(log4net.Appender.IAppender)">
+            <summary>
+            Removes the first occurrence of a specific <see cref="T:log4net.Appender.IAppender"/> from the <c>AppenderCollection</c>.
+            </summary>
+            <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to remove from the <c>AppenderCollection</c>.</param>
+            <exception cref="T:System.ArgumentException">
+            The specified <see cref="T:log4net.Appender.IAppender"/> was not found in the <c>AppenderCollection</c>.
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.RemoveAt(System.Int32)">
+            <summary>
+            Removes the element at the specified index of the <c>AppenderCollection</c>.
+            </summary>
+            <param name="index">The zero-based index of the element to remove.</param>
+            <exception cref="T:System.ArgumentOutOfRangeException">
+            <para><paramref name="index"/> is less than zero</para>
+            <para>-or-</para>
+            <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.GetEnumerator">
+            <summary>
+            Returns an enumerator that can iterate through the <c>AppenderCollection</c>.
+            </summary>
+            <returns>An <see cref="T:log4net.Appender.AppenderCollection.Enumerator"/> for the entire <c>AppenderCollection</c>.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.AppenderCollection)">
+            <summary>
+            Adds the elements of another <c>AppenderCollection</c> to the current <c>AppenderCollection</c>.
+            </summary>
+            <param name="x">The <c>AppenderCollection</c> whose elements should be added to the end of the current <c>AppenderCollection</c>.</param>
+            <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.IAppender[])">
+            <summary>
+            Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> array to the current <c>AppenderCollection</c>.
+            </summary>
+            <param name="x">The <see cref="T:log4net.Appender.IAppender"/> array whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+            <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.AddRange(System.Collections.ICollection)">
+            <summary>
+            Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> collection to the current <c>AppenderCollection</c>.
+            </summary>
+            <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+            <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.TrimToSize">
+            <summary>
+            Sets the capacity to the actual number of elements.
+            </summary>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.ToArray">
+            <summary>
+            Return the collection elements as an array
+            </summary>
+            <returns>the array</returns>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32)">
+            <exception cref="T:System.ArgumentOutOfRangeException">
+            <para><paramref name="index"/> is less than zero</para>
+            <para>-or-</para>
+            <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32,System.Boolean)">
+            <exception cref="T:System.ArgumentOutOfRangeException">
+            <para><paramref name="index"/> is less than zero</para>
+            <para>-or-</para>
+            <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+            </exception>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.Count">
+            <summary>
+            Gets the number of elements actually contained in the <c>AppenderCollection</c>.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.IsSynchronized">
+            <summary>
+            Gets a value indicating whether access to the collection is synchronized (thread-safe).
+            </summary>
+            <returns>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</returns>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.SyncRoot">
+            <summary>
+            Gets an object that can be used to synchronize access to the collection.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.Item(System.Int32)">
+            <summary>
+            Gets or sets the <see cref="T:log4net.Appender.IAppender"/> at the specified index.
+            </summary>
+            <param name="index">The zero-based index of the element to get or set.</param>
+            <exception cref="T:System.ArgumentOutOfRangeException">
+            	<para><paramref name="index"/> is less than zero</para>
+            	<para>-or-</para>
+            	<para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+            </exception>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.IsFixedSize">
+            <summary>
+            Gets a value indicating whether the collection has a fixed size.
+            </summary>
+            <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.IsReadOnly">
+            <summary>
+            Gets a value indicating whether the IList is read-only.
+            </summary>
+            <value>true if the collection is read-only; otherwise, false. The default is false</value>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.Capacity">
+            <summary>
+            Gets or sets the number of elements the <c>AppenderCollection</c> can contain.
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator">
+            <summary>
+            Supports type-safe iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+            </summary>
+            <exclude/>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.MoveNext">
+            <summary>
+            Advances the enumerator to the next element in the collection.
+            </summary>
+            <returns>
+            <c>true</c> if the enumerator was successfully advanced to the next element; 
+            <c>false</c> if the enumerator has passed the end of the collection.
+            </returns>
+            <exception cref="T:System.InvalidOperationException">
+            The collection was modified after the enumerator was created.
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Reset">
+            <summary>
+            Sets the enumerator to its initial position, before the first element in the collection.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Current">
+            <summary>
+            Gets the current element in the collection.
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AppenderCollection.Tag">
+            <summary>
+            Type visible only to our subclasses
+            Used to access protected constructor
+            </summary>
+            <exclude/>
+        </member>
+        <member name="F:log4net.Appender.AppenderCollection.Tag.Default">
+            <summary>
+            A value
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AppenderCollection.Enumerator">
+            <summary>
+            Supports simple iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+            </summary>
+            <exclude/>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Enumerator.#ctor(log4net.Appender.AppenderCollection)">
+            <summary>
+            Initializes a new instance of the <c>Enumerator</c> class.
+            </summary>
+            <param name="tc"></param>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Enumerator.MoveNext">
+            <summary>
+            Advances the enumerator to the next element in the collection.
+            </summary>
+            <returns>
+            <c>true</c> if the enumerator was successfully advanced to the next element; 
+            <c>false</c> if the enumerator has passed the end of the collection.
+            </returns>
+            <exception cref="T:System.InvalidOperationException">
+            The collection was modified after the enumerator was created.
+            </exception>
+        </member>
+        <member name="M:log4net.Appender.AppenderCollection.Enumerator.Reset">
+            <summary>
+            Sets the enumerator to its initial position, before the first element in the collection.
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.AppenderCollection.Enumerator.Current">
+            <summary>
+            Gets the current element in the collection.
+            </summary>
+        </member>
+        <member name="T:log4net.Appender.AppenderCollection.ReadOnlyAppenderCollection">
+            <exclude/>
+        </member>
+        <member name="T:log4net.Appender.AspNetTraceAppender">
+            <summary>
+            <para>
+            Appends log events to the ASP.NET <see cref="T:System.Web.TraceContext"/> system.
+            </para>
+            </summary>
+            <remarks>
+            <para>
+            Diagnostic information and tracing messages that you specify are appended to the output 
+            of the page that is sent to the requesting browser. Optionally, you can view this information
+            from a separate trace viewer (Trace.axd) that displays trace information for every page in a 
+            given application.
+            </para>
+            <para>
+            Trace statements are processed and displayed only when tracing is enabled. You can control 
+            whether tracing is displayed to a page, to the trace viewer, or both.
+            </para>
+            <para>
+            The logging event is passed to the <see cref="M:System.Web.TraceContext.Write(System.String)"/> or 
+            <see cref="M:System.Web.TraceContext.Warn(System.String)"/> method depending on the level of the logging event.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="M:log4net.Appender.AspNetTraceAppender.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.AspNetTraceAppender"/> class.
+            </summary>
+            <remarks>
+            <para>
+            Default constructor.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.AspNetTraceAppender.Append(log4net.Core.LoggingEvent)">
+            <summary>
+            Write the logging event to the ASP.NET trace
+            </summary>
+            <param name="loggingEvent">the event to log</param>
+            <remarks>
+            <para>
+            Write the logging event to the ASP.NET trace
+            <c>HttpContext.Current.Trace</c> 
+            (<see cref="T:System.Web.TraceContext"/>).
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Appender.AspNetTraceAppender.RequiresLayout">
+            <summary>
+            This appender requires a <see cref="N:log4net.Layout"/> to be set.
+            </summary>
+            <value><c>true</c></value>
+            <remarks>
+            <para>
+            This appender requires a <see cref="N:log4net.Layout"/> to be set.
+            </para>
+            </remarks>
+        </member>
+        <member name="T:log4net.Appender.BufferingForwardingAppender">
+            <summary>
+            Buffers events and then forwards them to attached appenders.
+            </summary>
+            <remarks>
+            <para>
+            The events are buffered in this appender until conditions are
+            met to allow the appender to deliver the events to the attached 
+            appenders. See <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> for the
+            conditions that cause the buffer to be sent.
+            </para>
+            <para>The forwarding appender can be used to specify different 
+            thresholds and filters for the same appender at different locations 
+            within the hierarchy.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="T:log4net.Core.IAppenderAttachable">
+            <summary>
+            Interface for attaching appenders to objects.
+            </summary>
+            <remarks>
+            <para>
+            Interface for attaching, removing and retrieving appenders.
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="M:log4net.Core.IAppenderAttachable.AddAppender(log4net.Appender.IAppender)">
+            <summary>
+            Attaches an appender.
+            </summary>
+            <param name="appender">The appender to add.</param>
+            <remarks>
+            <para>
+            Add the specified appender. The implementation may
+            choose to allow or deny duplicate appenders.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Core.IAppenderAttachable.GetAppender(System.String)">
+            <summary>
+            Gets an attached appender with the specified name.
+            </summary>
+            <param name="name">The name of the appender to get.</param>
+            <returns>
+            The appender with the name specified, or <c>null</c> if no appender with the
+            specified name is found.
+            </returns>
+            <remarks>
+            <para>
+            Returns an attached appender with the <paramref name="name"/> specified.
+            If no appender with the specified name is found <c>null</c> will be
+            returned.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Core.IAppenderAttachable.RemoveAllAppenders">
+            <summary>
+            Removes all attached appenders.
+            </summary>
+            <remarks>
+            <para>
+            Removes and closes all attached appenders
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(log4net.Appender.IAppender)">
+            <summary>
+            Removes the specified appender from the list of attached appenders.
+            </summary>
+            <param name="appender">The appender to remove.</param>
+            <returns>The appender removed from the list</returns>
+            <remarks>
+            <para>
+            The appender removed is not closed.
+            If you are discarding the appender you must call
+            <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(System.String)">
+            <summary>
+            Removes the appender with the specified name from the list of appenders.
+            </summary>
+            <param name="name">The name of the appender to remove.</param>
+            <returns>The appender removed from the list</returns>
+            <remarks>
+            <para>
+            The appender removed is not closed.
+            If you are discarding the appender you must call
+            <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+            </para>
+            </remarks>
+        </member>
+        <member name="P:log4net.Core.IAppenderAttachable.Appenders">
+            <summary>
+            Gets all attached appenders.
+            </summary>
+            <value>
+            A collection of attached appenders.
+            </value>
+            <remarks>
+            <para>
+            Gets a collection of attached appenders.
+            If there are no attached appenders the
+            implementation should return an empty 
+            collection rather than <c>null</c>.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.BufferingForwardingAppender"/> class.
+            </summary>
+            <remarks>
+            <para>
+            Default constructor.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.OnClose">
+            <summary>
+            Closes the appender and releases resources.
+            </summary>
+            <remarks>
+            <para>
+            Releases any resources allocated within the appender such as file handles, 
+            network connections, etc.
+            </para>
+            <para>
+            It is a programming error to append to a closed appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+            <summary>
+            Send the events.
+            </summary>
+            <param name="events">The events that need to be send.</param>
+            <remarks>
+            <para>
+            Forwards the events to the attached appenders.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.AddAppender(log4net.Appender.IAppender)">
+            <summary>
+            Adds an <see cref="T:log4net.Appender.IAppender"/> to the list of appenders of this
+            instance.
+            </summary>
+            <param name="newAppender">The <see cref="T:log4net.Appender.IAppender"/> to add to this appender.</param>
+            <remarks>
+            <para>
+            If the specified <see cref="T:log4net.Appender.IAppender"/> is already in the list of
+            appenders, then it won't be added again.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.GetAppender(System.String)">
+            <summary>
+            Looks for the appender with the specified name.
+            </summary>
+            <param name="name">The name of the appender to lookup.</param>
+            <returns>
+            The appender with the specified name, or <c>null</c>.
+            </returns>
+            <remarks>
+            <para>
+            Get the named appender attached to this buffering appender.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAllAppenders">
+            <summary>
+            Removes all previously added appenders from this appender.
+            </summary>
+            <remarks>
+            <para>
+            This is useful when re-reading configuration information.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(log4net.Appender.IAppender)">
+            <summary>
+            Removes the specified appender from the list of appenders.
+            </summary>
+            <param name="appender">The appender to remove.</param>
+            <returns>The appender removed from the list</returns>
+            <remarks>
+            The appender removed is not closed.
+            If you are discarding the appender you must call
+            <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(System.String)">
+            <summary>
+            Removes the appender with the specified name from the list of appenders.
+            </summary>
+            <param name="name">The name of the appender to remove.</param>
+            <returns>The appender removed from the list</returns>
+            <remarks>
+            The appender removed is not closed.
+            If you are discarding the appender you must call
+            <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.BufferingForwardingAppender.m_appenderAttachedImpl">
+            <summary>
+            Implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+            </summary>
+        </member>
+        <member name="P:log4net.Appender.BufferingForwardingAppender.Appenders">
+            <summary>
+            Gets the appenders contained in this appender as an 
+            <see cref="T:System.Collections.ICollection"/>.
+            </summary>
+            <remarks>
+            If no appenders can be found, then an <see cref="T:log4net.Util.EmptyCollection"/> 
+            is returned.
+            </remarks>
+            <returns>
+            A collection of the appenders in this appender.
+            </returns>
+        </member>
+        <member name="T:log4net.Appender.ConsoleAppender">
+            <summary>
+            Appends logging events to the console.
+            </summary>
+            <remarks>
+            <para>
+            ConsoleAppender appends log events to the standard output stream
+            or the error output stream using a layout specified by the 
+            user.
+            </para>
+            <para>
+            By default, all output is written to the console's standard output stream.
+            The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> property can be set to direct the output to the
+            error stream.
+            </para>
+            <para>
+            NOTE: This appender writes each message to the <c>System.Console.Out</c> or 
+            <c>System.Console.Error</c> that is set at the time the event is appended.
+            Therefore it is possible to programmatically redirect the output of this appender 
+            (for example NUnit does this to capture program output). While this is the desired
+            behavior of this appender it may have security implications in your application. 
+            </para>
+            </remarks>
+            <author>Nicko Cadell</author>
+            <author>Gert Driesen</author>
+        </member>
+        <member name="F:log4net.Appender.ConsoleAppender.ConsoleOut">
+            <summary>
+            The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console 
+            standard output stream.
+            </summary>
+            <remarks>
+            <para>
+            The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console 
+            standard output stream.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:log4net.Appender.ConsoleAppender.ConsoleError">
+            <summary>
+            The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console 
+            standard error output stream.
+            </summary>
+            <remarks>
+            <para>
+            The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console 
+            standard error output stream.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.ConsoleAppender.#ctor">
+            <summary>
+            Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class.
+            </summary>
+            <remarks>
+            The instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class is set up to write 
+            to the standard output stream.
+            </remarks>
+        </member>
+        <member name="M:log4net.Appender.ConsoleAppender.#ctor(log4net.Layout.ILayout)">
+            <summary>
+