comparison api/AbstractWarFoundryLoader.cs @ 291:24e7b571f50f

Re #318: DefaultWarFoundryLoader throws null ref when loading individual files * Fix quick fix so that it actually works and loads files - but it is still a quick-fix that needs double-checking
author IBBoard <dev@ibboard.co.uk>
date Tue, 14 Dec 2010 20:17:07 +0000
parents c035afa4a42c
children b24a78cfd314
comparison
equal deleted inserted replaced
290:5ed39187b0e3 291:24e7b571f50f
20 { 20 {
21 private ICollection<DirectoryInfo> directories; 21 private ICollection<DirectoryInfo> directories;
22 private ICollection<INativeWarFoundryFactory> factories; 22 private ICollection<INativeWarFoundryFactory> factories;
23 private ICollection<INonNativeWarFoundryFactory> nonNativeFactories; 23 private ICollection<INonNativeWarFoundryFactory> nonNativeFactories;
24 private Dictionary<IWarFoundryFactory, SimpleSet<IWarFoundryObject>> loadedObjects; 24 private Dictionary<IWarFoundryFactory, SimpleSet<IWarFoundryObject>> loadedObjects;
25
25 public delegate void FileLoadingCompleteDelegate(List<FileLoadFailure> failures); 26 public delegate void FileLoadingCompleteDelegate(List<FileLoadFailure> failures);
27
26 public event MethodInvoker FileLoadingStarted; 28 public event MethodInvoker FileLoadingStarted;
29
27 public event FileLoadingCompleteDelegate FileLoadingFinished; 30 public event FileLoadingCompleteDelegate FileLoadingFinished;
28 31
29 protected AbstractWarFoundryLoader() 32 protected AbstractWarFoundryLoader()
30 { 33 {
31 directories = new List<DirectoryInfo>(); 34 directories = new List<DirectoryInfo>();
32 factories = new List<INativeWarFoundryFactory>(); 35 factories = new List<INativeWarFoundryFactory>();
33 nonNativeFactories = new List<INonNativeWarFoundryFactory>(); 36 nonNativeFactories = new List<INonNativeWarFoundryFactory>();
131 Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems = new Dictionary<FileInfo, IWarFoundryFactory>(); 134 Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems = new Dictionary<FileInfo, IWarFoundryFactory>();
132 List<FileLoadFailure> failedLoads = FillLoadableFiles(loadableRaces, loadableGameSystems); 135 List<FileLoadFailure> failedLoads = FillLoadableFiles(loadableRaces, loadableGameSystems);
133 failedLoads.AddRange(LoadGameSystems(loadableGameSystems)); 136 failedLoads.AddRange(LoadGameSystems(loadableGameSystems));
134 failedLoads.AddRange(LoadRaces(loadableRaces)); 137 failedLoads.AddRange(LoadRaces(loadableRaces));
135 OnFileLoadingFinished(failedLoads); 138 OnFileLoadingFinished(failedLoads);
139 FinishFileLoad();
136 return failedLoads; 140 return failedLoads;
137 } 141 }
138 142
139 private void OnFileLoadingFinished(List<FileLoadFailure> failures) 143 private void OnFileLoadingFinished(List<FileLoadFailure> failures)
140 { 144 {
141 if (FileLoadingFinished!=null) 145 if (FileLoadingFinished != null)
142 { 146 {
143 FileLoadingFinished(failures); 147 FileLoadingFinished(failures);
144 } 148 }
145 } 149 }
146 150
147 protected abstract void PrepareForFileLoad(); 151 protected virtual void PrepareForFileLoad()
152 {
153 //Do nothing special
154 }
155
156 protected virtual void FinishFileLoad()
157 {
158 //Do nothing special
159 }
148 160
149 private List<FileLoadFailure> FillLoadableFiles(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems) 161 private List<FileLoadFailure> FillLoadableFiles(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems)
150 { 162 {
151 List<FileLoadFailure> fails = new List<FileLoadFailure>(); 163 List<FileLoadFailure> fails = new List<FileLoadFailure>();
152 164
169 } 181 }
170 182
171 private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems, DirectoryInfo directory) 183 private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems, DirectoryInfo directory)
172 { 184 {
173 List<FileLoadFailure> fails = new List<FileLoadFailure>(); 185 List<FileLoadFailure> fails = new List<FileLoadFailure>();
174 LogNotifier.Debug(GetType(), "Load from "+directory.FullName); 186 LogNotifier.Debug(GetType(), "Load from " + directory.FullName);
175 187
176 foreach (FileInfo file in directory.GetFiles()) 188 foreach (FileInfo file in directory.GetFiles())
177 { 189 {
178 IWarFoundryFactory factory = GetGameSystemLoadingFactoryForFile(file); 190 IWarFoundryFactory factory = GetGameSystemLoadingFactoryForFile(file);
179 191
183 } 195 }
184 else 196 else
185 { 197 {
186 factory = GetRaceLoadingFactoryForFile(file); 198 factory = GetRaceLoadingFactoryForFile(file);
187 199
188 if (factory!=null) 200 if (factory != null)
189 { 201 {
190 loadableRaces.Add(file, factory); 202 loadableRaces.Add(file, factory);
191 } 203 }
192 else 204 else
193 { 205 {
278 catch (Exception ex) 290 catch (Exception ex)
279 { 291 {
280 failure = new FileLoadFailure(file, null, ex.Message, null, ex); 292 failure = new FileLoadFailure(file, null, ex.Message, null, ex);
281 } 293 }
282 294
283 if (failure!=null) 295 if (failure != null)
284 { 296 {
285 fails.Add(failure); 297 fails.Add(failure);
286 LogNotifier.Warn(GetType(), failure.Message, failure.Exception); 298 LogNotifier.Warn(GetType(), failure.Message, failure.Exception);
287 } 299 }
288 } 300 }
310 catch (Exception ex) 322 catch (Exception ex)
311 { 323 {
312 failure = new FileLoadFailure(file, null, ex.Message, null, ex); 324 failure = new FileLoadFailure(file, null, ex.Message, null, ex);
313 } 325 }
314 326
315 if (failure!=null) 327 if (failure != null)
316 { 328 {
317 fails.Add(failure); 329 fails.Add(failure);
318 LogNotifier.Warn(GetType(), failure.Message, failure.Exception); 330 LogNotifier.Warn(GetType(), failure.Message, failure.Exception);
319 } 331 }
320 } 332 }
362 objs = LoadFileWithNativeFactories(file, out loadFactory); 374 objs = LoadFileWithNativeFactories(file, out loadFactory);
363 } 375 }
364 } 376 }
365 catch (InvalidFileException ex) 377 catch (InvalidFileException ex)
366 { 378 {
367 LogNotifier.Error(GetType(), file.FullName+" failed to load", ex); 379 LogNotifier.Error(GetType(), file.FullName + " failed to load", ex);
368 } 380 }
369 381
370 if (objs!=null) 382 if (objs != null)
371 { 383 {
372 AddLoadedObjects(objs, loadFactory); 384 AddLoadedObjects(objs, loadFactory);
373 } 385 }
374 else 386 else
375 { 387 {
376 objs = new List<IWarFoundryObject>(); 388 objs = new List<IWarFoundryObject>();
377 } 389 }
378 390
379 return objs; 391 return objs;
380 } 392 }
381 393
382 private ICollection<IWarFoundryObject> LoadFileWithNonNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory) 394 private ICollection<IWarFoundryObject> LoadFileWithNonNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory)
383 { 395 {
384 ICollection<IWarFoundryObject> objs = null; 396 ICollection<IWarFoundryObject> objs = null;
385 loadFactory = null; 397 loadFactory = null;
386 398
387 if (nonNativeFactories.Count > 0) 399 if (nonNativeFactories.Count > 0)
388 { 400 {
389 LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as a non-native file"); 401 LogNotifier.Debug(GetType(), "Attempting to load " + file.FullName + " as a non-native file");
390 402
391 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) 403 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories)
392 { 404 {
393 bool canLoad = factory.CanHandleFileFormat(file); 405 bool canLoad = factory.CanHandleFileFormat(file);
394 LogNotifier.Debug(GetType(), "Load using "+factory.GetType().FullName+"? " + (canLoad ? "yes" : "no")); 406 LogNotifier.Debug(GetType(), "Load using " + factory.GetType().FullName + "? " + (canLoad ? "yes" : "no"));
395 407
396 if (canLoad) 408 if (canLoad)
397 { 409 {
398 objs = factory.CreateObjectsFromFile(file); 410 objs = factory.CreateObjectsFromFile(file);
399 411
400 if (objs!=null) 412 if (objs != null)
401 { 413 {
402 loadFactory = factory; 414 loadFactory = factory;
403 break; 415 break;
404 } 416 }
405 } 417 }
406 } 418 }
407 } 419 }
408 420
409 return objs; 421 return objs;
410 } 422 }
411 423
412 private ICollection<IWarFoundryObject> LoadFileWithNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory) 424 private ICollection<IWarFoundryObject> LoadFileWithNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory)
413 { 425 {
414 ICollection<IWarFoundryObject> objs = null; 426 ICollection<IWarFoundryObject> objs = null;
415 loadFactory = null; 427 loadFactory = null;
416 428
417 if (factories.Count > 0) 429 if (factories.Count > 0)
418 { 430 {
419 LogNotifier.Debug(GetType(), "Attempting to load "+file.FullName+" as native file"); 431 LogNotifier.Debug(GetType(), "Attempting to load " + file.FullName + " as native file");
420 432
421 foreach (INativeWarFoundryFactory factory in factories) 433 foreach (INativeWarFoundryFactory factory in factories)
422 { 434 {
423 if (factory.CanHandleFileFormat(file)) 435 if (factory.CanHandleFileFormat(file))
424 { 436 {
425 objs = factory.CreateObjectsFromFile(file); 437 objs = factory.CreateObjectsFromFile(file);
426 438
427 if (objs!=null) 439 if (objs != null)
428 { 440 {
429 loadFactory = factory; 441 loadFactory = factory;
430 break; 442 break;
431 } 443 }
432 } 444 }
433 } 445 }
434 } 446 }
435 447
436 return objs; 448 return objs;
437 } 449 }
438 450
439 private void AddLoadedObjects(ICollection<IWarFoundryObject> loadedObjs, IWarFoundryFactory factory) 451 private void AddLoadedObjects(ICollection<IWarFoundryObject> loadedObjs, IWarFoundryFactory factory)
440 { 452 {
441 SimpleSet<IWarFoundryObject> objs; 453 SimpleSet<IWarFoundryObject> objs;
442 loadedObjects.TryGetValue(factory, out objs); 454 loadedObjects.TryGetValue(factory, out objs);
443 455
463 { 475 {
464 StoreRace((Race)loadedObject); 476 StoreRace((Race)loadedObject);
465 } 477 }
466 } 478 }
467 } 479 }
468 480
469 protected void StoreGameSystem(GameSystem system) 481 protected void StoreGameSystem(GameSystem system)
470 { 482 {
471 GameSystem existingSystem = GetExistingSystemForSystem(system); 483 GameSystem existingSystem = GetExistingSystemForSystem(system);
472 484
473 if (existingSystem!=null) 485 if (existingSystem != null)
474 { 486 {
475 if (!system.Equals(existingSystem)) 487 if (!system.Equals(existingSystem))
476 { 488 {
477 //TODO: Raise an event to say we got a different duplicate 489 //TODO: Raise an event to say we got a different duplicate
478 //We can't just fail, because failing is for completely unhandled files, not for objects in a file 490 //We can't just fail, because failing is for completely unhandled files, not for objects in a file
500 /// </summary> 512 /// </summary>
501 /// <param name="system"> 513 /// <param name="system">
502 /// The loaded <see cref="GameSystem"/> to store 514 /// The loaded <see cref="GameSystem"/> to store
503 /// </param> 515 /// </param>
504 protected abstract void DoStoreGameSystem(GameSystem system); 516 protected abstract void DoStoreGameSystem(GameSystem system);
505 517
506 protected void StoreRace(Race race) 518 protected void StoreRace(Race race)
507 { 519 {
508 if (race.GameSystem == null) 520 if (race.GameSystem == null)
509 { 521 {
510 throw new InvalidOperationException("Race cannot have null game system. Game system should be loaded before race."); 522 throw new InvalidOperationException("Race cannot have null game system. Game system should be loaded before race.");
599 public virtual string[] GetGameSystemIDs() 611 public virtual string[] GetGameSystemIDs()
600 { 612 {
601 GameSystem[] systems = GetGameSystems(); 613 GameSystem[] systems = GetGameSystems();
602 return GetWarFoundryObjectIDs(systems); 614 return GetWarFoundryObjectIDs(systems);
603 } 615 }
604 616
605 protected string[] GetWarFoundryObjectIDs(WarFoundryObject[] objs) 617 protected string[] GetWarFoundryObjectIDs(WarFoundryObject[] objs)
606 { 618 {
607 int objCount = objs.Length; 619 int objCount = objs.Length;
608 string[] keys = new string[objCount]; 620 string[] keys = new string[objCount];
609 621
627 public virtual string[] GetSystemRaceIDs(GameSystem system) 639 public virtual string[] GetSystemRaceIDs(GameSystem system)
628 { 640 {
629 Race[] races = GetRaces(system); 641 Race[] races = GetRaces(system);
630 return GetWarFoundryObjectIDs(races); 642 return GetWarFoundryObjectIDs(races);
631 } 643 }
632 644
633 public Army LoadArmy(FileInfo file) 645 public Army LoadArmy(FileInfo file)
634 { 646 {
635 IWarFoundryFactory factory = GetArmyLoadingFactoryForFile(file); 647 IWarFoundryFactory factory = GetArmyLoadingFactoryForFile(file);
636 Army loadedArmy = null; 648 Army loadedArmy = null;
637 649
643 { 655 {
644 foreach (IWarFoundryObject systemCount in objs) 656 foreach (IWarFoundryObject systemCount in objs)
645 { 657 {
646 if (systemCount is Army) 658 if (systemCount is Army)
647 { 659 {
648 loadedArmy = (Army) systemCount; 660 loadedArmy = (Army)systemCount;
649 } 661 }
650 } 662 }
651 } 663 }
652 } 664 }
653 665