/*
 * Author: Radovan Cerveny
 */

#include <sax/FromXMLParserHelper.h>
#include "MeasurementResults.hpp"
#include <exception/CommonException.h>

namespace core {

measurements::MeasurementResults xmlApi < measurements::MeasurementResults >::parse ( ext::deque < sax::Token >::iterator & input ) {
	measurements::MeasurementResults mr;

	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_RESULTS_TAG );

	parseRootMeasurementFrame ( mr, input );

	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_RESULTS_TAG );

	return mr;
}

bool xmlApi < measurements::MeasurementResults >::first ( const ext::deque < sax::Token >::const_iterator & input ) {
	return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName ( ) );
}

std::string xmlApi < measurements::MeasurementResults >::xmlTagName ( ) {
	return MEASUREMENT_RESULTS_TAG;
}

void xmlApi < measurements::MeasurementResults >::compose ( ext::deque < sax::Token > & output, const measurements::MeasurementResults & input ) {
	output.emplace_back ( MEASUREMENT_RESULTS_TAG, sax::Token::TokenType::START_ELEMENT );

	xmlApi < measurements::MeasurementResults >::composeMeasurementFrames ( output, 0, input.frames );

	output.emplace_back ( MEASUREMENT_RESULTS_TAG, sax::Token::TokenType::END_ELEMENT );
}

