/*
 * 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_MDC_H
#define _LOG4CXX_MDC_H

#include <log4cxx/log4cxx.h>
#include <log4cxx/logstring.h>
#include <map>

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

namespace log4cxx
{

/**
The MDC class is similar to the {@link log4cxx::NDC NDC} class except that it is
based on a map instead of a stack. It provides <em>mapped
diagnostic contexts</em>. A <em>Mapped Diagnostic Context</em>, or
MDC in short, is an instrument for distinguishing interleaved log
output from different sources. Log output is typically interleaved
when a server handles multiple clients near-simultaneously.
*/
class LOG4CXX_EXPORT MDC
{
	public:
		/** String to string stl map.
		*/
		typedef std::map<LogString, LogString> Map;

		/**
		 *  Places a key/value pair in the MDC for the current thread
		 *    which will be removed during the corresponding destructor.  Both
		 *    construction and destruction are expected to be on the same thread.
		 *    @param key key
		 *    @param value value.
		 */
		MDC(const std::string& key, const std::string& value);
		~MDC();

		/**
		* Put a context value (the <code>o</code> parameter) as identified
		* with the <code>key</code> parameter into the current thread's
		* context map.
		*
		* <p>If the current thread does not have a context map it is
		* created as a side effect.
		 *    @param key key
		 *    @param value value.
		*/
		static void put(const std::string& key, const std::string& value);
		/**
		* Put a context value (the <code>o</code> parameter) as identified
		* with the <code>key</code> parameter into the current thread's
		* context map.
		*
		* <p>If the current thread does not have a context map it is
		* created as a side effect.
		* */
		static void putLS(const LogString& key, const LogString& value);

		/**
		* Get the context identified by the <code>key</code> parameter.
		*
		*  <p>This method has no side effects.
		*  @param key key.
		*  @return value for key, empty if not set.
		* */
		static std::string get(const std::string& key);
		/**
		 *  Gets the context identified by the <code>key</code> parameter.
		 *  @param key context key.
		 *  @param dest destination to which value is appended.
		 *  @return true if key has associated value.
		 */
		static bool get(const LogString& key, LogString& dest);

		/**
		* Remove the the context identified by the <code>key</code>
		* parameter.
		*  @param key key.
		* @return value if key had been set, empty if not.
		*/
		static std::string remove(const std::string& key);
#if LOG4CXX_WCHAR_T_API
		/**
		 *  Places a key/value pair in the MDC for the current thread
		 *    which will be removed during the corresponding destructor.  Both
		 *    construction and destruction are expected to be on the same thread.
		 *    @param key key
		 *    @param value value.
		 */
		MDC(const std::wstring& key, const std::wstring& value);
		/**
		* Put a context value (the <code>o</code> parameter) as identified
		* with the <code>key</code> parameter into the current thread's
		* context map.
		*
		* <p>If the current thread does not have a context map it is
		* created as a side effect.
		 *    @param key key
		 *    @param value value.
		*/
		static void put(const std::wstring& key, const std::wstring& value);
		/**
		* Get the context identified by the <code>key</code> parameter.
		*
		*  <p>This method has no side effects.
		*  @param key key.
		*  @return value for key, empty if not set.
		* */
		static std::wstring get(const std::wstring& key);
		/**
		* Remove the the context identified by the <code>key</code>
		* parameter.
		*  @param key key.
		* @return value if key had been set, empty if not.
		*/
		static std::wstring remove(const std::wstring& key);
#endif
#if LOG4CXX_UNICHAR_API
		/**
		 *  Places a key/value pair in the MDC for the current thread
		 *    which will be removed during the corresponding destructor.  Both
		 *    construction and destruction are expected to be on the same thread.
		 *    @param key key
		 *    @param value value.
		 */
		MDC(const std::basic_string<UniChar>& key, const std::basic_string<UniChar>& value);
		/**
		* Put a context value (the <code>o</code> parameter) as identified
		* with the <code>key</code> parameter into the current thread's
		* context map.
		*
		* <p>If the current thread does not have a context map it is
		* created as a side effect.
		 *    @param key key
		 *    @param value value.
		*/
		static void put(const std::basic_string<UniChar>& key, const std::basic_string<UniChar>& value);
		/**
		* Get the context identified by the <code>key</code> parameter.
		*
		*  <p>This method has no side effects.
		*  @param key key.
		*  @return value for key, empty if not set.
		* */
		static std::basic_string<UniChar> get(const std::basic_string<UniChar>& key);
		/**
		* Remove the the context identified by the <code>key</code>
		* parameter.
		*  @param key key.
		* @return value if key had been set, empty if not.
		*/
		static std::basic_string<UniChar> remove(const std::basic_string<UniChar>& key);
#endif
#if LOG4CXX_CFSTRING_API
		/**
		 *  Places a key/value pair in the MDC for the current thread
		 *    which will be removed during the corresponding destructor.  Both
		 *    construction and destruction are expected to be on the same thread.
		 *    @param key key
		 *    @param value value.
		 */
		MDC(const CFStringRef& key, const CFStringRef& value);
		/**
		* Put a context value (the <code>o</code> parameter) as identified
		* with the <code>key</code> parameter into the current thread's
		* context map.
		*
		* <p>If the current thread does not have a context map it is
		* created as a side effect.
		 *    @param key key
		 *    @param value value.
		*/
		static void put(const CFStringRef& key, const CFStringRef& value);
		/**
		* Get the context identified by the <code>key</code> parameter.
		*
		*  <p>This method has no side effects.
		*  @param key key.
		*  @return value for key, empty if not set.
		* */
		static CFStringRef get(const CFStringRef& key);
		/**
		* Remove the the context identified by the <code>key</code>
		* parameter.
		*  @param key key.
		* @return value if key had been set, empty if not.
		*/
		static CFStringRef remove(const CFStringRef& key);
#endif
		/**
		* Remove the the context identified by the <code>key</code>
		* parameter.
		*  @param key key.
		* @param prevValue buffer to which previous value is appended.
		* @return true if key existed in MDC.
		*/
		static bool remove(const LogString& key, LogString& prevValue);

		/**
		* Clear all entries in the MDC.
		*/
		static void clear();

	private:
		MDC(const MDC&);
		MDC& operator=(const MDC&);
		LogString key;
}; // class MDC;
}  // namespace log4cxx

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


#endif // _LOG4CXX_MDC_H
