/*
 * 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_APPENDER_SKELETON_H
#define _LOG4CXX_APPENDER_SKELETON_H

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


#include <log4cxx/appender.h>
#include <log4cxx/layout.h>
#include <log4cxx/spi/errorhandler.h>
#include <log4cxx/spi/filter.h>
#include <log4cxx/helpers/objectimpl.h>
#include <log4cxx/helpers/mutex.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/level.h>


namespace log4cxx
{
/**
*  Implementation base class for all appenders.
*
*  This class provides the code for common functionality, such as
*  support for threshold filtering and support for general filters.
* */
class LOG4CXX_EXPORT AppenderSkeleton :
	public virtual Appender,
	public virtual helpers::ObjectImpl
{
	protected:
		/** The layout variable does not need to be set if the appender
		implementation has its own layout. */
		LayoutPtr layout;

		/** Appenders are named. */
		LogString name;

		/**
		There is no level threshold filtering by default.  */
		LevelPtr threshold;

		/**
		It is assumed and enforced that errorHandler is never null.
		*/
		spi::ErrorHandlerPtr errorHandler;

		/** The first filter in the filter chain. Set to <code>null</code>
		initially. */
		spi::FilterPtr headFilter;

		/** The last filter in the filter chain. */
		spi::FilterPtr tailFilter;

		/**
		Is this appender closed?
		*/
		bool closed;

		log4cxx::helpers::Pool pool;
		mutable SHARED_MUTEX mutex;

		/**
		Subclasses of <code>AppenderSkeleton</code> should implement this
		method to perform actual logging. See also AppenderSkeleton::doAppend
		method.
		*/
		virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) = 0;

		void doAppendImpl(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);

	public:
		DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderSkeleton)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(AppenderSkeleton)
		LOG4CXX_CAST_ENTRY(Appender)
		LOG4CXX_CAST_ENTRY(spi::OptionHandler)
		END_LOG4CXX_CAST_MAP()

		AppenderSkeleton();
		AppenderSkeleton(const LayoutPtr& layout);

		void addRef() const;
		void releaseRef() const;

		/**
		Finalize this appender by calling the derived class'
		<code>close</code> method.
		*/
		void finalize();

		/**
		Derived appenders should override this method if option structure
		requires it.
		*/
		virtual void activateOptions(log4cxx::helpers::Pool& /* pool */) {}
		virtual void setOption(const LogString& option, const LogString& value);

		/**
		Add a filter to end of the filter list.
		*/
		void addFilter(const spi::FilterPtr& newFilter) ;

	public:
		/**
		Clear the filters chain.
		*/
		void clearFilters();

		/**
		Return the currently set spi::ErrorHandler for this
		Appender.
		*/
		const spi::ErrorHandlerPtr& getErrorHandler() const
		{
			return errorHandler;
		}

		/**
		Returns the head Filter.
		*/
		spi::FilterPtr getFilter() const
		{
			return headFilter;
		}

		/**
		Return the first filter in the filter chain for this
		Appender. The return value may be <code>0</code> if no is
		filter is set.
		*/
		const spi::FilterPtr& getFirstFilter() const
		{
			return headFilter;
		}

		/**
		Returns the layout of this appender. The value may be 0.
		*/
		LayoutPtr getLayout() const
		{
			return layout;
		}


		/**
		Returns the name of this Appender.
		*/
		LogString getName() const
		{
			return name;
		}

		/**
		Returns this appenders threshold level. See the #setThreshold
		method for the meaning of this option.
		*/
		const LevelPtr& getThreshold()
		{
			return threshold;
		}

		/**
		Check whether the message level is below the appender's
		threshold. If there is no threshold set, then the return value is
		always <code>true</code>.
		*/
		bool isAsSevereAsThreshold(const LevelPtr& level) const;


		/**
		* This method performs threshold checks and invokes filters before
		* delegating actual logging to the subclasses specific
		* AppenderSkeleton#append method.
		* */
		virtual void doAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);

		/**
		Set the {@link spi::ErrorHandler ErrorHandler} for this Appender.
		*/
		void setErrorHandler(const spi::ErrorHandlerPtr& eh);

		/**
		Set the layout for this appender. Note that some appenders have
		their own (fixed) layouts or do not use one. For example, the
		{@link net::SocketAppender SocketAppender} ignores the layout set
		here.
		*/
		void setLayout(const LayoutPtr& layout1)
		{
			this->layout = layout1;
		}

		/**
		Set the name of this Appender.
		*/
		void setName(const LogString& name1)
		{
			this->name.assign(name1);
		}


		/**
		Set the threshold level. All log events with lower level
		than the threshold level are ignored by the appender.

		<p>In configuration files this option is specified by setting the
		value of the <b>Threshold</b> option to a level
		string, such as "DEBUG", "INFO" and so on.
		*/
		void setThreshold(const LevelPtr& threshold);

}; // class AppenderSkeleton
}  // namespace log4cxx

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


#endif //_LOG4CXX_APPENDER_SKELETON_H
