comparison api/Factories/Xml/WarFoundryXmlFactory.cs @ 50:bb6b993b98bf

Re #10 - Refactor for readability * Re-order methods so that they are in the correct order to read the code from top to bottom * Reduce visibility of methods where possible * Make use of XMLTools class * Refactor "can complete loading" checks in to single method
author IBBoard <dev@ibboard.co.uk>
date Sat, 28 Mar 2009 20:51:06 +0000
parents 9d31d063b194
children b271a2252758
comparison
equal deleted inserted replaced
49:9d31d063b194 50:bb6b993b98bf
38 } 38 }
39 39
40 return factory; 40 return factory;
41 } 41 }
42 42
43 protected WarFoundryXmlFactory() : base() 43 private WarFoundryXmlFactory() : base()
44 { 44 {
45 //Hide constructor 45 //Hide constructor
46 } 46 }
47 47
48 protected override bool CheckCanFindArmyFileContent(ZipFile file) 48 protected override bool CheckCanFindArmyFileContent(ZipFile file)
58 protected override bool CheckCanFindRaceFileContent(ZipFile file) 58 protected override bool CheckCanFindRaceFileContent(ZipFile file)
59 { 59 {
60 return file.FindEntry("data.racex", true) > -1; 60 return file.FindEntry("data.racex", true) > -1;
61 } 61 }
62 62
63 protected XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName) 63 protected override Stream GetArmyDataStream(ZipFile file)
64 {
65 return file.GetInputStream(file.FindEntry("data.armyx", true));
66 }
67
68 protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
69 {
70 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
71 return CreateArmyFromElement(file, elem);
72 }
73
74 private XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
64 { 75 {
65 XmlDocument doc = CreateXmlDocumentFromStream(stream); 76 XmlDocument doc = CreateXmlDocumentFromStream(stream);
66 XmlElement elem = (XmlElement)doc.LastChild; 77 XmlElement elem = (XmlElement)doc.LastChild;
67 78
68 if (!elem.LocalName.Equals(elementName.Value)) 79 if (!elem.LocalName.Equals(elementName.Value))
71 } 82 }
72 83
73 return elem; 84 return elem;
74 } 85 }
75 86
76 protected override Stream GetArmyDataStream(ZipFile file) 87 private XmlDocument CreateXmlDocumentFromStream(Stream stream)
77 {
78 return file.GetInputStream(file.FindEntry("data.armyx", true));
79 }
80
81 protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
82 {
83 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
84 return CreateArmyFromElement(file, elem);
85 }
86
87 private Army CreateArmyFromElement(ZipFile file, XmlElement elem)
88 {
89 string name = elem.GetAttribute("name");
90 string systemID = elem.GetAttribute("gameSystem");
91 GameSystem system = WarFoundryLoader.GetDefault().GetGameSystem(systemID);
92 string raceID = elem.GetAttribute("race");
93 Race race = WarFoundryLoader.GetDefault().GetRace(system, raceID);
94 int points = GetIntValueFromAttribute(elem, "maxPoints");
95 Army army = new Army(race, name, points, file);
96 //TODO: Complete loading of army
97 return army;
98 }
99
100 private void StoreExtraData(WarFoundryStagedLoadingObject wfObject, XmlElement elem)
101 {
102 extraData[wfObject] = elem.OwnerDocument;
103 }
104
105 public XmlDocument GetExtraData(IWarFoundryObject obj)
106 {
107 XmlDocument extra = null;
108 extraData.TryGetValue(obj, out extra);
109 return extra;
110 }
111
112 protected override Stream GetGameSystemDataStream (ZipFile file)
113 {
114 return file.GetInputStream(file.FindEntry("data.systemx", true));
115 }
116
117 protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
118 {
119 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
120 LogNotifier.Debug(GetType(), "Create GameSystem");
121 return CreateSystemFromElement(file, elem);
122 }
123
124 private GameSystem CreateSystemFromElement(ZipFile file, XmlElement elem)
125 {
126 string id = elem.GetAttribute("id");
127 string name = elem.GetAttribute("name");
128 GameSystem system = new GameSystem(id, name, this);
129 StoreExtraData(system, elem);
130 return system;
131 }
132
133 protected override Stream GetRaceDataStream (ZipFile file)
134 {
135 return file.GetInputStream(file.FindEntry("data.racex", true));
136 }
137
138 protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
139 {
140 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
141 LogNotifier.Debug(GetType(), "Create Race");
142 return CreateRaceFromElement(file, elem);
143 }
144
145 private Race CreateRaceFromElement(ZipFile file, XmlElement elem)
146 {
147 string id = elem.GetAttribute("id");
148 string subid = elem.GetAttribute("subid");
149 string systemID = elem.GetAttribute("system");
150 string name = elem.GetAttribute("name");
151 Race race = new Race(id, subid, name, systemID, this);
152 StoreExtraData(race, elem);
153 return race;
154 }
155
156 protected XmlDocument CreateXmlDocumentFromStream(Stream stream)
157 { 88 {
158 XmlDocument doc = new XmlDocument(); 89 XmlDocument doc = new XmlDocument();
159 XmlReader reader = XmlReader.Create(stream, GetReaderSettings()); 90 XmlReader reader = XmlReader.Create(stream, GetReaderSettings());
160 91
161 try 92 try
223 { 154 {
224 LogNotifier.Warn(GetType(), "Problem reading data for schema: " + ex.Message, ex); 155 LogNotifier.Warn(GetType(), "Problem reading data for schema: " + ex.Message, ex);
225 } 156 }
226 } 157 }
227 158
159 private Army CreateArmyFromElement(ZipFile file, XmlElement elem)
160 {
161 string name = elem.GetAttribute("name");
162 string systemID = elem.GetAttribute("gameSystem");
163 GameSystem system = WarFoundryLoader.GetDefault().GetGameSystem(systemID);
164 string raceID = elem.GetAttribute("race");
165 Race race = WarFoundryLoader.GetDefault().GetRace(system, raceID);
166 int points = XmlTools.GetIntValueFromAttribute(elem, "maxPoints");
167 Army army = new Army(race, name, points, file);
168 //TODO: Complete loading of army
169 return army;
170 }
171
172 protected override Stream GetGameSystemDataStream (ZipFile file)
173 {
174 return file.GetInputStream(file.FindEntry("data.systemx", true));
175 }
176
177 protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
178 {
179 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
180 LogNotifier.Debug(GetType(), "Create GameSystem");
181 return CreateSystemFromElement(file, elem);
182 }
183
184 private GameSystem CreateSystemFromElement(ZipFile file, XmlElement elem)
185 {
186 string id = elem.GetAttribute("id");
187 string name = elem.GetAttribute("name");
188 GameSystem system = new GameSystem(id, name, this);
189 StoreExtraData(system, elem);
190 return system;
191 }
192
193 private void StoreExtraData(WarFoundryStagedLoadingObject wfObject, XmlElement elem)
194 {
195 extraData[wfObject] = elem.OwnerDocument;
196 }
197
198 protected override Stream GetRaceDataStream (ZipFile file)
199 {
200 return file.GetInputStream(file.FindEntry("data.racex", true));
201 }
202
203 protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
204 {
205 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
206 LogNotifier.Debug(GetType(), "Create Race");
207 return CreateRaceFromElement(file, elem);
208 }
209
210 private Race CreateRaceFromElement(ZipFile file, XmlElement elem)
211 {
212 string id = elem.GetAttribute("id");
213 string subid = elem.GetAttribute("subid");
214 string systemID = elem.GetAttribute("system");
215 string name = elem.GetAttribute("name");
216 Race race = new Race(id, subid, name, systemID, this);
217 StoreExtraData(race, elem);
218 return race;
219 }
220
221 public XmlDocument GetExtraData(IWarFoundryObject obj)
222 {
223 XmlDocument extra = null;
224 extraData.TryGetValue(obj, out extra);
225 return extra;
226 }
227
228 private XmlNamespaceManager GetNamespaceManager() 228 private XmlNamespaceManager GetNamespaceManager()
229 { 229 {
230 if (nsManager == null) 230 if (nsManager == null)
231 { 231 {
232 nsManager = new XmlNamespaceManager(new NameTable()); 232 nsManager = new XmlNamespaceManager(new NameTable());
253 private XmlElement SelectSingleElement(XmlNode element, string xpathQuery) 253 private XmlElement SelectSingleElement(XmlNode element, string xpathQuery)
254 { 254 {
255 XmlNode node = SelectSingleNode(element, xpathQuery); 255 XmlNode node = SelectSingleNode(element, xpathQuery);
256 return (node is XmlElement) ? (XmlElement) node : null; 256 return (node is XmlElement) ? (XmlElement) node : null;
257 } 257 }
258
259 private int GetIntValueFromAttribute(XmlElement elem, string attributeName)
260 {
261 try
262 {
263 return int.Parse(elem.GetAttribute(attributeName));
264 }
265 catch(FormatException)
266 {
267 throw new FormatException(String.Format("Attribute '{0}' of {1} with ID {2} was not a valid number", attributeName, elem.Name, elem.GetAttribute("id")));
268 }
269 }
270
271 private double GetDoubleValueFromAttribute(XmlElement elem, string attributeName)
272 {
273 double doubleVal = double.NaN;
274 string attribValue = elem.GetAttribute(attributeName);
275
276 if (attribValue == "INF")
277 {
278 doubleVal = double.PositiveInfinity;
279 }
280 else
281 {
282 try
283 {
284 return int.Parse(attribValue);
285 }
286 catch(FormatException)
287 {
288 throw new FormatException(String.Format("Attribute '{0}' of {1} with ID {2} was not a valid number", attributeName, elem.Name, elem.GetAttribute("id")));
289 }
290 }
291
292 return doubleVal;
293 }
294 258
295 public override void CompleteLoading(IWarFoundryStagedLoadObject obj) 259 public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
296 { 260 {
297 LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID); 261 LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID);
298 262
306 } 270 }
307 } 271 }
308 272
309 public void CompleteLoading(GameSystem system) 273 public void CompleteLoading(GameSystem system)
310 { 274 {
311 if (system.IsFullyLoaded) 275 if (!CanCompleteLoading(system))
312 { 276 {
313 LogNotifier.DebugFormat(GetType(), "Object of type GameSystem with ID {0} is already fully loaded", system.ID);
314 return; 277 return;
315 } 278 }
316 279
317 if (system.IsLoading) 280 system.SetAsLoading();
318 {
319 LogNotifier.WarnFormat(GetType(), "Object of type GameSystem with ID {0} is already being loaded", system.ID);
320 return;
321 }
322
323 system.SetAsLoading();
324
325 XmlDocument extraData = GetExtraData(system); 281 XmlDocument extraData = GetExtraData(system);
326 LoadCategoriesForSystem(system, extraData); 282 LoadCategoriesForSystem(system, extraData);
327 XmlElement statsElem = SelectSingleElement(extraData, "/system:system/system:sysStatsList"); 283 XmlElement statsElem = SelectSingleElement(extraData, "/system:system/system:sysStatsList");
328 string defaultStatsID = statsElem.GetAttribute("defaultStats"); 284 string defaultStatsID = statsElem.GetAttribute("defaultStats");
329 LoadSystemStatsForSystem(system, extraData); 285 LoadSystemStatsForSystem(system, extraData);
331 LogNotifier.DebugFormat(GetType(), "Completed loading of GameSystem with ID {0}", system.ID); 287 LogNotifier.DebugFormat(GetType(), "Completed loading of GameSystem with ID {0}", system.ID);
332 LogNotifier.DebugFormat(GetType(), "GameSystem with ID {0} default stats: {1}", system.ID, system.StandardSystemStatsID); 288 LogNotifier.DebugFormat(GetType(), "GameSystem with ID {0} default stats: {1}", system.ID, system.StandardSystemStatsID);
333 system.SetAsFullyLoaded(); 289 system.SetAsFullyLoaded();
334 } 290 }
335 291
292 private bool CanCompleteLoading(IWarFoundryStagedLoadObject obj)
293 {
294 bool canLoad = true;
295
296 if (obj.IsFullyLoaded)
297 {
298 LogNotifier.DebugFormat(GetType(), "Object of type {0} with ID {1} is already fully loaded", obj.GetType().Name, obj.ID);
299 canLoad = false;
300 }
301 else if (obj.IsLoading)
302 {
303 LogNotifier.WarnFormat(GetType(), "Object of type {0} with ID {1} is already being loaded", obj.GetType().Name, obj.ID);
304 canLoad = false;
305 }
306
307 return canLoad;
308 }
309
336 private void LoadCategoriesForSystem(GameSystem system, XmlNode elem) 310 private void LoadCategoriesForSystem(GameSystem system, XmlNode elem)
337 { 311 {
338 WarFoundryObject tempObj; 312 WarFoundryObject tempObj;
339 313
340 foreach (XmlElement cat in SelectNodes(elem, "/system:system/system:categories/cat:cat")) 314 foreach (XmlElement cat in SelectNodes(elem, "/system:system/system:categories/cat:cat"))
341 { 315 {
342 tempObj = CreateObjectFromElement(cat); 316 system.AddCategory(CreateCategoryFromElement(cat));
343 317 }
344 if (tempObj is Category) 318 }
345 { 319
346 system.AddCategory((Category)tempObj); 320 private Category CreateCategoryFromElement(XmlElement elem)
347 } 321 {
348 else 322 string id = elem.GetAttribute("id");
349 { 323 string name = elem.GetAttribute("name");
350 LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml); 324 Category cat = new Category(id, name);
351 } 325 cat.MaximumPercentage = XmlTools.GetIntValueFromAttribute(elem, "maxPercentage");
352 } 326 cat.MinimumPercentage = XmlTools.GetIntValueFromAttribute(elem, "minPercentage");
327 cat.MaximumPoints = XmlTools.GetIntValueFromAttribute(elem, "maxPoints");
328 cat.MinimumPoints = XmlTools.GetIntValueFromAttribute(elem, "minPoints");
329 return cat;
330 }
331
332 private void LoadSystemStatsForSystem(GameSystem system, XmlNode elem)
333 {
334 foreach (XmlElement stats in SelectNodes(elem, "/system:system/system:sysStatsList/system:sysStats"))
335 {
336 SystemStats sysStats = CreateSystemStatsFromElement(stats);
337 system.AddSystemStats(sysStats);
338 }
339 }
340
341 private SystemStats CreateSystemStatsFromElement(XmlElement elem)
342 {
343 List<StatSlot> slots = new List<StatSlot>();
344 string id = elem.GetAttribute("id");
345
346 foreach (XmlElement slot in elem.ChildNodes)
347 {
348 StatSlot statSlot = new StatSlot(slot.GetAttribute("name"));
349 slots.Add(statSlot);
350 }
351
352 return new SystemStats(id, slots.ToArray());
353 } 353 }
354 354
355 public void CompleteLoading(Race race) 355 public void CompleteLoading(Race race)
356 { 356 {
357 if (race.IsFullyLoaded) 357 if (!CanCompleteLoading(system))
358 { 358 {
359 LogNotifier.DebugFormat(GetType(), "Object of type Race with ID {0} is already fully loaded", race.ID);
360 return;
361 }
362
363 if (race.IsLoading)
364 {
365 LogNotifier.WarnFormat(GetType(), "Object of type Race with ID {0} is already being loaded", race.ID);
366 return; 359 return;
367 } 360 }
368 361
369 race.SetAsLoading(); 362 race.SetAsLoading();
370 363
394 } 387 }
395 388
396 race.SetAsFullyLoaded(); 389 race.SetAsFullyLoaded();
397 LogNotifier.DebugFormat(GetType(), "Completed loading of Race with ID {0}", race.ID); 390 LogNotifier.DebugFormat(GetType(), "Completed loading of Race with ID {0}", race.ID);
398 } 391 }
399
400 private WarFoundryObject CreateObjectFromElement(XmlElement elem)
401 {
402 WarFoundryObject obj = null;
403 LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name);
404
405 if (elem.LocalName.Equals(WarFoundryXmlElementName.CATEGORY_ELEMENT.Value))
406 {
407 LogNotifier.Debug(GetType(), "Create Category");
408 obj = CreateCategoryFromElement(elem);
409 }
410 else
411 {
412 LogNotifier.Debug(GetType(), "No match");
413 }
414
415 return obj;
416 }
417
418 private Category CreateCategoryFromElement(XmlElement elem)
419 {
420 string id = elem.GetAttribute("id");
421 string name = elem.GetAttribute("name");
422 Category cat = new Category(id, name);
423 cat.MaximumPercentage = GetIntValueFromAttribute(elem, "maxPercentage");
424 cat.MinimumPercentage = GetIntValueFromAttribute(elem, "minPercentage");
425 cat.MaximumPoints = GetIntValueFromAttribute(elem, "maxPoints");
426 cat.MinimumPoints = GetIntValueFromAttribute(elem, "minPoints");
427 return cat;
428 }
429 392
430 private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system) 393 private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system)
431 { 394 {
432 string id = elem.GetAttribute("id"); 395 string id = elem.GetAttribute("id");
433 string name = elem.GetAttribute("typeName"); 396 string name = elem.GetAttribute("typeName");
434 UnitType type = new UnitType(id, name, parentRace); 397 UnitType type = new UnitType(id, name, parentRace);
435 type.MaxNumber = GetIntValueFromAttribute(elem, "maxNum"); 398 type.MaxNumber = XmlTools.GetIntValueFromAttribute(elem, "maxNum");
436 type.MinNumber = GetIntValueFromAttribute(elem, "minNum"); 399 type.MinNumber = XmlTools.GetIntValueFromAttribute(elem, "minNum");
437 type.MaxSize = GetIntValueFromAttribute(elem, "maxSize"); 400 type.MaxSize = XmlTools.GetIntValueFromAttribute(elem, "maxSize");
438 type.MinSize = GetIntValueFromAttribute(elem, "minSize"); 401 type.MinSize = XmlTools.GetIntValueFromAttribute(elem, "minSize");
439 type.BaseSize = GetIntValueFromAttribute(elem, "baseSize"); 402 type.BaseSize = XmlTools.GetIntValueFromAttribute(elem, "baseSize");
440 type.CostPerTrooper = GetIntValueFromAttribute(elem, "points"); 403 type.CostPerTrooper = XmlTools.GetIntValueFromAttribute(elem, "points");
441 type.BaseUnitCost = GetIntValueFromAttribute(elem, "unitPoints"); 404 type.BaseUnitCost = XmlTools.GetIntValueFromAttribute(elem, "unitPoints");
442 string mainCatID = elem.GetAttribute("cat"); 405 string mainCatID = elem.GetAttribute("cat");
443 Category cat = parentRace.GetCategory(mainCatID); 406 Category cat = parentRace.GetCategory(mainCatID);
444 407
445 if (cat == null) 408 if (cat == null)
446 { 409 {
490 stats.SetStats(statsList); 453 stats.SetStats(statsList);
491 454
492 return stats; 455 return stats;
493 } 456 }
494 457
495 private void LoadSystemStatsForSystem(GameSystem system, XmlNode elem)
496 {
497 foreach (XmlElement stats in SelectNodes(elem, "/system:system/system:sysStatsList/system:sysStats"))
498 {
499 SystemStats sysStats = CreateSystemStatsFromElement(stats);
500 system.AddSystemStats(sysStats);
501 }
502 }
503
504 private SystemStats CreateSystemStatsFromElement(XmlElement elem)
505 {
506 List<StatSlot> slots = new List<StatSlot>();
507 string id = elem.GetAttribute("id");
508
509 foreach (XmlElement slot in elem.ChildNodes)
510 {
511 StatSlot statSlot = new StatSlot(slot.GetAttribute("name"));
512 slots.Add(statSlot);
513 }
514
515 return new SystemStats(id, slots.ToArray());
516 }
517
518 private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race) 458 private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race)
519 { 459 {
520 string id = elem.GetAttribute("id"); 460 string id = elem.GetAttribute("id");
521 string name = elem.GetAttribute("name"); 461 string name = elem.GetAttribute("name");
522 double cost = 0, min = 0, max = 0; 462 double cost = 0, min = 0, max = 0;
523 ArmourType armourType; 463 ArmourType armourType;
524 464
525 try 465 try
526 { 466 {
527 cost = GetDoubleValueFromAttribute(elem, "cost"); 467 cost = XmlTools.GetDoubleValueFromAttribute(elem, "cost");
528 } 468 }
529 catch(FormatException ex) 469 catch(FormatException ex)
530 { 470 {
531 throw new InvalidFileException("Attribute 'cost' of equipment item "+id+" was not a valid number", ex); 471 throw new InvalidFileException("Attribute 'cost' of equipment item "+id+" was not a valid number", ex);
532 } 472 }
535 { 475 {
536 armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType")); 476 armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType"));
537 } 477 }
538 catch(ArgumentException ex) 478 catch(ArgumentException ex)
539 { 479 {
540 throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration"); 480 throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration", ex);
541 } 481 }
542 482
543 //TODO: Parse equipment stats if there are any 483 //TODO: Parse equipment stats if there are any
544 484
545 return new EquipmentItem(id, name, cost, min, max, armourType, race); 485 return new EquipmentItem(id, name, cost, min, max, armourType, race);