Skip to content
Snippets Groups Projects
xmlApi.cpp 7.23 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "xmlApi.hpp"
    
    namespace core {
    
    ext::map < std::string, std::unique_ptr < xmlApi < object::Object >::GroupParser > > & xmlApi < object::Object >::parseFunctions ( ) {
    	static ext::map < std::string, std::unique_ptr < GroupParser > > res;
    
    	return res;
    }
    
    ext::map < std::string, std::unique_ptr < xmlApi < object::Object >::GroupComposer > > & xmlApi < object::Object >::composeFunctions ( ) {
    	static ext::map < std::string, std::unique_ptr < GroupComposer > > res;
    
    	return res;
    }
    
    
    object::Object xmlApi < object::Object >::parseRef ( xmlApiInputContext & input ) {
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "Ref" );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ATTRIBUTE, "id" );
    	int id = ext::from_string < int > ( sax::FromXMLParserHelper::popTokenData ( input, sax::Token::TokenType::CHARACTER ) );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ATTRIBUTE, "id" );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "Ref" );
    	ext::map < int, object::Object >::iterator elem = input.idToInstance ( ).find ( id );
    
    	if ( elem == input.idToInstance ( ).end ( ) ) {
    		common::Streams::err << input.idToInstance ( ) << std::endl;
    		throw exception::CommonException ( "XML Inconsistent ( id not found " + ext::to_string ( id ) + " )" );
    	}
    
    	return elem->second;
    }
    
    object::Object xmlApi < object::Object >::parseUnique ( xmlApiInputContext & input ) {
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "UniqueObject" );
    	object::Object baseObject ( parse ( input ) );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "id" );
    	unsigned id = ext::from_string < unsigned > ( sax::FromXMLParserHelper::popTokenData ( input, sax::Token::TokenType::CHARACTER ) );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "id" );
    	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "UniqueObject" );
    	baseObject += id;
    	return baseObject;
    }
    
    object::Object xmlApi < object::Object >::parseObject ( xmlApiInputContext & input, const std::string & tagName ) {
    	typename ext::map < std::string, std::unique_ptr < GroupParser > >::iterator callback = parseFunctions ( ).find ( tagName );
    
    	if ( callback == parseFunctions ( ).end ( ) ) throw exception::CommonException ( "Parse callback for " + tagName + " tag not registered." );
    
    	return callback->second->parse ( input );
    }
    
    object::Object xmlApi < object::Object >::parse ( xmlApiInputContext & input, const std::string & tagName ) {
    	if ( /* common::GlobalData::optimizeXml && */ tagName == "Ref" ) {
    		return parseRef ( input );
    	} else if ( tagName == "UniqueObject" ) {
    		return parseUnique ( input );
    	} else {
    		return parseObject ( input, tagName );
    	}
    }
    
    object::Object xmlApi < object::Object >::parse ( ext::deque < sax::Token >::iterator & data ) {
    
    	xmlApiInputContext & input = static_cast < xmlApiInputContext & > ( data );
    
    	sax::FromXMLParserHelper::skipAttributes ( input, sax::Token::TokenType::START_ELEMENT );
    
    
    	const std::string & tagName = sax::FromXMLParserHelper::getTokenData ( static_cast < ext::deque < sax::Token >::iterator & > ( input ), sax::Token::TokenType::START_ELEMENT );
    
    
    	/* find out if this is a base for reference */
    	bool ref = sax::FromXMLParserHelper::isToken ( input + 1, sax::Token::TokenType::START_ATTRIBUTE, "ref" );
    	int id = 0;
    	if ( ref ) {
    		ext::deque < sax::Token >::iterator tmp = input + 2;
    		id = ext::from_string < unsigned > ( sax::FromXMLParserHelper::popTokenData ( tmp, sax::Token::TokenType::CHARACTER ) );
    	}
    
    	object::Object res = parse ( input, tagName );
    
    	/* if object is a base of reference, register it */
    	if ( ref )
    		input.idToInstance ( ).insert ( std::make_pair ( id, res ) );
    
    	return res;
    }
    
    bool xmlApi < object::Object >::first ( const ext::deque < sax::Token >::const_iterator & input ) {
    	const std::string & tagName = sax::FromXMLParserHelper::getTokenData ( input, sax::Token::TokenType::START_ELEMENT );
    
    	if ( tagName == "Ref" ) return true;
    
    	typename ext::map < std::string, std::unique_ptr < GroupParser > >::iterator callback = parseFunctions ( ).find ( tagName );
    
    	if ( callback == parseFunctions ( ).end ( ) ) return false;
    
    	return true;
    }
    
    std::string xmlApi < object::Object >::xmlTagName ( ) {
    	std::string target = ext::to_string < object::Object > ( );
    
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	throw exception::CommonException ( "Type " + target + " does not have xmlTagName." );
    
    }
    
    void xmlApi < object::Object >::composeRef ( xmlApiOutputContext & output, typename ext::map < object::Object, int >::iterator & elem ) {
    	output.emplace_back ( "Ref", sax::Token::TokenType::START_ELEMENT );
    	output.emplace_back ( "id", sax::Token::TokenType::START_ATTRIBUTE );
    	output.emplace_back ( ext::to_string ( elem->second ), sax::Token::TokenType::CHARACTER );
    	output.emplace_back ( "id", sax::Token::TokenType::END_ATTRIBUTE );
    	output.emplace_back ( "Ref", sax::Token::TokenType::END_ELEMENT );
    }
    
    void xmlApi < object::Object >::composeUnique ( xmlApiOutputContext & output, const object::Object & data ) {
    	output.emplace_back ( "UniqueObject", sax::Token::TokenType::START_ELEMENT );
    	composeObject ( output, data );
    	output.emplace_back ( "id", sax::Token::TokenType::START_ELEMENT );
    	output.emplace_back ( ext::to_string ( data.getId ( ) ), sax::Token::TokenType::CHARACTER );
    	output.emplace_back ( "id", sax::Token::TokenType::END_ELEMENT );
    	output.emplace_back ( "UniqueObject", sax::Token::TokenType::END_ELEMENT );
    }
    
    void xmlApi < object::Object >::composeObject ( xmlApiOutputContext & output, const object::Object & data ) {
    	const auto & content = data.getData ( );
    	std::string type = ext::to_string ( ext::type_index ( typeid ( content ) ) );
    	typename ext::map < std::string, std::unique_ptr < GroupComposer > >::iterator callback = composeFunctions ( ).find ( type );
    
    	if ( callback == composeFunctions ( ).end ( ) ) throw exception::CommonException ( "Compose callback for " + type + " tag not registered." );
    
    	/* encode referenced object */
    	callback->second->compose ( output, data );
    }
    
    void xmlApi < object::Object >::compose ( ext::deque < sax::Token > & data, const object::Object & object ) {
    	xmlApiOutputContext & output = ( xmlApiOutputContext & ) data;
    
    	typename ext::map < object::Object, int >::iterator elem = output.instanceToId ( ).find ( object );
    
    	/* get current position in token stream */
    	size_t pos = output.size();
    	int id = 0;
    	if ( common::GlobalData::optimizeXml && elem == output.instanceToId ( ).end ( ) ) {
    		id = output.idMax ( )++;
    	}
    
    	if ( common::GlobalData::optimizeXml && elem != output.instanceToId ( ).end ( ) ) {
    		composeRef ( output, elem );
    	} else if ( object.getId ( ) != 0 ) {
    		composeUnique ( output, object );
    	} else {
    		composeObject ( output, object );
    	}
    
    	/* emplace referenced attribute */
    	if ( common::GlobalData::optimizeXml && elem == output.instanceToId ( ).end ( ) ) {
    		output.emplace ( output.begin ( ) + pos + 1, "ref", sax::Token::TokenType::START_ATTRIBUTE );
    		output.emplace ( output.begin ( ) + pos + 2, ext::to_string ( id ), sax::Token::TokenType::CHARACTER );
    		output.emplace ( output.begin ( ) + pos + 3, "ref", sax::Token::TokenType::END_ATTRIBUTE );
    
    		output.instanceToId ( ).insert ( std::make_pair ( object, id ) );
    	}
    }