diff api/Factories/Xml/WarFoundryXmlFactory.cs @ 48:b49372dd8afa

Re #50 - Complete loading of XML files * Load base points * Check category exists when loaded Re #10 - Refactor source code for readability * Rearrange some methods * Move storing "extra data" in to a method
author IBBoard <dev@ibboard.co.uk>
date Sat, 28 Mar 2009 16:37:27 +0000
parents 85f2b9c3609c
children 9d31d063b194
line wrap: on
line diff
--- a/api/Factories/Xml/WarFoundryXmlFactory.cs	Thu Mar 26 20:49:42 2009 +0000
+++ b/api/Factories/Xml/WarFoundryXmlFactory.cs	Sat Mar 28 16:37:27 2009 +0000
@@ -91,22 +91,23 @@
 			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");
-			}
-			
+			int points = GetIntValueFromAttribute(elem, "maxPoints");			
 			Army army = new Army(race, name, points, file);
-			extraData[army] = elem.OwnerDocument;
+			StoreExtraData(army, elem);
 			return army;
 		}
+		
+		private void StoreExtraData(WarFoundryStagedLoadingObject wfObject, XmlElement elem)
+		{
+			extraData[wfObject] = elem.OwnerDocument;
+		}
+	
+		public XmlDocument GetExtraData(IWarFoundryObject obj)
+		{
+			XmlDocument extra = null;
+			extraData.TryGetValue(obj, out extra);			
+			return extra;
+		}
 
 		protected override Stream GetGameSystemDataStream (ZipFile file)
 		{
@@ -125,7 +126,7 @@
 			string id = elem.GetAttribute("id");
 			string name = elem.GetAttribute("name");
 			GameSystem system = new GameSystem(id, name, this);
-			extraData[system] = elem.OwnerDocument;
+			StoreExtraData(system, elem);
 			return system;
 		}
 		
@@ -148,128 +149,8 @@
 			string systemID = elem.GetAttribute("system");
 			string name = elem.GetAttribute("name");
 			Race race = new Race(id, subid, name, systemID, this);
-			extraData[race] = elem.OwnerDocument;
+			StoreExtraData(race, elem);
 			return race;
-		}
-
-		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)
-			{
-				CompleteLoading((GameSystem)obj);
-			}
-			else if (obj is Race)
-			{
-				CompleteLoading((Race)obj);
-			}
-		}
-	
-		public XmlNode GetExtraData(IWarFoundryObject obj)
-		{
-			XmlDocument extra = null;
-			extraData.TryGetValue(obj, out extra);
-			XmlNode node = null;
-			
-			if (extra !=null)
-			{
-				node = extra.LastChild;
-			}
-			
-			return node;
-		}
-		
-		public void CompleteLoading(GameSystem system)
-		{
-			if (system.IsFullyLoaded)
-			{
-				LogNotifier.DebugFormat(GetType(), "Object of type GameSystem with ID {0} is already fully loaded", system.ID);
-				return;
-			}
-			
-			if (system.IsLoading)
-			{
-				LogNotifier.WarnFormat(GetType(), "Object of type GameSystem with ID {0} is already being loaded", system.ID);
-				return;
-			}
-			
-			system.SetAsLoading();
-			
-			XmlNode elem = GetExtraData(system);
-			LoadCategoriesForSystem(system, elem);
-			XmlNodeList nodeList = SelectNodes(elem, "/system:system/system:sysStatsList");
-			XmlNode statsElem = nodeList.Item(0);
-			string defaultStatsID = ((XmlElement)statsElem).GetAttribute("defaultStats");
-			LoadSystemStatsForSystem(system, elem);
-			system.StandardSystemStatsID = defaultStatsID;
-			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 void LoadCategoriesForSystem(GameSystem system, XmlNode elem)
-		{
-			WarFoundryObject tempObj;
-						
-			foreach (XmlElement cat in SelectNodes(elem, "/system:system/system:categories/cat:cat"))
-			{
-				tempObj = CreateObjectFromElement(cat);
-				
-				if (tempObj is Category)
-				{
-					system.AddCategory((Category)tempObj);
-				}
-				else
-				{
-					LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml);
-				}
-			}
-		}
-		
-		public void CompleteLoading(Race race)
-		{
-			if (race.IsFullyLoaded)
-			{
-				LogNotifier.DebugFormat(GetType(), "Object of type Race with ID {0} is already fully loaded", race.ID);
-				return;
-			}
-			
-			if (race.IsLoading)
-			{
-				LogNotifier.WarnFormat(GetType(), "Object of type Race with ID {0} is already being loaded", race.ID);
-				return;
-			}
-			
-			race.SetAsLoading();
-			
-			XmlNode elem = GetExtraData(race);
-			
-			foreach (XmlElement node in SelectNodes(elem, "/race:race/race:units/race:unit"))
-			{
-				UnitType type = CreateUnitTypeFromElement(node, race, race.GameSystem);
-				race.AddUnitType(type);
-			}
-			
-			foreach (XmlElement node in SelectNodes(elem, "/race:race/race:categories/cat:cat"))
-			{
-				race.AddCategory(CreateCategoryFromElement(node));
-			}
-							
-			foreach (XmlElement node  in SelectNodes(elem, "/race:race/race:equipment/cat:equipmentItem"))
-			{
-				EquipmentItem item = CreateEquipmentItemFromElement(node, race);
-				race.AddEquipmentItem(item);
-			}
-							
-			foreach (XmlElement node  in SelectNodes(elem, "/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);
 		}
 		
 		protected XmlDocument CreateXmlDocumentFromStream(Stream stream)
@@ -290,7 +171,7 @@
 			return doc;
 		}
 		
-				/// <summary>
+		/// <summary>
 		/// Lazy-getter for XML reader settings. May throw a <see cref="InvalidDataException"/> if there is a problem with the translation schema.
 		/// </summary>
 		/// <returns>
@@ -319,6 +200,11 @@
 			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
@@ -359,39 +245,9 @@
 			return element.SelectNodes(xpathQuery, GetNamespaceManager());
 		}
 		
