Mercurial > repos > IBDev-IBBoard.WarFoundry.API
diff api/WarFoundryLoader.cs @ 14:0770e5cbba7c
Closes #21 - File loading in order
* Reworked LoadFiles to smaller methods for readability (also re #10) and structure
* Now determine expected load return before loading then load all "expected GameSystem" before "expected Race"
* Make "can load as race/game system/army" methods public in interface
Re #22 - Get errored file loading
* Created FileLoadFailure class and made LoadFiles return a list of them
Also
* Some code cleanup
* Change to DictionaryUtils calls
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 25 Jan 2009 14:03:20 +0000 |
parents | 613bc5eaac59 |
children | 306558904c2a |
line wrap: on
line diff
--- a/api/WarFoundryLoader.cs Thu Jan 22 20:26:08 2009 +0000 +++ b/api/WarFoundryLoader.cs Sun Jan 25 14:03:20 2009 +0000 @@ -152,49 +152,22 @@ /// <summary> /// Loads all of the data files in the registered directories. /// </summary> - public void LoadFiles() + /// <returns> + /// A <see cref="Dictionary"/> of files that failed to load mapped against the message that their failure returned + /// </returns> + public List<FileLoadFailure> LoadFiles() { LogNotifier.Debug(GetType(), "Load files"); PrepareForFileLoad(); - - foreach (DirectoryInfo directory in directories) - { - if (directory.Exists) - { - LogNotifier.Debug(GetType(), "Load from "+directory.FullName); - - foreach (FileInfo file in directory.GetFiles()) - { - LoadFile(file); - } - } - else - { - LogNotifier.WarnFormat(GetType(), "Load for {0} failed because directory didn't exist", directory.FullName); - } - } - - ICollection<Race> races = new List<Race>(); + Dictionary<FileInfo, IWarFoundryFactory> loadableRaces = new Dictionary<FileInfo, IWarFoundryFactory>(); + Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems = new Dictionary<FileInfo, IWarFoundryFactory>(); + List<FileLoadFailure> failedLoads = FillLoadableFiles(loadableRaces, loadableGameSystems); + failedLoads.AddRange(LoadGameSystems(loadableGameSystems)); + failedLoads.AddRange(LoadRaces(loadableRaces)); + + LogNotifier.Debug(GetType(), failedLoads.Count + " failed file loads"); - foreach (SimpleSet<IWarFoundryObject> objs in loadedObjects.Values) - { - foreach (IWarFoundryObject obj in objs) - { - if (obj is Race) - { - races.Add((Race)obj); - } - else if (obj is GameSystem) - { - StoreGameSystem((GameSystem)obj); - } - } - } - - foreach (Race race in races) - { - StoreRace(race); - } + return failedLoads; } protected void PrepareForFileLoad() @@ -203,6 +176,179 @@ systemsTable = new Dictionary<string,GameSystem>(); racesTable = new Dictionary<string,Dictionary<string,Dictionary<string,Race>>>(); } + + private List<FileLoadFailure> FillLoadableFiles(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems) + { + List<FileLoadFailure> fails = new List<FileLoadFailure>(); + + foreach (DirectoryInfo directory in directories) + { + if (directory.Exists) + { + List<FileLoadFailure> directoryFails = FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, directory); + fails.AddRange(directoryFails); + } + else + { + LogNotifier.WarnFormat(GetType(), "Load for {0} failed because directory didn't exist", directory.FullName); + } + } + + return fails; + } + + private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems, DirectoryInfo directory) + { + List<FileLoadFailure> fails = new List<FileLoadFailure>(); + LogNotifier.Debug(GetType(), "Load from "+directory.FullName); + + foreach (FileInfo file in directory.GetFiles()) + { + IWarFoundryFactory factory = GetGameSystemRaceLoadingFactoryForFile(file); + + if (factory != null) + { + loadableGameSystems.Add(file, factory); + } + else + { + factory = GetRaceLoadingFactoryForFile(file); + + if (factory!=null) + { + loadableRaces.Add(file, factory); + } + else + { + fails.Add(new FileLoadFailure(file, "FileNotHandled", "File not handled as a Race or Game System definition: {0}")); + } + } + } + + return fails; + } + + private IWarFoundryFactory GetGameSystemRaceLoadingFactoryForFile(FileInfo file) + { + IWarFoundryFactory loadingFactory = null; + + foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) + { + if (factory.CanHandleFileAsGameSystem(file)) + { + loadingFactory = factory; + break; + } + } + + if (loadingFactory == null) + { + foreach (INativeWarFoundryFactory factory in factories) + { + if (factory.CanHandleFileAsGameSystem(file)) + { + loadingFactory = factory; + break; + } + } + } + + return loadingFactory; + } + + private IWarFoundryFactory GetRaceLoadingFactoryForFile(FileInfo file) + { + IWarFoundryFactory loadingFactory = null; + + foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) + { + if (factory.CanHandleFileAsRace(file)) + { + loadingFactory = factory; + break; + } + } + + if (loadingFactory == null) + { + foreach (INativeWarFoundryFactory factory in factories) + { + if (factory.CanHandleFileAsRace(file)) + { + loadingFactory = factory; + break; + } + } + } + + return loadingFactory; + } + + private List<FileLoadFailure> LoadGameSystems(Dictionary<FileInfo, IWarFoundryFactory> gameSystemFiles) + { + List<FileLoadFailure> fails = new List<FileLoadFailure>(); + + + foreach (FileInfo file in gameSystemFiles.Keys) + { + try + { + bool loaded = LoadObject(file, gameSystemFiles[file]); + + if (!loaded) + { + fails.Add(new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}")); + } + } + catch (Exception ex) + { + fails.Add(new FileLoadFailure(file, ex.Message)); + } + } + + return fails; + } + + private List<FileLoadFailure> LoadRaces(Dictionary<FileInfo, IWarFoundryFactory> raceFiles) + { + List<FileLoadFailure> fails = new List<FileLoadFailure>(); + + foreach (FileInfo file in raceFiles.Keys) + { + try + { + bool loaded = LoadObject(file, raceFiles[file]); + + if (!loaded) + { + fails.Add(new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}")); + } + } + catch (Exception ex) + { + fails.Add(new FileLoadFailure(file, ex.Message)); + } + } + + return fails; + } + + private bool LoadObject(FileInfo file, IWarFoundryFactory factory) + { + bool loaded = false; + + LogNotifier.DebugFormat(GetType(), "Loading {0} using {1}", file.FullName, factory.GetType().Name); + ICollection<IWarFoundryObject> objects = factory.CreateObjectsFromFile(file); + + if (objects.Count > 0) + { + AddLoadedObjects(objects, factory); + loaded = true; + } + + return loaded; + } + /// <summary> /// Loads a single file through the registered WarFoundryFactories, if a factory exists that supports the file format. @@ -210,60 +356,66 @@ /// <param name="file"> /// A <see cref="FileInfo"/> for the file to attempt to load /// </param> - protected void LoadFile(FileInfo file) + /// <returns> + /// An ICollection of IWarFoundryObjects loaded from <code>file</code> + /// </returns> + public ICollection<IWarFoundryObject> LoadFile(FileInfo file) { - bool handled = false; + ICollection<IWarFoundryObject> objs = null; + IWarFoundryFactory loadFactory = null; - if (!handled) + if (nonNativeFactories.Count > 0) { - ICollection<IWarFoundryObject> objs = null; - IWarFoundryFactory loadFactory = null; + LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as a non-native file"); - if (nonNativeFactories.Count > 0) + foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) { - LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as a non-native file"); + bool canLoad = factory.CanHandleFileFormat(file); + LogNotifier.Debug(GetType(), "Load using "+factory.GetType().FullName+"? " + (canLoad ? "yes" : "no")); - foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) + if (canLoad) { - LogNotifier.Debug(GetType(), "Load using "+factory.GetType().AssemblyQualifiedName+"? " + (factory.CanHandleFileFormat(file) ? "yes" : "no")); + objs = factory.CreateObjectsFromFile(file); - if (factory.CanHandleFileFormat(file)) + if (objs!=null) { - objs = factory.CreateObjectsFromFile(file); - - if (objs!=null) - { - loadFactory = factory; - break; - } - } - } + loadFactory = factory; + break; + } + } } + } + + if (objs == null) + { + LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as native file"); - if (objs == null) + foreach (INativeWarFoundryFactory factory in factories) { - LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as native file"); - - foreach (INativeWarFoundryFactory factory in factories) + if (factory.CanHandleFileFormat(file)) { - if (factory.CanHandleFileFormat(file)) + objs = factory.CreateObjectsFromFile(file); + + if (objs!=null) { - objs = factory.CreateObjectsFromFile(file); - - if (objs!=null) - { - loadFactory = factory; - break; - } + loadFactory = factory; + break; } } } - - if (objs!=null) - { - AddLoadedObjects(objs, loadFactory); - } + } + + if (objs!=null) + { + AddLoadedObjects(objs, loadFactory); } + else + { + LogNotifier.Debug(GetType(), "Loading of "+file.FullName+" failed"); + objs = new List<IWarFoundryObject>(); + } + + return objs; } private void AddLoadedObjects(ICollection<IWarFoundryObject> loadedObjs, IWarFoundryFactory factory) @@ -278,20 +430,22 @@ } objs.AddRange(loadedObjs); + StoreObjects(loadedObjs); } - - private void AddLoadedObject(IWarFoundryObject obj, IWarFoundryFactory factory) + + private void StoreObjects(ICollection<IWarFoundryObject> loadedObjects) { - SimpleSet<IWarFoundryObject> objs; - loadedObjects.TryGetValue(factory, out objs); - - if (objs == null) + foreach (IWarFoundryObject loadedObject in loadedObjects) { - objs = new SimpleSet<IWarFoundryObject>(); - loadedObjects.Add(factory, objs); + if (loadedObject is GameSystem) + { + StoreGameSystem((GameSystem)loadedObject); + } + else if (loadedObject is Race) + { + StoreRace((Race)loadedObject); + } } - - objs.Add(obj); } protected virtual ZipFile MakeZipFile(FileInfo file) @@ -313,24 +467,6 @@ } } - - /// <summary> - /// Stores a loaded <see cref="GameSystem"/> that has been generated outside the core loading structure. - /// - /// Note: Calls to this function should be made before calls to StoreRace(Race, IWarFoundryFactory). - /// </summary> - /// <param name="system"> - /// The <see cref="GameSystem"/> to register as loaded. - /// </param> - /// <param name="factory"> - /// The <see cref="IWarFoundryFactory"/> that created it. - /// </param> - public void StoreGameSystem(GameSystem system, IWarFoundryFactory factory) - { - AddLoadedObject(system, factory); - StoreGameSystem(system); - } - protected void StoreRace(Race race) { Dictionary<string, Dictionary<string, Race>> systemRaces; @@ -370,23 +506,6 @@ } /// <summary> - /// Stores a loaded <see cref="Race"/> that has been generated outside the core loading structure. - /// - /// Note: Calls to this function should ensure that the relevant <see cref="GameSystem"> has been created first. - /// </summary> - /// <param name="race"> - /// The <see cref="Race"/> to register as loaded. - /// </param> - /// <param name="factory"> - /// The <see cref="IWarFoundryFactory"/> that created it - /// </param> - public void StoreRace(Race race, IWarFoundryFactory factory) - { - AddLoadedObject(race, factory); - StoreRace(race); - } - - /// <summary> /// Gets all <see cref="GameSystem"/>s that are currently available, determined by those that can be loaded with the current <see cref="IWarFoundryFactory"/>s. /// </summary> /// <returns> @@ -399,15 +518,7 @@ LoadFiles(); } - GameSystem[] systems = new GameSystem[systemsTable.Count]; - int iSys = 0; - - foreach (GameSystem sys in systemsTable.Values) - { - systems[iSys++] = sys; - } - - return systems; + return DictionaryUtils.ToArray<string, GameSystem>(systemsTable); } /// <summary>