void xmlApi < measurements::MeasurementResults >::composeMeasurementFrames ( ext::deque < sax::Token > & tokens, unsigned idx, const measurements::stealth_vector < measurements::MeasurementFrame > & frames ) {

	const measurements::MeasurementFrame & frame = frames[idx];

	tokens.emplace_back ( MEASUREMENT_FRAME_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( MEASUREMENT_FRAME_NAME_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( measurements::to_string ( frame.name ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEASUREMENT_FRAME_NAME_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( MEASUREMENT_FRAME_TYPE_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( measurements::to_string ( frame.type ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEASUREMENT_FRAME_TYPE_TAG, sax::Token::TokenType::END_ELEMENT );

	if ( frame.type != measurements::Type::ROOT ) {
		composeTimeDataFrame ( tokens, idx, frames );
		composeMemoryDataFrame ( tokens, idx, frames );
		composeCounterDataFrame ( tokens, idx, frames );
	}

	tokens.emplace_back ( MEASUREMENT_SUBFRAMES_TAG, sax::Token::TokenType::START_ELEMENT );

	for ( unsigned subIdx : frame.subIdxs )
		composeMeasurementFrames ( tokens, subIdx, frames );

	tokens.emplace_back ( MEASUREMENT_SUBFRAMES_TAG, sax::Token::TokenType::END_ELEMENT );

	tokens.emplace_back ( MEASUREMENT_FRAME_TAG, sax::Token::TokenType::END_ELEMENT );
}

void xmlApi < measurements::MeasurementResults >::composeTimeDataFrame ( ext::deque < sax::Token > & tokens, unsigned idx, const measurements::stealth_vector < measurements::MeasurementFrame > & frames ) {
	const measurements::TimeDataFrame & frame = frames[idx].time;

	tokens.emplace_back ( TIME_DATA_FRAME_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( TIME_DATA_FRAME_DURATION_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.duration.count ( ) ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( TIME_DATA_FRAME_DURATION_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( TIME_DATA_FRAME_IN_FRAME_DURATION_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.inFrameDuration.count ( ) ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( TIME_DATA_FRAME_IN_FRAME_DURATION_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( TIME_DATA_FRAME_TAG, sax::Token::TokenType::END_ELEMENT );
}

void xmlApi < measurements::MeasurementResults >::composeMemoryDataFrame ( ext::deque < sax::Token > & tokens, unsigned idx, const measurements::stealth_vector < measurements::MeasurementFrame > & frames ) {
	const measurements::MemoryDataFrame & frame = frames[idx].memory;

	tokens.emplace_back ( MEMORY_DATA_FRAME_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.startHeapUsage ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.endHeapUsage ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.highWatermark ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG, sax::Token::TokenType::START_ELEMENT );
	tokens.emplace_back ( ext::to_string ( frame.inFrameHighWatermark ), sax::Token::TokenType::CHARACTER );
	tokens.emplace_back ( MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG, sax::Token::TokenType::END_ELEMENT );
	tokens.emplace_back ( MEMORY_DATA_FRAME_TAG, sax::Token::TokenType::END_ELEMENT );
}

void xmlApi < measurements::MeasurementResults >::composeCounterDataFrame ( ext::deque < sax::Token > & tokens, unsigned idx, const measurements::stealth_vector < measurements::MeasurementFrame > & frames ) {
	const measurements::CounterDataFrame & cdf = frames[idx].counter;

	tokens.emplace_back ( COUNTER_DATA_FRAME_TAG, sax::Token::TokenType::START_ELEMENT );

	tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTERS_TAG, sax::Token::TokenType::START_ELEMENT );

	for ( const auto & elem : cdf.counters ) {
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_NAME_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( measurements::to_string ( elem.first ), sax::Token::TokenType::CHARACTER );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_NAME_TAG, sax::Token::TokenType::END_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_VALUE_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( ext::to_string ( elem.second ), sax::Token::TokenType::CHARACTER );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_VALUE_TAG, sax::Token::TokenType::END_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_TAG, sax::Token::TokenType::END_ELEMENT );
	}

	tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTERS_TAG, sax::Token::TokenType::END_ELEMENT );

	tokens.emplace_back ( COUNTER_DATA_FRAME_IN_FRAME_COUNTERS_TAG, sax::Token::TokenType::START_ELEMENT );

	for ( const auto & elem : cdf.inFrameCounters ) {
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_NAME_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( measurements::to_string ( elem.first ), sax::Token::TokenType::CHARACTER );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_NAME_TAG, sax::Token::TokenType::END_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_VALUE_TAG, sax::Token::TokenType::START_ELEMENT );
		tokens.emplace_back ( ext::to_string ( elem.second ), sax::Token::TokenType::CHARACTER );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_VALUE_TAG, sax::Token::TokenType::END_ELEMENT );
		tokens.emplace_back ( COUNTER_DATA_FRAME_COUNTER_TAG, sax::Token::TokenType::END_ELEMENT );
	}

	tokens.emplace_back ( COUNTER_DATA_FRAME_IN_FRAME_COUNTERS_TAG, sax::Token::TokenType::END_ELEMENT );

	tokens.emplace_back ( COUNTER_DATA_FRAME_TAG, sax::Token::TokenType::END_ELEMENT );
}

void xmlApi < measurements::MeasurementResults >::parseRootMeasurementFrame ( measurements::MeasurementResults & mr, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_TAG );

	mr.frames.emplace_back ( "Root", measurements::Type::ROOT, 0 );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == MEASUREMENT_FRAME_NAME_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_NAME_TAG );
			sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_NAME_TAG );
		} else if ( data == MEASUREMENT_FRAME_TYPE_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_TYPE_TAG );
			sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_TYPE_TAG );
		} else if ( data == MEASUREMENT_SUBFRAMES_TAG ) {

			parseSubframes ( 0, mr, iter );
		} else {
			break;
		}
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseSubframes ( unsigned parentIdx, measurements::MeasurementResults & mr, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_SUBFRAMES_TAG );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == MEASUREMENT_FRAME_TAG )
			parseMeasurementFrame ( parentIdx, mr, iter );
		else
			break;
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_SUBFRAMES_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseMeasurementFrame ( unsigned parentIdx, measurements::MeasurementResults & mr, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_TAG );

	unsigned mfIdx = mr.frames.size ( );

	mr.frames.emplace_back ( "Root", measurements::Type::ROOT, parentIdx );
	measurements::MeasurementFrame & mf = mr.frames.back ( );

	mr.frames[parentIdx].subIdxs.push_back ( mfIdx );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == MEASUREMENT_FRAME_NAME_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_NAME_TAG );
			mf.name = measurements::stealthStringFromString ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_NAME_TAG );
		} else if ( data == MEASUREMENT_FRAME_TYPE_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEASUREMENT_FRAME_TYPE_TAG );
			mf.type = measurements::measurementTypeFromString ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_TYPE_TAG );
		} else if ( data == TIME_DATA_FRAME_TAG ) {
			parseTimeDataFrame ( mf, iter );
		} else if ( data == MEMORY_DATA_FRAME_TAG ) {
			parseMemoryDataFrame ( mf, iter );
		} else if ( data == COUNTER_DATA_FRAME_TAG ) {
			parseCounterDataFrame ( mf, iter );
		} else if ( data == MEASUREMENT_SUBFRAMES_TAG ) {
			parseSubframes ( mfIdx, mr, iter );
		} else {
			break;
		}
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEASUREMENT_FRAME_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseTimeDataFrame ( measurements::MeasurementFrame & mf, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, TIME_DATA_FRAME_TAG );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == TIME_DATA_FRAME_DURATION_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, TIME_DATA_FRAME_DURATION_TAG );
			mf.time.duration = measurements::TimeDataFrame::value_type ( valueTypeFromString < measurements::TimeDataFrame::value_type::rep > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, TIME_DATA_FRAME_DURATION_TAG );
		} else if ( data == TIME_DATA_FRAME_IN_FRAME_DURATION_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, TIME_DATA_FRAME_IN_FRAME_DURATION_TAG );
			mf.time.inFrameDuration = measurements::TimeDataFrame::value_type ( valueTypeFromString < measurements::TimeDataFrame::value_type::rep > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, TIME_DATA_FRAME_IN_FRAME_DURATION_TAG );
		} else {
			break;
		}
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, TIME_DATA_FRAME_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseMemoryDataFrame ( measurements::MeasurementFrame & mf, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEMORY_DATA_FRAME_TAG );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG );
			mf.memory.startHeapUsage = valueTypeFromString < measurements::MemoryDataFrame::value_type > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG );
		} else if ( data == MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG );
			mf.memory.endHeapUsage = valueTypeFromString < measurements::MemoryDataFrame::value_type > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG );
		} else if ( data == MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG );
			mf.memory.highWatermark = valueTypeFromString < measurements::MemoryDataFrame::value_type > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG );
		} else if ( data == MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG );
			mf.memory.inFrameHighWatermark = valueTypeFromString < measurements::MemoryDataFrame::value_type > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG );
		} else {
			break;
		}
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, MEMORY_DATA_FRAME_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseCounterDataFrame ( measurements::MeasurementFrame & mf, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, COUNTER_DATA_FRAME_TAG );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == COUNTER_DATA_FRAME_COUNTERS_TAG )
			parseCounterDataFrameCounters ( COUNTER_DATA_FRAME_COUNTERS_TAG, mf.counter.counters, iter );
		else if ( data == COUNTER_DATA_FRAME_IN_FRAME_COUNTERS_TAG )
			parseCounterDataFrameCounters ( COUNTER_DATA_FRAME_IN_FRAME_COUNTERS_TAG, mf.counter.inFrameCounters, iter );
		else
			break;
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, COUNTER_DATA_FRAME_TAG );
}