-		private void ValidationEventMethod(object sender, ValidationEventArgs e)
-		{
-			throw new InvalidDataException("Problem validating against schema for WarFoundry data: " + e.Exception.Message, e.Exception);
-		}
-					
-		private WarFoundryObject CreateObjectFromElement(XmlElement elem)
+		private XmlNode SelectSingleNode(XmlNode element, string xpathQuery)
 		{
-			WarFoundryObject obj = null;
-			LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name);
-			
-			if (elem.LocalName.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");
-			Category cat = new Category(id, name);
-			cat.MaximumPercentage = GetIntValueFromAttribute(elem, "maxPercentage");
-			cat.MinimumPercentage = GetIntValueFromAttribute(elem, "minPercentage");
-			cat.MaximumPoints = GetIntValueFromAttribute(elem, "maxPoints");
-			cat.MinimumPoints = GetIntValueFromAttribute(elem, "minPoints");
-			return cat;
+			return element.SelectSingleNode(xpathQuery, GetNamespaceManager());
 		}
 				
 		private int GetIntValueFromAttribute(XmlElement elem, string attributeName)
@@ -429,6 +285,145 @@
 			
 			return doubleVal;
 		}
+
+		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)
+			{
+				CompleteLoading((GameSystem)obj);
+			}
+			else if (obj is Race)
+			{
+				CompleteLoading((Race)obj);
+			}
+			else if (obj is Army)
+			{
+				CompleteLoading((Army) obj);
+			}
+		}
+		
+		public void CompleteLoading(GameSystem system)
+		{
+			if (system.IsFullyLoaded)
+			{
+				LogNotifier.DebugFormat(GetType(), "Object of type GameSystem with ID {0} is already fully loaded", system.ID);
+				return;
+			}
+			
+			if (system.IsLoading)
+			{
+				LogNotifier.WarnFormat(GetType(), "Object of type GameSystem with ID {0} is already being loaded", system.ID);
+				return;
+			}
+			
+			system.SetAsLoading();
+			
+			XmlDocument extraData = GetExtraData(system);
+			LoadCategoriesForSystem(system, extraData);
+			XmlElement statsElem = SelectSingleNode(extraData, "/system:system/system:sysStatsList");
+			string defaultStatsID = statsElem.GetAttribute("defaultStats");
+			LoadSystemStatsForSystem(system, extraData);
+			system.StandardSystemStatsID = defaultStatsID;
+			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 void LoadCategoriesForSystem(GameSystem system, XmlNode elem)
+		{
+			WarFoundryObject tempObj;
+						
+			foreach (XmlElement cat in SelectNodes(elem, "/system:system/system:categories/cat:cat"))
+			{
+				tempObj = CreateObjectFromElement(cat);
+				
+				if (tempObj is Category)
+				{
+					system.AddCategory((Category)tempObj);
+				}
+				else
+				{
+					LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml);
+				}
+			}
+		}
+		
+		public void CompleteLoading(Race race)
+		{
+			if (race.IsFullyLoaded)
+			{
+				LogNotifier.DebugFormat(GetType(), "Object of type Race with ID {0} is already fully loaded", race.ID);
+				return;
+			}
+			
+			if (race.IsLoading)
+			{
+				LogNotifier.WarnFormat(GetType(), "Object of type Race with ID {0} is already being loaded", race.ID);
+				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);
+			}
+							
+			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 WarFoundryObject CreateObjectFromElement(XmlElement elem)
+		{
+			WarFoundryObject obj = null;
+			LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name);
+			
+			if (elem.LocalName.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");
+			Category cat = new Category(id, name);
+			cat.MaximumPercentage = GetIntValueFromAttribute(elem, "maxPercentage");
+			cat.MinimumPercentage = GetIntValueFromAttribute(elem, "minPercentage");
+			cat.MaximumPoints = GetIntValueFromAttribute(elem, "maxPoints");
+			cat.MinimumPoints = GetIntValueFromAttribute(elem, "minPoints");
+			return cat;
+		}
 						
 		private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system)
 		{
@@ -439,14 +434,20 @@
 			type.MinNumber = GetIntValueFromAttribute(elem, "minNum");
 			type.MaxSize = GetIntValueFromAttribute(elem, "maxSize");
 			type.MinSize = GetIntValueFromAttribute(elem, "minSize");
-			//TODO: Add base size
+			type.BaseSize = GetIntValueFromAttribute(elem, "baseSize");
 			type.CostPerTrooper = GetIntValueFromAttribute(elem, "points");
 			type.BaseUnitCost = GetIntValueFromAttribute(elem, "unitPoints");
 			string mainCatID = elem.GetAttribute("cat");
-			type.MainCategory = parentRace.GetCategory(mainCatID);						
-			XmlNodeList nodes = SelectNodes(elem, "/race:race/race:units/race:unit/race:stats");
-			XmlNode node = nodes.Item(0);
-			type.UnitStats = ParseUnitStats((XmlElement)node, system);
+			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 = SelectSingleNodes(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;