/*
 * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package javax.management;


import java.util.List;
import java.util.Vector;

/**
 * Provides an implementation of the {@link javax.management.NotificationFilter} interface.
 * The filtering is performed on the notification type attribute.
 * <P>
 * Manages a list of enabled notification types.
 * A method allows users to enable/disable as many notification types as required.
 * <P>
 * Then, before sending a notification to a listener registered with a filter,
 * the notification broadcaster compares this notification type with all notification types
 * enabled by the filter. The notification will be sent to the listener
 * only if its filter enables this notification type.
 * <P>
 * Example:
 * <BLOCKQUOTE>
 * <PRE>
 * NotificationFilterSupport myFilter = new NotificationFilterSupport();
 * myFilter.enableType("my_example.my_type");
 * myBroadcaster.addListener(myListener, myFilter, null);
 * </PRE>
 * </BLOCKQUOTE>
 * The listener <CODE>myListener</CODE> will only receive notifications the type of which equals/starts with "my_example.my_type".
 *
 * @see javax.management.NotificationBroadcaster#addNotificationListener
 *
 * @since 1.5
 */
public class NotificationFilterSupport implements NotificationFilter {

    /* Serial version */
    private static final long serialVersionUID = 6579080007561786969L;

    /**
     * @serial {@link Vector} that contains the enabled notification types.
     *         The default value is an empty vector.
     */
    private List<String> enabledTypes = new Vector<String>();


    /**
     * Invoked before sending the specified notification to the listener.
     * <BR>This filter compares the type of the specified notification with each enabled type.
     * If the notification type matches one of the enabled types,
     * the notification should be sent to the listener and this method returns <CODE>true</CODE>.
     *
     * @param notification The notification to be sent.
     * @return <CODE>true</CODE> if the notification should be sent to the listener, <CODE>false</CODE> otherwise.
     */
    public synchronized boolean isNotificationEnabled(Notification notification) {

        String type = notification.getType();

        if (type == null) {
            return false;
        }
        try {
            for (String prefix : enabledTypes) {
                if (type.startsWith(prefix)) {
                    return true;
                }
            }
        } catch (java.lang.NullPointerException e) {
            // Should never occurs...
            return false;
        }
        return false;
    }

    /**
     * Enables all the notifications the type of which starts with the specified prefix
     * to be sent to the listener.
     * <BR>If the specified prefix is already in the list of enabled notification types,
     * this method has no effect.
     * <P>
     * Example:
     * <BLOCKQUOTE>
     * <PRE>
     * // Enables all notifications the type of which starts with "my_example" to be sent.
     * myFilter.enableType("my_example");
     * // Enables all notifications the type of which is "my_example.my_type" to be sent.
     * myFilter.enableType("my_example.my_type");
     * </PRE>
     * </BLOCKQUOTE>
     *
     * Note that:
     * <BLOCKQUOTE><CODE>
     * myFilter.enableType("my_example.*");
     * </CODE></BLOCKQUOTE>
     * will no match any notification type.
     *
     * @param prefix The prefix.
     * @exception java.lang.IllegalArgumentException The prefix parameter is null.
     */
    public synchronized void enableType(String prefix)
            throws IllegalArgumentException {

        if (prefix == null) {
            throw new IllegalArgumentException("The prefix cannot be null.");
        }
        if (!enabledTypes.contains(prefix)) {
            enabledTypes.add(prefix);
        }
    }

    /**
     * Removes the given prefix from the prefix list.
     * <BR>If the specified prefix is not in the list of enabled notification types,
     * this method has no effect.
     *
     * @param prefix The prefix.
     */
    public synchronized void disableType(String prefix) {
        enabledTypes.remove(prefix);
    }

    /**
     * Disables all notification types.
     */
    public synchronized void disableAllTypes() {
        enabledTypes.clear();
    }


    /**
     * Gets all the enabled notification types for this filter.
     *
     * @return The list containing all the enabled notification types.
     */
    public synchronized Vector<String> getEnabledTypes() {
        return (Vector<String>)enabledTypes;
    }

}
