/*
 * 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_HELPERS_APPENDER_ATTACHABLE_IMPL_H
#define _LOG4CXX_HELPERS_APPENDER_ATTACHABLE_IMPL_H

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


#include <log4cxx/spi/appenderattachable.h>
#include <log4cxx/helpers/object.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/log4cxx.h>

namespace log4cxx
{
namespace spi
{
class LoggingEvent;
typedef log4cxx::shared_ptr<LoggingEvent> LoggingEventPtr;
}

namespace helpers
{

class LOG4CXX_EXPORT AppenderAttachableImpl :
	public virtual spi::AppenderAttachable,
    public virtual helpers::Object
{
	protected:
		/** Array of appenders. */
		AppenderList  appenderList;

	public:
		/**
		 *   Create new instance.
		 *   @param pool pool, must be longer-lived than instance.
		 */
		AppenderAttachableImpl(Pool& pool);

		DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderAttachableImpl)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(AppenderAttachableImpl)
		LOG4CXX_CAST_ENTRY(spi::AppenderAttachable)
		END_LOG4CXX_CAST_MAP()

		// Methods
		/**
		 * Add an appender.
		 */
        virtual void addAppender(const AppenderPtr newAppender);

		/**
		 Call the <code>doAppend</code> method on all attached appenders.
		*/
		int appendLoopOnAppenders(const spi::LoggingEventPtr& event,
			log4cxx::helpers::Pool& p);

		/**
		 * Get all previously added appenders as an Enumeration.
		 */
		virtual AppenderList getAllAppenders() const;

		/**
		 * Get an appender by name.
		 */
		virtual AppenderPtr getAppender(const LogString& name) const;

		/**
		 Returns <code>true</code> if the specified appender is in the
		 list of attached appenders, <code>false</code> otherwise.
		*/
        virtual bool isAttached(const AppenderPtr appender) const;

		/**
		 * Remove all previously added appenders.
		 */
		virtual void removeAllAppenders();

		/**
		 * Remove the appender passed as parameter from the list of appenders.
		 */
        virtual void removeAppender(const AppenderPtr appender);

		/**
		 * Remove the appender with the name passed as parameter from the
		 * list of appenders.
		 */
		virtual void removeAppender(const LogString& name);

		inline mutex& getMutex() const
		{
			return m_mutex;
		}

	private:
		mutable mutex m_mutex;
		AppenderAttachableImpl(const AppenderAttachableImpl&);
		AppenderAttachableImpl& operator=(const AppenderAttachableImpl&);
};

LOG4CXX_PTR_DEF(AppenderAttachableImpl);

}
}

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

#endif //_LOG4CXX_HELPERS_APPENDER_ATTACHABLE_IMPL_H
