diff api/Factories/Xml/WarFoundryXmlFactory.cs @ 52:64ef178c18aa

Re #10 - Refactor for readability * Break WarFoundryXMLFactory out in to GameSystem, Race and Army factories * Create factory utils classes with methods from WarFoundryXMLFactory for getting node lists etc
author IBBoard <dev@ibboard.co.uk>
date Mon, 30 Mar 2009 19:44:03 +0000
parents b271a2252758
children 3ea0ab04352b
line wrap: on
line diff
--- a/api/Factories/Xml/WarFoundryXmlFactory.cs	Sat Mar 28 21:00:35 2009 +0000
+++ b/api/Factories/Xml/WarFoundryXmlFactory.cs	Mon Mar 30 19:44:03 2009 +0000
@@ -26,9 +26,9 @@
 	public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
 	{
 		private static WarFoundryXmlFactory factory;
-		private XmlReaderSettings settings;
-		private XmlNamespaceManager nsManager;
-		private Dictionary<IWarFoundryObject, XmlDocument> extraData = new Dictionary<IWarFoundryObject, XmlDocument>();
+		private WarFoundryXmlGameSystemFactory gameSystemFactory;
+		private WarFoundryXmlRaceFactory raceFactory;
+		private WarFoundryXmlArmyFactory armyFactory;
 
 		public static AbstractNativeWarFoundryFactory GetFactory()
 		{
@@ -42,7 +42,9 @@
 		
 		private WarFoundryXmlFactory() : base()
 		{
-			//Hide constructor
+			gameSystemFactory = new WarFoundryXmlGameSystemFactory(this);
+			raceFactory = new WarFoundryXmlRaceFactory(this);
+			armyFactory = new WarFoundryXmlArmyFactory();
 		}
 		
 		protected override bool CheckCanFindArmyFileContent(ZipFile file)
@@ -68,12 +70,12 @@
 		protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
 		{
 			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
-			return CreateArmyFromElement(file, elem);
+			return armyFactory.CreateArmyFromElement(file, elem);
 		}
 		
 		private XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
 		{
-			XmlDocument doc = CreateXmlDocumentFromStream(stream);			
+			XmlDocument doc = WarFoundryXmlFactoryUtils.CreateXmlDocumentFromStream(stream);			
 			XmlElement elem = (XmlElement)doc.LastChild;
 			
 			if (!elem.LocalName.Equals(elementName.Value))
@@ -83,91 +85,6 @@
 			
 			return elem;
 		}
-		
-		private XmlDocument CreateXmlDocumentFromStream(Stream stream)
-		{
-			XmlDocument doc = new XmlDocument();
-			XmlReader reader = XmlReader.Create(stream, GetReaderSettings());
-			
-			try
-			{
-				doc.Load(reader);
-			}
-			//Don't catch XMLSchemaExceptions - let them get thrown out
-			finally
-			{
-				reader.Close();
-			}
-
-			return doc;
-		}
-		
-		/// <summary>
-		/// Lazy-getter for XML reader settings. May throw a <see cref="InvalidDataException"/> if there is a problem with the translation schema.
-		/// </summary>
-		/// <returns>
-		/// A <see cref="XmlReaderSettings"/> with the default values for validating the translation document against the translation schema
-		/// </returns>
-		private XmlReaderSettings GetReaderSettings()
-		{
-			if (settings == null)
-			{
-				settings = new XmlReaderSettings();
-				settings.ValidationType = ValidationType.Schema;
-				settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
-				settings.ProhibitDtd = true;
-				settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
-				XmlSchemaSet cache = new XmlSchemaSet();
-				string path =  IBBoard.Constants.ExecutablePath + "/dtds/";
-				string nsBase = "http://ibboard.co.uk/warfoundry/";
-				AddSchemaToCache(cache, nsBase + "core", path + "warfoundry-core.xsd");
-				AddSchemaToCache(cache, nsBase + "cats", path + "warfoundry-cats.xsd");
-				AddSchemaToCache(cache, nsBase + "race", path + "race.xsd");
-				AddSchemaToCache(cache, nsBase + "system", path + "system.xsd");
-				AddSchemaToCache(cache, nsBase + "army", path + "army.xsd");
-				settings.Schemas.Add(cache);
-			}
-			
-			return settings;
-		}
-		
-		private void ValidationEventMethod(object sender, ValidationEventArgs e)
-		{
-			throw new InvalidDataException("Problem validating against schema for WarFoundry data: " + e.Exception.Message, e.Exception);
-		}
-		
-		private void AddSchemaToCache(XmlSchemaSet cache, string xmlNamespace, string schemaLocation)
-		{
-			try
-			{
-				cache.Add(xmlNamespace, schemaLocation);
-			}
-			catch (IOException ex)
-			{
-				LogNotifier.Warn(GetType(), "Problem reading schema: " + ex.Message, ex);
-			}
-			catch (XmlSchemaException ex)
-			{
-				LogNotifier.Warn(GetType(), "Problem validating schema for WarFoundry data: " + ex.Message, ex);
-			}
-			catch (XmlException ex)
-			{
-				LogNotifier.Warn(GetType(), "Problem reading data for schema: " + ex.Message, ex);
-			}
-		}
-		
-		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);
-			int points = XmlTools.GetIntValueFromAttribute(elem, "maxPoints");			
-			Army army = new Army(race, name, points, file);
-			//TODO: Complete loading of army
-			return army;
-		}
 
 		protected override Stream GetGameSystemDataStream (ZipFile file)
 		{
@@ -178,21 +95,7 @@
 		{
 			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 GameSystem(id, name, this);
-			StoreExtraData(system, elem);
-			return system;
-		}
-		
-		private void StoreExtraData(WarFoundryStagedLoadingObject wfObject, XmlElement elem)
-		{
-			extraData[wfObject] = elem.OwnerDocument;
+			return gameSystemFactory.CreateSystemFromElement(file, elem);
 		}
 		
 		protected override Stream GetRaceDataStream (ZipFile file)
@@ -204,56 +107,7 @@
 		{
 			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 Race(id, subid, name, systemID, this);
-			StoreExtraData(race, elem);
-			return race;
-		}
-	
-		public XmlDocument GetExtraData(IWarFoundryObject obj)
-		{
-			XmlDocument extra = null;
-			extraData.TryGetValue(obj, out extra);			
-			return extra;
-		}
-		
-		private XmlNamespaceManager GetNamespaceManager()
-		{
-			if (nsManager == null)
-			{
-				nsManager = new XmlNamespaceManager(new NameTable());
-				nsManager.AddNamespace("core", "http://ibboard.co.uk/warfoundry/core");
-				nsManager.AddNamespace("cat", "http://ibboard.co.uk/warfoundry/cats");
-				nsManager.AddNamespace("race", "http://ibboard.co.uk/warfoundry/race");
-				nsManager.AddNamespace("system", "http://ibboard.co.uk/warfoundry/system");
-				nsManager.AddNamespace("army", "http://ibboard.co.uk/warfoundry/army");
-			}
-			
-			return nsManager;
-		}
-		
-		private XmlNodeList SelectNodes(XmlNode element, string xpathQuery)
-		{
-			return element.SelectNodes(xpathQuery, GetNamespaceManager());
-		}
-		
-		private XmlNode SelectSingleNode(XmlNode element, string xpathQuery)
-		{
-			return element.SelectSingleNode(xpathQuery, GetNamespaceManager());
-		}
-		
-		private XmlElement SelectSingleElement(XmlNode element, string xpathQuery)
-		{
-			XmlNode node = SelectSingleNode(element, xpathQuery);
-			return (node is XmlElement) ? (XmlElement) node : null;
+			return raceFactory.CreateRaceFromElement(file, elem);
 		}
 
 		public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
@@ -262,237 +116,12 @@
 							
 			if (obj is GameSystem)
 			{
-				CompleteLoading((GameSystem)obj);
+				gameSystemFactory.CompleteLoading((GameSystem)obj);
 			}
 			else if (obj is Race)
 			{
-				CompleteLoading((Race)obj);
-			}
-		}
-		
-		public void CompleteLoading(GameSystem system)
-		{
-			if (!CanCompleteLoading(system))
-			{
-				return;
-			}
-			
-			system.SetAsLoading();			
-			XmlDocument extraData = GetExtraData(system);
-			LoadCategoriesForSystem(system, extraData);
-			XmlElement statsElem = SelectSingleElement(extraData, "/system:system/system:sysStatsList");
-			string defaultStatsID = statsElem.GetAttribute("defaultStats");
-			LoadSystemStatsForSystem(system, extraData);
-			system.StandardSystemStatsID = defaultStatsID;
-			XmlElement systemElement = SelectSingleElement(extraData, "/system:system");
-			system.WarnOnError = XmlTools.GetBoolValueFromAttribute(systemElement, "warn");
-			system.AllowAllies = XmlTools.GetBoolValueFromAttribute(systemElement, "allowAllies");
-			LogNotifier.DebugFormat(GetType(), "Completed loading of GameSystem with ID {0}", system.ID);
-			LogNotifier.DebugFormat(GetType(), "GameSystem with ID {0} default stats: {1}", system.ID, system.StandardSystemStatsID);
-			system.SetAsFullyLoaded();
-		}
-		
-		private bool CanCompleteLoading(IWarFoundryStagedLoadObject obj)
-		{
-			bool canLoad = true;			
-			
-			if (obj.IsFullyLoaded)
-			{
-				LogNotifier.DebugFormat(GetType(), "Object of type {0} with ID {1} is already fully loaded", obj.GetType().Name, obj.ID);
-				canLoad = false;
-			}
-			else if (obj.IsLoading)
-			{
-				LogNotifier.WarnFormat(GetType(), "Object of type {0} with ID {1} is already being loaded", obj.GetType().Name, obj.ID);
-				canLoad = false;
-			}
-			
-			return canLoad;
-		}
-		
-		private void LoadCategoriesForSystem(GameSystem system, XmlNode elem)
-		{
-			foreach (XmlElement cat in SelectNodes(elem, "/system:system/system:categories/cat:cat"))
-			{
-				system.AddCategory(CreateCategoryFromElement(cat));
-			}
-		}
-		
-		private Category CreateCategoryFromElement(XmlElement elem)
-		{
-			string id = elem.GetAttribute("id");
-			string name = elem.GetAttribute("name");
-			Category cat = new Category(id, name);
-			cat.MaximumPercentage = XmlTools.GetIntValueFromAttribute(elem, "maxPercentage");
-			cat.MinimumPercentage = XmlTools.GetIntValueFromAttribute(elem, "minPercentage");
-			cat.MaximumPoints = XmlTools.GetIntValueFromAttribute(elem, "maxPoints");
-			cat.MinimumPoints = XmlTools.GetIntValueFromAttribute(elem, "minPoints");
-			return cat;
-		}		
-		
-		private void LoadSystemStatsForSystem(GameSystem system, XmlNode elem)
-		{
-			foreach (XmlElement stats in SelectNodes(elem, "/system:system/system:sysStatsList/system:sysStats"))
-			{
-				SystemStats sysStats = CreateSystemStatsFromElement(stats);
-				system.AddSystemStats(sysStats);
-			}
-		}
-		
-		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());
-		}
-		
-		public void CompleteLoading(Race race)
-		{
-			if (!CanCompleteLoading(race))
-			{
-				return;
-			}
-			
-			race.SetAsLoading();			
-			XmlDocument extraData = GetExtraData(race);
-			
-			foreach (XmlElement node in SelectNodes(extraData, "/race:race/race:units/race:unit"))
-			{
-				UnitType type = CreateUnitTypeFromElement(node, race, race.GameSystem);
-				race.AddUnitType(type);
-			}
-			
-			foreach (XmlElement node in SelectNodes(extraData, "/race:race/race:categories/cat:cat"))
-			{
-				race.AddCategory(CreateCategoryFromElement(node));
-			}
-							
-			foreach (XmlElement node  in SelectNodes(extraData, "/race:race/race:equipment/cat:equipmentItem"))
-			{
-				EquipmentItem item = CreateEquipmentItemFromElement(node, race);
-				race.AddEquipmentItem(item);
+				raceFactory.CompleteLoading((Race)obj);
 			}
-							
-			foreach (XmlElement node  in SelectNodes(extraData, "/race:race/race:abilities/cat:ability"))
-			{
-				Ability ability = CreateAbilityFromElement(node, race);
-				race.AddAbility(ability);
-			}
-			
-			race.SetAsFullyLoaded();
-			LogNotifier.DebugFormat(GetType(), "Completed loading of Race with ID {0}", race.ID);
-		}
-						
-		private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system)
-		{
-			string id = elem.GetAttribute("id");
-			string name = elem.GetAttribute("typeName");
-			UnitType type = new UnitType(id, name, parentRace);
-			type.MaxNumber = XmlTools.GetIntValueFromAttribute(elem, "maxNum");
-			type.MinNumber = XmlTools.GetIntValueFromAttribute(elem, "minNum");
-			type.MaxSize = XmlTools.GetIntValueFromAttribute(elem, "maxSize");
-			type.MinSize = XmlTools.GetIntValueFromAttribute(elem, "minSize");
-			type.BaseSize = XmlTools.GetIntValueFromAttribute(elem, "baseSize");
-			type.CostPerTrooper = XmlTools.GetIntValueFromAttribute(elem, "points");
-			type.BaseUnitCost = XmlTools.GetIntValueFromAttribute(elem, "unitPoints");
-			string mainCatID = elem.GetAttribute("cat");
-			Category cat = parentRace.GetCategory(mainCatID);
-			
-			if (cat == null)
-			{
-				throw new InvalidDataException(String.Format("Attribute 'cat' of UnitType {0} (value: {1}) did not reference a valid category", id, mainCatID));
-			}
-			
-			type.MainCategory = cat;
-			XmlElement statsElement = SelectSingleElement(elem, "/race:race/race:units/race:unit/race:stats");
-			type.UnitStats = ParseUnitStats(statsElement, system);
-			//TODO: Add unit requirements
-			LogNotifier.Debug(GetType(), "Loaded "+type.Name);
-			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.GetSystemStatsForID(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 EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race)
-		{
-			string id = elem.GetAttribute("id");
-			string name = elem.GetAttribute("name");
-			double cost = 0, min = 0, max = 0;
-			ArmourType armourType;
-			
-			try
-			{
-				cost = XmlTools.GetDoubleValueFromAttribute(elem, "cost");
-			}
-			catch(FormatException ex)
-			{
-				throw new InvalidFileException("Attribute 'cost' of equipment item "+id+" was not a valid number", ex);
-			}			
-			
-			try
-			{
-				armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType"));
-			}
-			catch(ArgumentException ex)
-			{
-				throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration", ex);
-			}
-			
-			//TODO: Parse equipment stats if there are any
-			
-			return new EquipmentItem(id, name, cost, min, max, armourType, race);
-		}
-		
-		private Ability CreateAbilityFromElement(XmlElement elem, Race race)
-		{
-			string id = elem.GetAttribute("id");
-			string name = elem.GetAttribute("name");
-			Ability ability = new Ability(id, name);
-			XmlNode node = elem.SelectSingleNode("description", GetNamespaceManager());
-			ability.Description = (node == null) ? "" : node.InnerText;
-			return ability;
 		}
 	}
 }
\ No newline at end of file