/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _LOG4CXX_SPI_LOGGING_EVENT_H
#define _LOG4CXX_SPI_LOGGING_EVENT_H

#if defined(_MSC_VER)
	#pragma warning (push)
	#pragma warning ( disable: 4231 4251 4275 4786 )
#endif



#include <log4cxx/helpers/objectptr.h>
#include <log4cxx/logstring.h>
#include <time.h>
#include <log4cxx/logger.h>
#include <log4cxx/mdc.h>
#include <log4cxx/spi/location/locationinfo.h>
#include <vector>


namespace log4cxx
{
namespace helpers
{
class ObjectOutputStream;
}

namespace spi
{
LOG4CXX_LIST_DEF(KeySet, LogString);

/**
The internal representation of logging events. When an affirmative
decision is made to log then a <code>LoggingEvent</code> instance
is created. This instance is passed around to the different log4cxx
components.

<p>This class is of concern to those wishing to extend log4cxx.
*/
class LOG4CXX_EXPORT LoggingEvent :
	public virtual helpers::ObjectImpl
{
	public:
		DECLARE_LOG4CXX_OBJECT(LoggingEvent)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(LoggingEvent)
		END_LOG4CXX_CAST_MAP()

		typedef spi::KeySet KeySet;

		/** For serialization only
		*/
		LoggingEvent();

		/**
		Instantiate a LoggingEvent from the supplied parameters.

		<p>Except timeStamp all the other fields of
		<code>LoggingEvent</code> are filled when actually needed.
		<p>
		@param logger The logger of this event.
		@param level The level of this event.
		@param message  The message of this event.
		@param location location of logging request.
		*/
		LoggingEvent(const LogString& logger,
			const LevelPtr& level,   const LogString& message,
			const log4cxx::spi::LocationInfo& location);

		~LoggingEvent();

		/** Return the level of this event. */
		inline const LevelPtr& getLevel() const
		{
			return level;
		}

		/**  Return the name of the logger. */
		inline const LogString& getLoggerName() const
		{
			return logger;
		}

		/** Return the message for this logging event. */
		inline const LogString& getMessage() const
		{
			return message;
		}

		/** Return the message for this logging event. */
		inline const LogString& getRenderedMessage() const
		{
			return message;
		}

		/**Returns the time when the application started,
		in microseconds elapsed since 01.01.1970.
		*/
		static log4cxx_time_t getStartTime();

		/** Return the threadName of this event. */
		inline const LogString& getThreadName() const
		{
			return threadName;
		}

		/** The number of microseconds elapsed from 01.01.1970 until logging event
		 was created. */
		inline log4cxx_time_t getTimeStamp() const
		{
			return timeStamp;
		}

		/* Return the file where this log statement was written. */
		inline const log4cxx::spi::LocationInfo& getLocationInformation() const
		{
			return locationInfo;
		}

		/**
		* This method appends the NDC for this event to passed string. It will return the
		* correct content even if the event was generated in a different
		* thread or even on a different machine. The NDC#get method
		* should <em>never</em> be called directly.
		*
		* @param dest destination for NDC, unchanged if NDC is not set.
		* @return true if NDC is set.
		*/
		bool getNDC(LogString& dest) const;

		/**
		 *  Writes the content of the LoggingEvent
		 *  in a format compatible with log4j's serialized form.
		 */
		void write(helpers::ObjectOutputStream& os, helpers::Pool& p) const;

		/**
		* Appends the the context corresponding to the <code>key</code> parameter.
		* If there is a local MDC copy, possibly because we are in a logging
		* server or running inside AsyncAppender, then we search for the key in
		* MDC copy, if a value is found it is returned. Otherwise, if the search
		* in MDC copy returns an empty result, then the current thread's
		* <code>MDC</code> is used.
		*
		* <p>
		* Note that <em>both</em> the local MDC copy and the current thread's MDC
		* are searched.
		* </p>
		* @param key key.
		* @param dest string to which value, if any, is appended.
		* @return true if key had a corresponding value.
		*/
		bool getMDC(const LogString& key, LogString& dest) const;

		/**
		* Returns the set of of the key values in the MDC for the event.
		* The returned set is unmodifiable by the caller.
		*
		* @return Set an unmodifiable set of the MDC keys.
		*
		*/
		KeySet getMDCKeySet() const;

		/**
		Obtain a copy of this thread's MDC prior to serialization
		or asynchronous logging.
		*/
		void getMDCCopy() const;

		/**
		* Return a previously set property.
		* @param key key.
		* @param dest string to which value, if any, is appended.
		* @return true if key had a corresponding value.
		*/
		bool getProperty(const LogString& key, LogString& dest) const;
		/**
		* Returns the set of of the key values in the properties
		* for the event. The returned set is unmodifiable by the caller.
		*
		* @return Set an unmodifiable set of the property keys.
		*/
		KeySet getPropertyKeySet() const;

		/**
		* Set a string property using a key and a string value.  since 1.3
		*/
		void setProperty(const LogString& key, const LogString& value);

	private:
		/**
		* The logger of the logging event.
		**/
		LogString logger;

		/** level of logging event. */
		LevelPtr level;

		/** The nested diagnostic context (NDC) of logging event. */
		mutable LogString* ndc;

		/** The mapped diagnostic context (MDC) of logging event. */
		mutable MDC::Map* mdcCopy;

		/**
		* A map of String keys and String values.
		*/
		std::map<LogString, LogString>* properties;

		/** Have we tried to do an NDC lookup? If we did, there is no need
		*  to do it again.  Note that its value is always false when
		*  serialized. Thus, a receiving SocketNode will never use it's own
		*  (incorrect) NDC. See also writeObject method.
		*/
		mutable bool ndcLookupRequired;

		/**
		* Have we tried to do an MDC lookup? If we did, there is no need to do it
		* again.  Note that its value is always false when serialized. See also
		* the getMDC and getMDCCopy methods.
		*/
		mutable bool mdcCopyLookupRequired;

		/** The application supplied message of logging event. */
		LogString message;


		/** The number of microseconds elapsed from 01.01.1970 until logging event
		 was created. */
		log4cxx_time_t timeStamp;

		/** The is the location where this log statement was written. */
		const log4cxx::spi::LocationInfo locationInfo;


		/** The identifier of thread in which this logging event
		was generated.
		*/
		const LogString threadName;

		//
		//   prevent copy and assignment
		//
		LoggingEvent(const LoggingEvent&);
		LoggingEvent& operator=(const LoggingEvent&);
		static const LogString getCurrentThreadName();

		static void writeProlog(log4cxx::helpers::ObjectOutputStream& os, log4cxx::helpers::Pool& p);

};

LOG4CXX_PTR_DEF(LoggingEvent);
LOG4CXX_LIST_DEF(LoggingEventList, LoggingEventPtr);
}
}

#if defined(_MSC_VER)
	#pragma warning (pop)
#endif


#endif //_LOG4CXX_SPI_LOGGING_EVENT_H