void xmlApi < measurements::MeasurementResults >::parseCounterDataFrameCounters ( const std::string & tag, measurements::stealth_map < measurements::stealth_string, measurements::CounterHint::value_type > & counters, ext::deque < sax::Token >::iterator & iter ) {
	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, tag );

	for ( ; ; ) {
		if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

		std::string data = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

		if ( data == COUNTER_DATA_FRAME_COUNTER_TAG ) {
			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, COUNTER_DATA_FRAME_COUNTER_TAG );

			measurements::stealth_string counterName;
			measurements::CounterHint::value_type counterValue = { };

			for ( ; ; ) {
				if ( !sax::FromXMLParserHelper::isTokenType ( iter, sax::Token::TokenType::START_ELEMENT ) ) break;

				std::string counterData = sax::FromXMLParserHelper::getTokenData ( iter, sax::Token::TokenType::START_ELEMENT );

				if ( counterData == COUNTER_DATA_FRAME_COUNTER_NAME_TAG ) {
					sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, COUNTER_DATA_FRAME_COUNTER_NAME_TAG );
					counterName = measurements::stealthStringFromString ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
					sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, COUNTER_DATA_FRAME_COUNTER_NAME_TAG );
				} else if ( counterData == COUNTER_DATA_FRAME_COUNTER_VALUE_TAG ) {
					sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::START_ELEMENT, COUNTER_DATA_FRAME_COUNTER_VALUE_TAG );
					counterValue = valueTypeFromString < measurements::CounterHint::value_type > ( sax::FromXMLParserHelper::popTokenData ( iter, sax::Token::TokenType::CHARACTER ) );
					sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, COUNTER_DATA_FRAME_COUNTER_VALUE_TAG );
				} else {
					break;
				}
			}

			sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, COUNTER_DATA_FRAME_COUNTER_TAG );

			counters[counterName] = counterValue;

		} else {
			break;
		}
	}

	sax::FromXMLParserHelper::popToken ( iter, sax::Token::TokenType::END_ELEMENT, tag );
}

