/*
 * 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_SPI_LOG_REPOSITORY_H
#define _LOG4CXX_SPI_LOG_REPOSITORY_H

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


#include <log4cxx/appender.h>
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/level.h>
#include <log4cxx/spi/hierarchyeventlistener.h>

namespace log4cxx
{
namespace spi
{

/**
A <code>LoggerRepository</code> is used to create and retrieve
<code>Loggers</code>. The relation between loggers in a repository
depends on the repository but typically loggers are arranged in a
named hierarchy.

<p>In addition to the creational methods, a
<code>LoggerRepository</code> can be queried for existing loggers,
can act as a point of registry for events related to loggers.
*/
class LOG4CXX_EXPORT LoggerRepository : public virtual helpers::Object
{
	public:
		DECLARE_ABSTRACT_LOG4CXX_OBJECT(LoggerRepository)
		virtual ~LoggerRepository() {}

		/**
		Add a {@link spi::HierarchyEventListener HierarchyEventListener}
		            event to the repository.
		*/
		virtual void addHierarchyEventListener(const HierarchyEventListenerPtr&
			listener) = 0;
		/**
		Is the repository disabled for a given level? The answer depends
		on the repository threshold and the <code>level</code>
		parameter. See also #setThreshold method.  */
		virtual bool isDisabled(int level) const = 0;

		/**
		Set the repository-wide threshold. All logging requests below the
		threshold are immediately dropped. By default, the threshold is
		set to <code>Level::getAll()</code> which has the lowest possible rank.  */
		virtual void setThreshold(const LevelPtr& level) = 0;

		/**
		Another form of {@link #setThreshold(const LevelPtr&)
		            setThreshold} accepting a string
		parameter instead of a <code>Level</code>. */
		virtual void setThreshold(const LogString& val) = 0;

		virtual void emitNoAppenderWarning(const LoggerPtr& logger) = 0;

		/**
		Get the repository-wide threshold. See {@link
		#setThreshold(const LevelPtr&) setThreshold}
		            for an explanation. */
		virtual const LevelPtr& getThreshold() const = 0;

		virtual LoggerPtr getLogger(const LogString& name) = 0;

		virtual LoggerPtr getLogger(const LogString& name,
			const spi::LoggerFactoryPtr& factory) = 0;

		virtual LoggerPtr getRootLogger() const = 0;

		virtual LoggerPtr exists(const LogString& name) = 0;

		virtual void shutdown() = 0;

		virtual LoggerList getCurrentLoggers() const = 0;

		virtual void fireAddAppenderEvent(const LoggerPtr& logger,
			const AppenderPtr& appender) = 0;

		virtual void resetConfiguration() = 0;

		virtual bool isConfigured() = 0;
		virtual void setConfigured(bool configured) = 0;

}; // class LoggerRepository

}  // namespace spi
} // namespace log4cxx

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


#endif //_LOG4CXX_SPI_LOG_REPOSITORY_H
