view api/Factories/AbstractNativeWarFoundryFactory.cs @ 151:1d13820b3d96

Fixes #176: Bug when saving recently edited army * Add loaded file cleanup to AbstractWarFoundryFactory * Add override of method with Zip reference closing to WarFoundryXmlFactory WarFoundry now no longer ends up with trailing handles to files, although why they only caused problems in some situations is unknown Also: * Some line ending fixes (curse cross-platform development and different line terminators!)
author IBBoard <dev@ibboard.co.uk>
date Sat, 26 Sep 2009 18:48:36 +0000
parents b36cc4af435b
children 70ba3bee0c2e
line wrap: on
line source

// This file (AbstractNativeWarFoundryFactory.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2007, 2008, 2009 IBBoard.
//
// 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.

using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Collections.Generic;
using System.Text;
using IBBoard;
using IBBoard.IO;
using IBBoard.Lang;
using IBBoard.Logging;
using IBBoard.Xml;
using IBBoard.WarFoundry.API.Objects;
using ICSharpCode.SharpZipLib.Zip;

namespace IBBoard.WarFoundry.API.Factories
{
	/// <summary>
	/// Base abstract class for all factories that load native WarFoundry data.
	/// </summary>
	public abstract class AbstractNativeWarFoundryFactory : AbstractWarFoundryFactory<ZipFile>, INativeWarFoundryFactory
	{
		public static readonly string SYSTEM_ZIP_IDENTIFIER = "WarFoundry_System";
		public static readonly string RACE_ZIP_IDENTIFIER = "WarFoundry_Race";
		public static readonly string ARMY_ZIP_IDENTIFIER = "WarFoundry_Army";
				
		protected AbstractNativeWarFoundryFactory()
		{
			//Do nothing - just make the constructor non-public
		}
				
		protected override ZipFile GetFileAsSupportedType (FileInfo file)
		{
			ZipFile zip = null;
			
			try
			{
				zip = new ZipFile(file.FullName);
			}
			catch(ZipException)
			{
				//Silently dispose as per spec for the method
			}
			catch (IOException)
			{
				//Silently dispose as per spec for the method
			}
			
			return zip;
		}
		
		protected override bool CheckCanHandleFileFormat (ZipFile file)
		{	
			return CheckCanHandleFileAsGameSystem(file) || CheckCanHandleFileAsRace(file) || CheckCanHandleFileAsArmy(file); 
		}
		
		protected override bool CheckCanHandleFileAsGameSystem(ZipFile file)
		{
			return file.ZipFileComment.StartsWith(SYSTEM_ZIP_IDENTIFIER) && CheckCanFindSystemFileContent(file);
		}
		
		protected abstract bool CheckCanFindSystemFileContent(ZipFile file);
		
		protected override bool CheckCanHandleFileAsRace(ZipFile file)
		{
			return file.ZipFileComment.StartsWith(RACE_ZIP_IDENTIFIER) && CheckCanFindRaceFileContent(file);
		}
		
		protected abstract bool CheckCanFindRaceFileContent(ZipFile file);
		
		protected override bool CheckCanHandleFileAsArmy(ZipFile file)
		{
			return file.ZipFileComment.StartsWith(ARMY_ZIP_IDENTIFIER) && CheckCanFindArmyFileContent(file);
		}
		
		protected abstract bool CheckCanFindArmyFileContent(ZipFile file);
		
		protected override ICollection<IWarFoundryObject> DoCreateObjectsFromFile (ZipFile file)
		{
			ICollection<IWarFoundryObject> objects = null;
			string comment = file.ZipFileComment;
			IWarFoundryObject obj = null;
				
			if (comment.StartsWith(SYSTEM_ZIP_IDENTIFIER))
			{
				obj = CreateGameSystemFromFile(file);
			}
			else if (comment.StartsWith(RACE_ZIP_IDENTIFIER))
			{
				obj = CreateRaceFromFile(file);
			}
			else if (comment.StartsWith(ARMY_ZIP_IDENTIFIER))
			{
				obj = CreateArmyFromFile(file);
			}
			
			if (obj!=null)
			{
				objects = new List<IWarFoundryObject>();
				objects.Add(obj);
			}

			file.Close();
			
			return objects;
		}
		
		protected Army CreateArmyFromFile(ZipFile file)
		{
			Stream dataStream = GetArmyDataStream(file);

			try
			{
				return CreateArmyFromStream(file, dataStream);
			}
			catch (InvalidFileException ex)
			{
				throw new InvalidFileException("Data file " + file.Name + " was not a valid army file", ex);
			}
			finally
			{
				dataStream.Close();
			}
		}
		
		protected abstract Stream GetArmyDataStream(ZipFile file);
		protected abstract Army CreateArmyFromStream(ZipFile file, Stream dataStream);
		
		protected Race CreateRaceFromFile(ZipFile file)
		{
			Stream dataStream = GetRaceDataStream(file);

			try
			{
				return CreateRaceFromStream(file, dataStream);
			}
			catch (InvalidFileException ex)
			{
				throw new InvalidFileException("Data file "+file.Name+" was not a valid race file", ex);
			}
			finally
			{
				dataStream.Close();
			}
		}
		
		protected abstract Stream GetRaceDataStream(ZipFile file);
		protected abstract Race CreateRaceFromStream(ZipFile file, Stream dataStream);
		
		protected GameSystem CreateGameSystemFromFile(ZipFile file)
		{
			Stream dataStream = GetGameSystemDataStream(file);

			try
			{
				return CreateGameSystemFromStream(file, dataStream);
			}
			catch (InvalidFileException ex)
			{
				throw new InvalidFileException("Data file " + file.Name + " was not a valid game system file", ex);
			}
			finally
			{
				dataStream.Close();
			}
		}
		
		protected abstract Stream GetGameSystemDataStream(ZipFile file);
		protected abstract GameSystem CreateGameSystemFromStream(ZipFile file, Stream dataStream);
		
		public override bool Equals (object o)
		{
			if (o == this)
			{
				return true;
			}
			else if (o == null || !(this.GetType().Equals(o.GetType())))
			{
				return false;
			}
			
			return true;
		}
		
		public override int GetHashCode ()
		{
			return GetType().FullName.GetHashCode();
		}
	}
}