diff API/Factories/Xml/WarFoundryXmlFactory.cs @ 337:3c4a6403a88c

* Fix capitalisation so that new files are in the namespace no-open-ticket
author IBBoard <dev@ibboard.co.uk>
date Sun, 03 Apr 2011 18:50:32 +0000
parents
children 1a70ca80ef41
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/API/Factories/Xml/WarFoundryXmlFactory.cs	Sun Apr 03 18:50:32 2011 +0000
@@ -0,0 +1,191 @@
+// This file (WarFoundryXmlFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2007, 2008, 2009 IBBoard.
+//
+// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+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;
+using System.Text.RegularExpressions;
+
+namespace IBBoard.WarFoundry.API.Factories.Xml
+{
+	/// <summary>
+	/// The WarFoundryXmlFactory loads WarFoundry classes from the native "XML in a zip" file format. Files are validated using the schema for the file type, so structurally invalid files should be identified at initial load.
+	/// </summary>
+	public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
+	{
+		private static WarFoundryXmlFactory factory;
+		private WarFoundryXmlGameSystemFactory gameSystemFactory;
+		private WarFoundryXmlRaceFactory raceFactory;
+		private WarFoundryXmlArmyFactory armyFactory;
+
+		public static WarFoundryXmlFactory GetFactory()
+		{
+			if (factory == null)
+			{
+				factory = new WarFoundryXmlFactory();
+			}
+			
+			return factory;
+		}
+		
+		private WarFoundryXmlFactory() : base()
+		{
+			gameSystemFactory = new WarFoundryXmlGameSystemFactory(this);
+			raceFactory = new WarFoundryXmlRaceFactory(this);
+			armyFactory = new WarFoundryXmlArmyFactory();
+		}
+		
+		public WarFoundryXmlGameSystemFactory GetSystemFactory()
+		{
+			return gameSystemFactory;
+		}
+		
+		public WarFoundryXmlRaceFactory GetRaceFactory()
+		{
+			return raceFactory;
+		}
+		
+		public WarFoundryXmlArmyFactory GetArmyFactory()
+		{
+			return armyFactory;
+		}
+		
+		protected override bool CheckCanFindArmyFileContent(ZipFile file)
+		{
+			return FindEntries(file, "*.armyx").Count > 0;
+		}
+		
+		protected override bool CheckCanFindSystemFileContent(ZipFile file)
+		{
+			return FindEntries(file, "*.systemx").Count > 0;
+		}
+		
+		protected override bool CheckCanFindRaceFileContent(ZipFile file)
+		{
+			return FindEntries(file, "*.racex").Count > 0;
+		}
+		
+		protected override ICollection<ZipEntry> GetArmyZipEntries(ZipFile file)
+		{
+			return FindEntries(file, "*.armyx");
+		}
+		
+		private ICollection<ZipEntry> FindEntries(ZipFile file, string wildcardPattern)
+		{
+			Regex re = new Regex("^" + Regex.Escape(wildcardPattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
+			ICollection<ZipEntry> entries = new List<ZipEntry>();
+				
+			foreach (ZipEntry entry in file)
+			{
+				if (re.IsMatch(entry.Name))
+				{
+					entries.Add(entry);
+				}
+			}
+			
+			return entries;
+		}
+		
+		protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
+			return armyFactory.CreateArmyFromElement(file, elem);
+		}
+		
+		private XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
+		{
+			XmlDocument doc = WarFoundryXmlFactoryUtils.CreateXmlDocumentFromStream(stream);
+
+			XmlElement elem = (XmlElement)doc.LastChild;
+			
+			if (!elem.LocalName.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 ICollection<ZipEntry> GetGameSystemZipEntries(ZipFile file)
+		{
+			return FindEntries(file, "*.systemx");
+		}
+		
+		protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
+			LogNotifier.Debug(GetType(), "Create GameSystem");
+			return gameSystemFactory.CreateSystemFromElement(file, elem);
+		}
+		
+		protected override ICollection<ZipEntry> GetRaceZipEntries(ZipFile file)
+		{
+			return FindEntries(file, "*.racex");
+		}
+		
+		protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
+		{
+			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
+			LogNotifier.Debug(GetType(), "Create Race");
+			return raceFactory.CreateRaceFromElement(file, elem);
+		}
+
+		protected override void CleanUpFileAsSupportedType(ZipFile typedFile)
+		{
+			typedFile.Close();
+		}
+
+		public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
+		{			
+			LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID);
+
+			if (obj is GameSystem)
+			{
+				CompleteLoadingGameSystem((GameSystem) obj);
+			}
+			else if (obj is Race)
+			{
+				CompleteLoadingRace((Race) obj);
+			}
+		}
+
+		private void CompleteLoadingRace(Race race)
+		{
+			try
+			{
+				raceFactory.CompleteLoading(race);
+			}
+			catch (InvalidFileException ex)
+			{
+				WarFoundryLoader.GetDefault().RemoveRace(race);
+				throw;
+			}
+		}
+
+		private void CompleteLoadingGameSystem(GameSystem system)
+		{
+			try
+			{
+				gameSystemFactory.CompleteLoading(system);
+			}
+			catch (InvalidFileException ex)
+			{
+				WarFoundryLoader.GetDefault().RemoveGameSystem(system);
+				throw;
+			}
+		}
+	}
+}
\ No newline at end of file