comparison 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
comparison
equal deleted inserted replaced
336:3631c1493c7f 337:3c4a6403a88c
1 // This file (WarFoundryXmlFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2007, 2008, 2009 IBBoard.
2 //
3 // 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.
4
5 using System;
6 using System.IO;
7 using System.Xml;
8 using System.Xml.Schema;
9 using System.Xml.XPath;
10 using System.Collections.Generic;
11 using System.Text;
12 using IBBoard;
13 using IBBoard.IO;
14 using IBBoard.Lang;
15 using IBBoard.Logging;
16 using IBBoard.Xml;
17 using IBBoard.WarFoundry.API.Requirements;
18 using IBBoard.WarFoundry.API.Objects;
19 using ICSharpCode.SharpZipLib.Zip;
20 using System.Text.RegularExpressions;
21
22 namespace IBBoard.WarFoundry.API.Factories.Xml
23 {
24 /// <summary>
25 /// 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.
26 /// </summary>
27 public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
28 {
29 private static WarFoundryXmlFactory factory;
30 private WarFoundryXmlGameSystemFactory gameSystemFactory;
31 private WarFoundryXmlRaceFactory raceFactory;
32 private WarFoundryXmlArmyFactory armyFactory;
33
34 public static WarFoundryXmlFactory GetFactory()
35 {
36 if (factory == null)
37 {
38 factory = new WarFoundryXmlFactory();
39 }
40
41 return factory;
42 }
43
44 private WarFoundryXmlFactory() : base()
45 {
46 gameSystemFactory = new WarFoundryXmlGameSystemFactory(this);
47 raceFactory = new WarFoundryXmlRaceFactory(this);
48 armyFactory = new WarFoundryXmlArmyFactory();
49 }
50
51 public WarFoundryXmlGameSystemFactory GetSystemFactory()
52 {
53 return gameSystemFactory;
54 }
55
56 public WarFoundryXmlRaceFactory GetRaceFactory()
57 {
58 return raceFactory;
59 }
60
61 public WarFoundryXmlArmyFactory GetArmyFactory()
62 {
63 return armyFactory;
64 }
65
66 protected override bool CheckCanFindArmyFileContent(ZipFile file)
67 {
68 return FindEntries(file, "*.armyx").Count > 0;
69 }
70
71 protected override bool CheckCanFindSystemFileContent(ZipFile file)
72 {
73 return FindEntries(file, "*.systemx").Count > 0;
74 }
75
76 protected override bool CheckCanFindRaceFileContent(ZipFile file)
77 {
78 return FindEntries(file, "*.racex").Count > 0;
79 }
80
81 protected override ICollection<ZipEntry> GetArmyZipEntries(ZipFile file)
82 {
83 return FindEntries(file, "*.armyx");
84 }
85
86 private ICollection<ZipEntry> FindEntries(ZipFile file, string wildcardPattern)
87 {
88 Regex re = new Regex("^" + Regex.Escape(wildcardPattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
89 ICollection<ZipEntry> entries = new List<ZipEntry>();
90
91 foreach (ZipEntry entry in file)
92 {
93 if (re.IsMatch(entry.Name))
94 {
95 entries.Add(entry);
96 }
97 }
98
99 return entries;
100 }
101
102 protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
103 {
104 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
105 return armyFactory.CreateArmyFromElement(file, elem);
106 }
107
108 private XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
109 {
110 XmlDocument doc = WarFoundryXmlFactoryUtils.CreateXmlDocumentFromStream(stream);
111
112 XmlElement elem = (XmlElement)doc.LastChild;
113
114 if (!elem.LocalName.Equals(elementName.Value))
115 {
116 throw new InvalidFileException(String.Format("Root element of XML was not valid. Expected {0} but got {1}", elementName.Value, elem.Name));
117 }
118
119 return elem;
120 }
121
122 protected override ICollection<ZipEntry> GetGameSystemZipEntries(ZipFile file)
123 {
124 return FindEntries(file, "*.systemx");
125 }
126
127 protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
128 {
129 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
130 LogNotifier.Debug(GetType(), "Create GameSystem");
131 return gameSystemFactory.CreateSystemFromElement(file, elem);
132 }
133
134 protected override ICollection<ZipEntry> GetRaceZipEntries(ZipFile file)
135 {
136 return FindEntries(file, "*.racex");
137 }
138
139 protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
140 {
141 XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
142 LogNotifier.Debug(GetType(), "Create Race");
143 return raceFactory.CreateRaceFromElement(file, elem);
144 }
145
146 protected override void CleanUpFileAsSupportedType(ZipFile typedFile)
147 {
148 typedFile.Close();
149 }
150
151 public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
152 {
153 LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID);
154
155 if (obj is GameSystem)
156 {
157 CompleteLoadingGameSystem((GameSystem) obj);
158 }
159 else if (obj is Race)
160 {
161 CompleteLoadingRace((Race) obj);
162 }
163 }
164
165 private void CompleteLoadingRace(Race race)
166 {
167 try
168 {
169 raceFactory.CompleteLoading(race);
170 }
171 catch (InvalidFileException ex)
172 {
173 WarFoundryLoader.GetDefault().RemoveRace(race);
174 throw;
175 }
176 }
177
178 private void CompleteLoadingGameSystem(GameSystem system)
179 {
180 try
181 {
182 gameSystemFactory.CompleteLoading(system);
183 }
184 catch (InvalidFileException ex)
185 {
186 WarFoundryLoader.GetDefault().RemoveGameSystem(system);
187 throw;
188 }
189 }
190 }
191 }