view api/Factories/Xml/WarFoundryXmlFactory.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 a37cdcbcad14
children 70ba3bee0c2e
line wrap: on
line source

// This file (WarFoundryXmlFactory.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.Xml.XPath;
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.Requirements;
using IBBoard.WarFoundry.API.Objects;
using ICSharpCode.SharpZipLib.Zip;

namespace IBBoard.WarFoundry.API.Factories.Xml
{
	/// <summary>
	/// 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.
	/// </summary>
	public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
	{
		private static WarFoundryXmlFactory factory;
		private WarFoundryXmlGameSystemFactory gameSystemFactory;
		private WarFoundryXmlRaceFactory raceFactory;
		private WarFoundryXmlArmyFactory armyFactory;

		public static AbstractNativeWarFoundryFactory GetFactory()
		{
			if (factory == null)
			{
				factory = new WarFoundryXmlFactory();
			}
			
			return factory;
		}
		
		private WarFoundryXmlFactory() : base()
		{
			gameSystemFactory = new WarFoundryXmlGameSystemFactory(this);
			raceFactory = new WarFoundryXmlRaceFactory(this);
			armyFactory = new WarFoundryXmlArmyFactory();
		}
		
		protected override bool CheckCanFindArmyFileContent(ZipFile file)
		{
			return file.FindEntry("data.armyx", true) > -1;
		}
		
		protected override bool CheckCanFindSystemFileContent(ZipFile file)
		{
			return file.FindEntry("data.systemx", true) > -1;
		}
		
		protected override bool CheckCanFindRaceFileContent(ZipFile file)
		{
			return file.FindEntry("data.racex", true) > -1;
		}
		
		protected override Stream GetArmyDataStream(ZipFile file)
		{
			return file.GetInputStream(file.FindEntry("data.armyx", true));
		}
		
		protected override Army CreateArmyFromStream (ZipFile file, Stream dataStream)
		{
			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.ARMY_ELEMENT);
			return armyFactory.CreateArmyFromElement(file, elem);
		}
		
		private XmlElement GetRootElementFromStream(Stream stream, WarFoundryXmlElementName elementName)
		{
			XmlDocument doc = WarFoundryXmlFactoryUtils.CreateXmlDocumentFromStream(stream);
			stream.Close();
			XmlElement elem = (XmlElement)doc.LastChild;
			
			if (!elem.LocalName.Equals(elementName.Value))
			{
				throw new InvalidFileException(String.Format("Root element of XML was not valid. Expected {0} but got {1}", elementName.Value, elem.Name));
			}
			
			return elem;
		}

		protected override Stream GetGameSystemDataStream (ZipFile file)
		{
			return file.GetInputStream(file.FindEntry("data.systemx", true));
		}
		
		protected override GameSystem CreateGameSystemFromStream (ZipFile file, Stream dataStream)
		{
			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.SYSTEM_ELEMENT);
			LogNotifier.Debug(GetType(), "Create GameSystem");
			return gameSystemFactory.CreateSystemFromElement(file, elem);
		}
		
		protected override Stream GetRaceDataStream (ZipFile file)
		{
			return file.GetInputStream(file.FindEntry("data.racex", true));
		}
		
		protected override Race CreateRaceFromStream (ZipFile file, Stream dataStream)
		{
			XmlElement elem = GetRootElementFromStream(dataStream, WarFoundryXmlElementName.RACE_ELEMENT);
			LogNotifier.Debug(GetType(), "Create Race");
			return raceFactory.CreateRaceFromElement(file, elem);
		}

		protected override void CleanUpFileAsSupportedType(ZipFile typedFile)
		{
			typedFile.Close();
		}

		public override void CompleteLoading(IWarFoundryStagedLoadObject obj)
		{			
			LogNotifier.DebugFormat(GetType(), "Complete loading of {0} with ID {1}", obj.GetType().Name, obj.ID);
							
			if (obj is GameSystem)
			{
				gameSystemFactory.CompleteLoading((GameSystem)obj);
			}
			else if (obj is Race)
			{
				raceFactory.CompleteLoading((Race)obj);
			}
		}
	}
}