template < typename T >
T xmlApi < measurements::MeasurementResults >::valueTypeFromString ( const std::string & str ) {
	std::istringstream iss ( str );
	T val;

	iss >> val;
	return val;
}

std::string xmlApi < measurements::MeasurementResults >::MEASUREMENT_RESULTS_TAG = "MeasurementResults";

std::string xmlApi < measurements::MeasurementResults >::MEASUREMENT_FRAME_TAG = "MeasurementFrame";
std::string xmlApi < measurements::MeasurementResults >::MEASUREMENT_FRAME_NAME_TAG = "Name";
std::string xmlApi < measurements::MeasurementResults >::MEASUREMENT_FRAME_TYPE_TAG = "Type";

std::string xmlApi < measurements::MeasurementResults >::MEASUREMENT_SUBFRAMES_TAG = "SubFrames";

std::string xmlApi < measurements::MeasurementResults >::TIME_DATA_FRAME_TAG = "TimeData";
std::string xmlApi < measurements::MeasurementResults >::TIME_DATA_FRAME_DURATION_TAG = "Duration";
std::string xmlApi < measurements::MeasurementResults >::TIME_DATA_FRAME_IN_FRAME_DURATION_TAG = "InFrameDuration";

std::string xmlApi < measurements::MeasurementResults >::MEMORY_DATA_FRAME_TAG = "MemoryData";
std::string xmlApi < measurements::MeasurementResults >::MEMORY_DATA_FRAME_START_HEAP_USAGE_TAG = "StartHeapUsage";
std::string xmlApi < measurements::MeasurementResults >::MEMORY_DATA_FRAME_END_HEAP_USAGE_TAG = "EndHeapUsage";
std::string xmlApi < measurements::MeasurementResults >::MEMORY_DATA_FRAME_HIGH_WATERMARK_TAG = "HighWatermark";
std::string xmlApi < measurements::MeasurementResults >::MEMORY_DATA_FRAME_IN_FRAME_HIGH_WATERMARK_TAG = "InFrameHighWatermark";

std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_TAG = "CounterData";
std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_COUNTERS_TAG = "Counters";
std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_IN_FRAME_COUNTERS_TAG = "InFrameCounters";
std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_COUNTER_TAG = "Counter";
std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_COUNTER_NAME_TAG	= "Name";
std::string xmlApi < measurements::MeasurementResults >::COUNTER_DATA_FRAME_COUNTER_VALUE_TAG = "Value";

}
