Mercurial > repos > IBDev-IBBoard.WarFoundry.API
annotate api/Factories/Xml/WarFoundryXmlFactory.cs @ 17:a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
no-open-ticket
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Mon, 26 Jan 2009 20:29:37 +0000 |
parents | 306558904c2a |
children | f9846f896df3 |
rev | line source |
---|---|
15 | 1 // This file (WarFoundryXmlFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard. |
0 | 2 // |
15 | 3 // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license. |
0 | 4 |
5 using System; | |
6 using System.IO; | |
7 using System.Xml; | |
8 using System.Xml.Schema; | |
9 using System.Collections.Generic; | |
10 using System.Text; | |
11 using IBBoard; | |
12 using IBBoard.IO; | |
13 using IBBoard.Lang; | |
14 using IBBoard.Logging; | |
15 using IBBoard.Xml; | |
16 using IBBoard.WarFoundry.API.Requirements; | |
17 using IBBoard.WarFoundry.API.Objects; | |
18 using ICSharpCode.SharpZipLib.Zip; | |
19 | |
20 namespace IBBoard.WarFoundry.API.Factories.Xml | |
21 { | |
22 /// <summary> | |
10 | 23 /// 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. |
0 | 24 /// </summary> |
25 public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory | |
26 { | |
17
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
27 private static WarFoundryXmlFactory factory; |
0 | 28 private Dictionary<IWarFoundryObject, XmlDocument> extraData = new Dictionary<IWarFoundryObject, XmlDocument>(); |
29 private XmlResolver xmlResolver; | |
30 | |
17
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
31 public static AbstractNativeWarFoundryFactory GetFactory() |
0 | 32 { |
17
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
33 if (factory == null) |
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
34 { |
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
35 factory = new WarFoundryXmlFactory(); |
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
36 } |
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
37 |
a99d3b8466ba
Change "CreateFactory" method to "GetFactory" method to allow for caching
IBBoard <dev@ibboard.co.uk>
parents:
15
diff
changeset
|
38 return factory; |
0 | 39 } |
40 | |
41 protected WarFoundryXmlFactory() : base() | |
42 { | |
43 xmlResolver = new IBBXmlResolver(Constants.ExecutablePath); | |
44 } | |
45 | |
46 protected override bool CheckCanFindArmyFileContent(ZipFile file) | |
47 { | |
48 return file.FindEntry("data.armyx", true) > -1; | |
49 } | |
50 | |
51 protected override bool CheckCanFindSystemFileContent(ZipFile file) | |
52 { | |
53 return file.FindEntry("data.systemx", true) > -1; | |
54 } | |
55 | |
56 protected override bool CheckCanFindRaceFileContent(ZipFile file) | |
57 { | |
58 return file.FindEntry("data.racex", true) > -1; | |
59 } | |
60 | |
61 protected XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName) | |
62 { | |
63 XmlDocument doc = CreateXmlDocumentFromStream(stream); | |
64 XmlElement elem = (XmlElement)doc.LastChild; | |
65 | |
66 if (!elem.Name.Equals(elementName.Value)) | |
67 { | |
68 throw new InvalidFileException(String.Format("Root element of XML was not valid. Expected {0} but got {1}", elementName.Value, elem.Name)); | |
69 } | |
70 | |
71 return elem; | |
72 } | |
73 | |
74 protected override Stream GetArmyDataStream(ZipFile file) | |
75 { | |
76 return file.GetInputStream(file.FindEntry("data.armyx", true)); | |
77 } | |
78 | |
79 protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream) | |
80 { | |
81 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT); | |
82 return CreateArmyFromElement(file, elem); | |
83 } | |
84 | |
85 private Army CreateArmyFromElement(ZipFile file, XmlElement elem) | |
86 { | |
87 string name = elem.GetAttribute("name"); | |
88 string systemID = elem.GetAttribute("gameSystem"); | |
89 GameSystem system = WarFoundryLoader.GetDefault().GetGameSystem(systemID); | |
90 string raceID = elem.GetAttribute("race"); | |
91 Race race = WarFoundryLoader.GetDefault().GetRace(system, raceID); | |
92 string pointsString = elem.GetAttribute("maxPoints"); | |
93 int points = 0; | |
94 | |
95 try | |
96 { | |
97 points = int.Parse(pointsString); | |
98 } | |
99 catch(FormatException) | |
100 { | |
101 throw new FormatException("Attribute 'maxPoints' of army '"+name+"' was not a valid number"); | |
102 } | |
103 | |
10 | 104 Army army = new Army(race, name, points, file); |
0 | 105 extraData[army] = elem.OwnerDocument; |
106 return army; | |
107 } | |
108 | |
109 protected override Stream GetGameSystemDataStream (ZipFile file) | |
110 { | |
111 return file.GetInputStream(file.FindEntry("data.systemx", true)); | |
112 } | |
113 | |
114 protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream) | |
115 { | |
116 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT); | |
117 LogNotifier.Debug(GetType(), "Create GameSystem"); | |
118 return CreateSystemFromElement(file, elem); | |
119 } | |
120 | |
121 private GameSystem CreateSystemFromElement(ZipFile file, XmlElement elem) | |
122 { | |
123 string id = elem.GetAttribute("id"); | |
124 string name = elem.GetAttribute("name"); | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
125 GameSystem system = new GameSystem(id, name, this); |
0 | 126 extraData[system] = elem.OwnerDocument; |
127 return system; | |
128 } | |
129 | |
130 protected override Stream GetRaceDataStream (ZipFile file) | |
131 { | |
132 return file.GetInputStream(file.FindEntry("data.racex", true)); | |
133 } | |
134 | |
135 protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream) | |
136 { | |
137 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT); | |
138 LogNotifier.Debug(GetType(), "Create Race"); | |
139 return CreateRaceFromElement(file, elem); | |
140 } | |
141 | |
142 private Race CreateRaceFromElement(ZipFile file, XmlElement elem) | |
143 { | |
144 string id = elem.GetAttribute("id"); | |
145 string subid = elem.GetAttribute("subid"); | |
146 string systemID = elem.GetAttribute("system"); | |
147 string name = elem.GetAttribute("name"); | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
148 Race race = new Race(id, subid, name, systemID, this); |
0 | 149 extraData[race] = elem.OwnerDocument; |
150 return race; | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
151 } |
0 | 152 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
153 public override void CompleteLoading(IWarFoundryStagedLoadObject obj) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
154 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
155 LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
156 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
157 if (obj is GameSystem) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
158 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
159 CompleteLoading((GameSystem)obj); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
160 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
161 else if (obj is Race) |
0 | 162 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
163 CompleteLoading((Race)obj); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
164 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
165 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
166 |
10 | 167 public XmlNode GetExtraData(IWarFoundryObject obj) |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
168 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
169 XmlDocument extra = null; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
170 extraData.TryGetValue(obj, out extra); |
10 | 171 XmlNode node = null; |
172 | |
173 if (extra !=null) | |
174 { | |
175 node = extra.LastChild; | |
176 } | |
177 | |
178 return node; | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
179 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
180 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
181 public void CompleteLoading(GameSystem system) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
182 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
183 if (system.IsFullyLoaded) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
184 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
185 LogNotifier.DebugFormat(GetType(), "Object of type GameSystem with ID {0} is already fully loaded", system.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
186 return; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
187 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
188 |
10 | 189 XmlNode elem = GetExtraData(system); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
190 XmlNode catsElem = elem.FirstChild; |
10 | 191 LoadCategoriesForSystem(system, elem); |
192 | |
193 XmlElement statsElem = (XmlElement)catsElem.NextSibling; | |
194 LoadSystemStatsFromElement(statsElem, system); | |
195 string defaultStatsID = statsElem.GetAttribute("defaultStats"); | |
196 | |
197 LogNotifier.DebugFormat(GetType(), "Completed loading of GameSystem with ID {0}", system.Name); | |
198 system.StandardSystemStatsID = defaultStatsID; | |
199 system.SetAsFullyLoaded(); | |
200 } | |
201 | |
202 private void LoadCategoriesForSystem(GameSystem system, XmlNode elem) | |
203 { | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
204 WarFoundryObject tempObj; |
10 | 205 |
206 foreach (XmlElement cat in elem.SelectNodes("//"+WarFoundryXmlElementName.CATEGORY_ELEMENT.Value)) | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
207 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
208 tempObj = CreateObjectFromElement(cat); |
0 | 209 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
210 if (tempObj is Category) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
211 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
212 system.AddCategory((Category)tempObj); |
0 | 213 } |
214 else | |
215 { | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
216 LogNotifier.WarnFormat(GetType(), "Object for string {0} was not of type Category", cat.OuterXml); |
0 | 217 } |
218 } | |
219 } | |
220 | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
221 public void CompleteLoading(Race race) |
0 | 222 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
223 if (race.IsFullyLoaded) |
0 | 224 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
225 LogNotifier.DebugFormat(GetType(), "Object of type Race with ID {0} is already fully loaded", race.ID); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
226 return; |
0 | 227 } |
228 | |
10 | 229 XmlNode elem = GetExtraData(race); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
230 XmlNode colNode = elem.FirstChild; |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
231 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
232 foreach (XmlElement node in colNode.ChildNodes) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
233 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
234 UnitType type = CreateUnitTypeFromElement(node, race, race.GameSystem); |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
235 race.AddUnitType(type); |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
236 } |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
237 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
238 colNode = colNode.NextSibling; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
239 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
240 if (colNode!=null && colNode.Name == WarFoundryXmlElementName.CATEGORIES_ELEMENT.Value) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
241 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
242 foreach (XmlElement node in colNode.ChildNodes) |
0 | 243 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
244 race.AddCategory(CreateCategoryFromElement(node)); |
0 | 245 } |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
246 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
247 colNode = colNode.NextSibling; |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
248 } |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
249 |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
250 if (colNode!=null && colNode.Name == WarFoundryXmlElementName.RACE_EQUIPMENT_ITEMS_ELEMENT.Value) |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
251 { |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
252 foreach (XmlElement node in colNode.ChildNodes) |
0 | 253 { |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
254 EquipmentItem item = CreateEquipmentItemFromElement(node, race); |
11
5a1df00b0359
Re #9 - Make WarFoundry API load files in small methods
IBBoard <dev@ibboard.co.uk>
parents:
10
diff
changeset
|
255 race.AddEquipmentItem(item); |
0 | 256 } |
257 } | |
8
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
258 |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
259 Dictionary<string, Ability> raceAbilities = new Dictionary<string, Ability>(); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
260 //TODO: Load abilities |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
261 race.SetAbilities(raceAbilities); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
262 race.SetAsFullyLoaded(); |
613bc5eaac59
Re #9 - Make WarFoundry loading granular
IBBoard <dev@ibboard.co.uk>
parents:
6
diff
changeset
|
263 LogNotifier.DebugFormat(GetType(), "Completed loading of Race with ID {0}", race.Name); |
0 | 264 } |
265 | |
266 protected XmlDocument CreateXmlDocumentFromStream(Stream stream) | |
267 { | |
268 XmlDocument doc = new XmlDocument(); | |
269 XmlReaderSettings settings = new XmlReaderSettings(); | |
270 settings.XmlResolver = xmlResolver; | |
271 settings.ValidationType = ValidationType.DTD; | |
272 settings.ProhibitDtd = false; | |
273 settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod); | |
274 XmlReader reader = XmlReader.Create(stream, settings); | |
275 | |
276 try | |
277 { | |
278 doc.Load(reader); | |
279 } | |
280 //Don't catch XMLSchemaExceptions - let them get thrown out | |
281 finally | |
282 { | |
283 reader.Close(); | |
284 } | |
285 | |
286 if (doc.ChildNodes.Count!=3) | |
287 { | |
288 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.")); | |
289 } | |
290 | |
291 return doc; | |
292 } | |
293 | |
294 protected XmlDocument CreateXmlDocumentFromString(string xmlString) | |
295 { | |
296 XmlReaderSettings settings = new XmlReaderSettings(); | |
297 settings.XmlResolver = xmlResolver; | |
298 settings.ValidationType = ValidationType.DTD; | |
299 settings.ProhibitDtd = false; | |
300 settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod); | |
301 XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xmlString)), settings); | |
302 XmlDocument doc = new XmlDocument(); | |
303 | |
304 try | |
305 { | |
306 doc.Load(reader); | |
307 } | |
308 catch(XmlSchemaException ex) | |
309 { | |
310 throw new InvalidFileException(Translation.GetTranslation("ErrorInvalidXmlString", "Failed to parse invalid XML string"), ex); | |
311 } | |
312 finally | |
313 { | |
314 //We might not need to make sure the memory stream is closed, but do it just in case | |
315 reader.Close(); | |
316 } | |
317 | |
318 if (doc.ChildNodes.Count!=3) | |
319 { | |
320 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."))); | |
321 } | |
322 | |
323 return doc; | |
324 } | |
325 | |
326 private WarFoundryObject CreateObjectFromElement(XmlElement elem) | |
327 { | |
328 WarFoundryObject obj = null; | |
329 LogNotifier.DebugFormat(GetType(), "Create object for <{0}>", elem.Name); | |
330 | |
331 if (elem.Name.Equals(WarFoundryXmlElementName.CATEGORY_ELEMENT.Value)) | |
332 { | |
333 LogNotifier.Debug(GetType(), "Create Category"); | |
334 obj = CreateCategoryFromElement(elem); | |
335 } | |
336 else | |
337 { | |
338 LogNotifier.Debug(GetType(), "No match"); | |
339 } | |
340 | |
341 return obj; | |
342 } | |
343 | |
344 private Category CreateCategoryFromElement(XmlElement elem) | |
345 { | |
346 string id = elem.GetAttribute("id"); | |
347 string name = elem.GetAttribute("name"); | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
348 int minPc, maxPc, minPts, maxPts, minChoices, maxChoices, baseValue, incValue, incAmount; |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
349 minPc = GetIntValueFromAttribute(elem, "minPercentage"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
350 maxPc = GetIntValueFromAttribute(elem, "maxPercentage"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
351 minPts = GetIntValueFromAttribute(elem, "minPoints"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
352 maxPts = GetIntValueFromAttribute(elem, "maxPoints"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
353 minChoices = GetIntValueFromAttribute(elem, "minChoices"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
354 maxChoices = GetIntValueFromAttribute(elem, "maxChoices"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
355 baseValue = GetIntValueFromAttribute(elem, "baseValue"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
356 incValue = GetIntValueFromAttribute(elem, "incValue"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
357 incAmount = GetIntValueFromAttribute(elem, "incAmount"); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
358 |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
359 return new Category(id, name, minPts, maxPts, minPc, maxPc, minChoices, maxChoices, baseValue, incValue, incAmount); |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
360 } |
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
361 |
10 | 362 private int GetIntValueFromAttribute(XmlElement elem, string attributeName) |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
363 { |
0 | 364 try |
365 { | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
366 return int.Parse(elem.GetAttribute(attributeName)); |
0 | 367 } |
368 catch(FormatException) | |
369 { | |
9
6ad505b6c36e
Re #10 - Refactor for readability
IBBoard <dev@ibboard.co.uk>
parents:
8
diff
changeset
|
370 throw new FormatException(String.Format("Attribute '{0}' of {1} with ID {2} was not a valid number", attributeName, elem.Name, elem.GetAttribute("id"))); |
0 | 371 } |
372 } | |
373 | |
374 private UnitType CreateUnitTypeFromElement(XmlElement elem, Race parentRace, GameSystem system) | |
375 { | |
376 string id = elem.GetAttribute("id"); | |
377 string name = elem.GetAttribute("typeName"); | |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
378 UnitType type = new UnitType(id, name, parentRace); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
379 type.MinNumber = GetIntValueFromAttribute(elem, "minNum"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
380 type.MaxNumber = GetIntValueFromAttribute(elem, "maxNum"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
381 type.MinSize = GetIntValueFromAttribute(elem, "minSize"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
382 type.MaxSize = GetIntValueFromAttribute(elem, "maxSize"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
383 //TODO: Add base size |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
384 type.CostPerTrooper = GetIntValueFromAttribute(elem, "points"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
385 type.BaseUnitCost = GetIntValueFromAttribute(elem, "unitPoints"); |
0 | 386 |
387 XmlNode node = elem.FirstChild; | |
388 | |
389 foreach(XmlElement cat in node.ChildNodes) | |
390 { | |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
391 string catID = cat.GetAttribute("catID"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
392 type.AddCategory(parentRace.GetCategory(catID)); |
0 | 393 } |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
394 |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
395 string mainCatID = elem.GetAttribute("cat"); |
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
396 type.MainCategory = parentRace.GetCategory(mainCatID); |
0 | 397 node = node.NextSibling; |
12
ac232763858b
Re #9 - Make WarFoundry API use smaller methods
IBBoard <dev@ibboard.co.uk>
parents:
11
diff
changeset
|
398 type.UnitStats = ParseUnitStats((XmlElement)node, system); |
0 | 399 //TODO: Add unit requirements |
400 | |
401 return type; | |
402 } | |
403 | |
404 private Stats ParseUnitStats(XmlElement elem, GameSystem system) | |
405 { | |
406 List<Stat> statsList = new List<Stat>(); | |
407 String statsID = elem.GetAttribute("statSet"); | |
408 SystemStats statsSet; | |
409 | |
410 if (statsID == "") | |
411 { | |
412 statsSet = system.StandardSystemStats; | |
413 } | |
414 else | |
415 { | |
6 | 416 statsSet = system.GetSystemStatsForID(statsID); |
0 | 417 } |
418 | |
419 Stats stats = new Stats(statsSet); | |
420 | |
421 foreach (XmlElement stat in elem.ChildNodes) | |
422 { | |
423 String statID = stat.GetAttribute("name"); | |
424 StatSlot slot = statsSet[statID]; | |
425 | |
426 if (slot!=null) | |
427 { | |
428 statsList.Add(new Stat(slot, stat.InnerText)); | |
429 } | |
430 else | |
431 { | |
432 throw new InvalidFileException("The stat "+statID+" was not found in stats set "+statsID); | |
433 } | |
434 } | |
435 | |
436 stats.SetStats(statsList); | |
437 | |
438 return stats; | |
439 } | |
440 | |
6 | 441 private void LoadSystemStatsFromElement(XmlElement elem, GameSystem system) |
0 | 442 { |
443 foreach (XmlElement stats in elem.ChildNodes) | |
444 { | |
445 SystemStats sysStats = CreateSystemStatsFromElement(stats); | |
6 | 446 system.AddSystemStats(sysStats); |
0 | 447 } |
448 } | |
449 | |
450 private SystemStats CreateSystemStatsFromElement(XmlElement elem) | |
451 { | |
452 List<StatSlot> slots = new List<StatSlot>(); | |
453 string id = elem.GetAttribute("id"); | |
454 | |
455 foreach (XmlElement slot in elem.ChildNodes) | |
456 { | |
457 StatSlot statSlot = new StatSlot(slot.GetAttribute("name")); | |
458 slots.Add(statSlot); | |
459 } | |
460 | |
461 return new SystemStats(id, slots.ToArray()); | |
462 } | |
463 | |
464 private EquipmentItem CreateEquipmentItemFromElement(XmlElement elem, Race race) | |
465 { | |
466 string id = elem.GetAttribute("id"); | |
467 string name = elem.GetAttribute("name"); | |
468 float cost = 0, min = 0, max = 0; | |
469 ArmourType armourType; | |
470 | |
471 try | |
472 { | |
473 cost = float.Parse(elem.GetAttribute("cost")); | |
474 } | |
475 catch(FormatException) | |
476 { | |
477 throw new FormatException("Attribute 'cost' of equipment item "+id+" was not a valid number"); | |
478 } | |
479 | |
480 try | |
481 { | |
482 min = float.Parse(elem.GetAttribute("min")); | |
483 } | |
484 catch(FormatException) | |
485 { | |
486 throw new FormatException("Attribute 'min' of equipment item "+id+" was not a valid number"); | |
487 } | |
488 | |
489 try | |
490 { | |
491 max = float.Parse(elem.GetAttribute("max")); | |
492 } | |
493 catch(FormatException) | |
494 { | |
495 throw new FormatException("Attribute 'max' of equipment item "+id+" was not a valid number"); | |
496 } | |
497 | |
498 try | |
499 { | |
500 armourType = (ArmourType)Enum.Parse(typeof(ArmourType), elem.GetAttribute("armourType")); | |
501 } | |
502 catch(FormatException) | |
503 { | |
504 throw new InvalidFileException("Attribute 'armourType' of equipment "+id+" was not a valid value from the enumeration"); | |
505 } | |
506 | |
507 if (elem.ChildNodes.Count>0) | |
508 { | |
509 //It has stats! | |
510 //TODO: Parse equipment stats | |
511 } | |
512 | |
513 return new EquipmentItem(id, name, cost, min, max, armourType, race); | |
514 } | |
515 | |
516 private void ValidationEventMethod(object sender, ValidationEventArgs e) | |
517 { | |
518 //TODO: Fire a validation failure event | |
519 LogNotifier.WarnFormat(GetType(), "Validation Error: {0}", e.Message); | |
520 } | |
521 } | |
522 } |