/*
 * 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_LEVEL_MATCH_FILTER_H
#define _LOG4CXX_FILTER_LEVEL_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 level matching.

<p>The filter admits two options <b>LevelToMatch</b> and
<b>AcceptOnMatch</b>. If there is an exact match between the value
of the <b>LevelToMatch</b> option and the level 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 DENY} is returned. If there is no match,
{@link spi::Filter#NEUTRAL NEUTRAL} is returned.
*/

class LOG4CXX_EXPORT LevelMatchFilter : public spi::Filter
{
	private:
		bool acceptOnMatch;
		LevelPtr levelToMatch;

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

		LevelMatchFilter();

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

		void setLevelToMatch(const LogString& levelToMatch);

		LogString getLevelToMatch() 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>LevelToMatch</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 LevelMatchFilter
LOG4CXX_PTR_DEF(LevelMatchFilter);
}  // namespace filter
} // namespace log4cxx

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

#endif // _LOG4CXX_FILTER_LEVEL_MATCH_FILTER_H
