bool ParseHelperFoo::StartElementHandler(XmlParseMaster::SharedData* data, std::string name, Hashmap<std::string, std::string>& attributes)
	{
		if (!data)
		{
			throw std::exception("Shared data is null");
		}

		if (data->Is("SharedDataFoo"))
		{
			SharedDataFoo* reinterpereted = reinterpret_cast<SharedDataFoo*>(data);

			//Handle initializing the element itself
			reinterpereted->IncrementDepth();
			reinterpereted->mMap.Insert(std::pair<std::string, std::uint32_t>(name, 0xffffffff)); //Initialize to the max value of an unsigned int, indicating that the value hasn't been assigned yet			
			mElementStack.PushFront(name);//Put the current element into our stack


			//Handle attributes
			if (attributes.ContainsKey("name"))
			{
				reinterpereted->mName = (*(attributes.Find("name"))).second;
			}

			if (attributes.ContainsKey("style"))
			{
				reinterpereted->mStyle = (*(attributes.Find("style"))).second;
			}

			return true;
		}
		return false;
	}
	//Handle start elements
	bool XMLParseHelperExpression::StartElementHandler(XmlParseMaster::SharedData* data, std::string name, Hashmap<std::string, std::string>& attributes)
	{
		/**
		Requirements for starting a new expression action:
		1. Shared data must be SharedDataWorld
		2. Name of element must be 'action'
		3. Must contain a 'class' attribute
		4. Must contain a 'target' attribute
		5. Must contain a 'name' attribute
		6. Class type must be 'ActionExpression'
		*/

		SharedDataWorld* reinterpereted = data->As<SharedDataWorld>();
		if (reinterpereted != nullptr && name == actionString && attributes.ContainsKey(classString) && attributes.ContainsKey(nameString))
		{
			if (attributes.Find(classString)->second == "ActionExpression")
			{
				//Ensure that we have either an actionList or an entity that is going to contain this new actionExpression
				Scope* actionList = reinterpereted->GetAction();
				Scope* entity = reinterpereted->GetEntity();
				if (actionList != nullptr && actionList->Is("ActionList"))
				{
					//Create a new actionExpression with the factory from the actionlist
					ActionExpression* newAction = actionList->As<ActionList>()->CreateAction("ActionExpression", attributes.Find(nameString)->second)->As<ActionExpression>();
					reinterpereted->SetAction(newAction);
				}
				else if (entity != nullptr)
				{
					//Create a new actionExpression with the factory from the entity
					ActionExpression* newAction = entity->As<Entity>()->CreateAction("ActionExpression", attributes.Find(nameString)->second)->As<ActionExpression>();
					reinterpereted->SetAction(newAction);
				}
				else
				{
					return false;
				}
				reinterpereted->IncrementDepth();
				return true;
			}
		}
		return false;
	}
	bool XmlParseHelperTable::StartElementHandler(XmlParseMaster::SharedData& sharedData, const std::string& elementName, const Hashmap<std::string, std::string>& attributes)
	{
		SharedDataTable* sharedDataPtr = sharedData.As<SharedDataTable>();
		if (sharedDataPtr == nullptr)
			return false;

		if (elementName != ELEMENT_SCOPE)
			return false;

		if (!attributes.ContainsKey(ATTRIBUTE_NAME))
			throw std::exception("ClearScreen syntax for <scope>. Missing attribute: name");

		if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::SCOPE_START))
			throw std::exception("ClearScreen script syntax");
		bool transitionToStateRouter = sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::STATE_ROUTER);
		UNREFERENCED_PARAMETER(transitionToStateRouter);
		assert(transitionToStateRouter);

		sharedDataPtr->CurrentScopePtr =  &(sharedDataPtr->CurrentScopePtr->AppendScope(attributes[ATTRIBUTE_NAME]));

		return true;
	}
	bool XmlParseHelperSector::StartElementHandler(XmlParseMaster::SharedData& sharedData, const std::string& elementName, const Hashmap<std::string, std::string>& attributes)
	{
		SharedDataTable* sharedDataPtr = sharedData.As<SharedDataTable>();
		if (sharedDataPtr == nullptr)
			return false;

		if (elementName != ELEMENT_NAME)
			return false;

		if (!attributes.ContainsKey(ATTRIBUTE_NAME))
			throw std::exception("ClearScreen syntax for <sector>. Missing attribute: name");

		if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::SECTOR_START))
			throw std::exception("ClearScreen script syntax");
		bool transitionToStateRouter = sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::STATE_ROUTER);
		UNREFERENCED_PARAMETER(transitionToStateRouter);
		assert(transitionToStateRouter);

		assert(sharedDataPtr->CurrentScopePtr->Is(World::TypeIdClass()));
		World* world = static_cast<World*>(sharedDataPtr->CurrentScopePtr);

		sharedDataPtr->CurrentScopePtr = &(world->CreateSector(attributes[ATTRIBUTE_NAME]));
		return true;
	}
	bool XmlParseHelperPrimitives::StartElementHandler(XmlParseMaster::SharedData& sharedData, const std::string& elementName, const Hashmap<std::string, std::string>& attributes)
	{
		SharedDataTable* sharedDataPtr = sharedData.As<SharedDataTable>();
		if (sharedDataPtr == nullptr)
			return false;
		if (!mElementMetaData.ContainsKey(elementName))
			return false;

		if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::PRIMITIVE_START))
			throw std::exception("ClearScreen script syntax");

		if (attributes.ContainsKey("index"))
		{
			sscanf_s(attributes["index"].c_str(), "%u", &mIndex);
			mIndexAttributeSpecified = true;
		}
		else
		{
			mIndexAttributeSpecified = false;
		}

		// <integer name="variableName">
		if (attributes.ContainsKey("name"))
		{
			if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::NAME_START))
				throw std::exception("ClearScreen script syntax");
			if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::NAME_END))
				throw std::exception("ClearScreen script syntax");

			mCurrentDataName = attributes["name"];
			Datum& primitiveDatum = sharedDataPtr->CurrentScopePtr->Append(mCurrentDataName);
			primitiveDatum.SetType(mElementMetaData[elementName]);

			// <integer name="variableName" value="variableValue"/>
			if (attributes.ContainsKey("value"))
			{
				if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::VALUE_START))
					throw std::exception("ClearScreen script syntax");
				if (!sharedDataPtr->CheckStateTransition(SharedDataTable::ParserState::VALUE_END))
					throw std::exception("ClearScreen script syntax");
				
				std::uint32_t index = mIndex;
				if (!mIndexAttributeSpecified)
					index = (primitiveDatum.StorageType() == Datum::DatumStorageType::EXTERNAL) ? 0 : primitiveDatum.Size();

				if (primitiveDatum.Type() != Datum::DatumType::REFERENCE)
				{
					primitiveDatum.SetFromString(attributes["value"], index);
				}
				else
				{
					Datum* reference = World::ComplexSearch(attributes["value"], *sharedDataPtr->CurrentScopePtr);
					if (reference == nullptr)
					{
						std::stringstream str;
						str << "LNK2001: unresolved external symbol: " << attributes["value"] << " :P ";
						throw std::exception(str.str().c_str());
					}
					primitiveDatum.Set(reference, index);
				}
				mCurrentDataName = "";
			}
		}

		return true;
	}