/*
 * 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.
 */

package org.apache.log4j.spi;

/**
 * Users should extend this class to implement customized logging event filtering. Note that
 * {@link org.apache.log4j.Category} and {@link org.apache.log4j.AppenderSkeleton}, the parent class of all standard
 * appenders, have built-in filtering rules. It is suggested that you first use and understand the built-in rules before
 * rushing to write your own custom filters.
 *
 * <p>
 * This abstract class assumes and also imposes that filters be organized in a linear chain. The
 * {@link #decide decide(LoggingEvent)} method of each filter is called sequentially, in the order of their addition to
 * the chain.
 *
 * <p>
 * The {@link #decide decide(LoggingEvent)} method must return one of the integer constants {@link #DENY},
 * {@link #NEUTRAL} or {@link #ACCEPT}.
 *
 * <p>
 * If the value {@link #DENY} is returned, then the log event is dropped immediately without consulting with the
 * remaining filters.
 *
 * <p>
 * If the value {@link #NEUTRAL} is returned, then the next filter in the chain is consulted. If there are no more
 * filters in the chain, then the log event is logged. Thus, in the presence of no filters, the default behaviour is to
 * log all logging events.
 *
 * <p>
 * If the value {@link #ACCEPT} is returned, then the log event is logged without consulting the remaining filters.
 *
 * <p>
 * The philosophy of log4j filters is largely inspired from the Linux ipchains.
 *
 * <p>
 * Note that filtering is only supported by the {@link org.apache.log4j.xml.DOMConfigurator DOMConfigurator}. The
 * {@link org.apache.log4j.PropertyConfigurator PropertyConfigurator} does not support filters.
 *
 * @author Ceki G&uuml;lc&uuml;
 * @since 0.9.0
 */
public abstract class Filter implements OptionHandler {

    /**
     * Points to the next filter in the filter chain.
     *
     * @deprecated As of 1.2.12, use {@link #getNext} and {@link #setNext} instead
     */
    public Filter next;

    /**
     * The log event must be dropped immediately without consulting with the remaining filters, if any, in the chain.
     */
    public static final int DENY = -1;

    /**
     * This filter is neutral with respect to the log event. The remaining filters, if any, should be consulted for a
     * final decision.
     */
    public static final int NEUTRAL = 0;

    /**
     * The log event must be logged immediately without consulting with the remaining filters, if any, in the chain.
     */
    public static final int ACCEPT = 1;

    /**
     * Usually filters options become active when set. We provide a default do-nothing implementation for convenience.
     */
    public void activateOptions() {
    }

    /**
     * <p>
     * If the decision is <code>DENY</code>, then the event will be dropped. If the decision is <code>NEUTRAL</code>,
     * then the next filter, if any, will be invoked. If the decision is ACCEPT then the event will be logged without
     * consulting with other filters in the chain.
     *
     * @param event The LoggingEvent to decide upon.
     * @return decision The decision of the filter.
     */
    abstract public int decide(LoggingEvent event);

    /**
     * Set the next filter pointer.
     */
    public void setNext(Filter next) {
        this.next = next;
    }

    /**
     * Return the pointer to the next filter;
     */
    public Filter getNext() {
        return next;
    }

}
