/*
 * 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_FILTER_LOGGER_MATCH_FILTER_H
#define _LOG4CXX_FILTER_LOGGER_MATCH_FILTER_H

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


#include <log4cxx/spi/filter.h>
#include <log4cxx/level.h>

namespace log4cxx
{
class Level;

namespace filter
{
/**
   This is a very simple filter based on logger name matching.

   <p>The filter admits two options <b>LoggerToMatch</b> and
   <b>AcceptOnMatch</b>. If there is an exact match between the value
   of the <b>LoggerToMatch</b> option and the logger of the {@link
                spi::LoggingEvent LoggingEvent}, then the #decide method returns  {@link
                spi::Filter#ACCEPT ACCEPT} in case the <b>AcceptOnMatch</b> option value is set
   to <code>true</code>, if it is <code>false</code> then {@link
   spi::Filter#DENY} is returned. If there is no match, {@link
   spi::Filter#NEUTRAL} is returned.  A loggerToMatch of "root"
   matches both the root logger and a logger named "root".

   */

class LOG4CXX_EXPORT LoggerMatchFilter : public spi::Filter
{
	private:
		bool acceptOnMatch;
		LogString loggerToMatch;

	public:
		typedef spi::Filter BASE_CLASS;
		DECLARE_LOG4CXX_OBJECT(LoggerMatchFilter)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(LoggerMatchFilter)
		LOG4CXX_CAST_ENTRY_CHAIN(BASE_CLASS)
		END_LOG4CXX_CAST_MAP()

		LoggerMatchFilter();

		/**
		Set options
		*/
		virtual void setOption(const LogString& option,
			const LogString& value);

		void setLoggerToMatch(const LogString& levelToMatch);

		LogString getLoggerToMatch() const;

		inline void setAcceptOnMatch(bool acceptOnMatch1)
		{
			this->acceptOnMatch = acceptOnMatch1;
		}

		inline bool getAcceptOnMatch() const
		{
			return acceptOnMatch;
		}

		/**
		Return the decision of this filter.

		Returns {@link spi::Filter#NEUTRAL NEUTRAL} if the
		<b>LoggerToMatch</b> option is not set or if there is not match.
		Otherwise, if there is a match, then the returned decision is
		{@link spi::Filter#ACCEPT ACCEPT} if the <b>AcceptOnMatch</b>
		property is set to <code>true</code>. The returned decision is
		{@link spi::Filter#DENY DENY} if the
		<b>AcceptOnMatch</b> property is set to false.
		*/
		FilterDecision decide(const spi::LoggingEventPtr& event) const;
}; // class LoggerMatchFilter
LOG4CXX_PTR_DEF(LoggerMatchFilter);
}  // namespace filter
} // namespace log4cxx

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

#endif // _LOG4CXX_FILTER_LOGGER_MATCH_FILTER_H
