//
// Copyright (c) 2009-2010 Ronald Kluth
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

/**
 * @file XmlStreamWriter.h
 * @author Ronald Kluth
 * @date 2010/03/26
 * @brief Declaration and implementation of class template XmlStreamWriter
 * @since 0.1
 */

#ifndef LOG_OUTPUT_XMLSTREAMWRITER_INCLUDED
#define LOG_OUTPUT_XMLSTREAMWRITER_INCLUDED

#include "../Record.h"
#include "XmlWriter.h"

#ifdef _MSC_VER
#include <memory>
#else
#include <tr1/memory>
#endif

namespace Log {

/**
 * @brief Simple log consumer implementation that writes records to an XML stream
 * @tparam InfoListT List of info types to retrieve from log records
 *
 * This class is a very simple XML output component. The @c consume method
 * simply transforms each record into XML format by calling methods
 * of the base class @c XmlWriter. Info type elements are added automatically,
 * according to the type list provided as template parameter.
 *
 * @note Be aware that string names of info types should not contain white space
 * because these names are used  as XML tag names.
 */
template < typename InfoListT = Detail::NullList >
class XmlStreamWriter : public XmlWriter
{
public:
	/// List of info types to retrieve from log records
	typedef InfoListT InfoListType;
	/// Pointer type to manage instances
	typedef std::tr1::shared_ptr< XmlStreamWriter< InfoListType > > Ptr;

	/// Creation of XmlStreamWriter objects wrapped in a @c shared_ptr
	static Ptr create( std::ostream& os, unsigned int indent = 0 )
	{
		return Ptr( new XmlStreamWriter( os, indent ) );
	}

	/// Destruction
	virtual ~XmlStreamWriter()
	{
	}

	/// Implementation of the log consumer interface, transforms records to XML
	virtual void consume( const Log::ChannelId channelId, const Record& record )
	{
		if( os_.good() )
		{
			XmlWriter::startElement( os_, indent_, "record" );
			os_ << std::endl;
			if( ! record.getText().empty() )
			{
				XmlWriter::writeElement( os_, indent_ + indent_, "text", record.getText() );
			}
			XmlWriter::StreamInfoElements addInfo( os_, indent_ + indent_ );
			record.iterateInfo< InfoListType >( addInfo );
			XmlWriter::closeElement( os_, indent_, "record" );
		}
	}
private:
	/// Reference to the stream the log information is written to
	std::ostream& os_;
	/// Stores the number of spaces to be prepended before each line
	unsigned int indent_;
	
private:
	/// Construction private, use create() instead
	XmlStreamWriter( std::ostream& os, unsigned int indent = 0 )
	:	os_( os )
	,	indent_( indent )
	{}
};

} // namespace Log

#endif /* LOG_OUTPUT_XMLSTREAMWRITER_INCLUDED */
