/*
 * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.management.monitor;

import static com.sun.jmx.defaults.JmxProperties.MONITOR_LOGGER;
import java.util.logging.Level;
import javax.management.MBeanNotificationInfo;
import javax.management.ObjectName;
import static javax.management.monitor.Monitor.NumericalType.*;
import static javax.management.monitor.MonitorNotification.*;

/**
 * Defines a monitor MBean designed to observe the values of a gauge attribute.
 *
 * <P> A gauge monitor observes an attribute that is continuously
 * variable with time. A gauge monitor sends notifications as
 * follows:
 *
 * <UL>
 *
 * <LI> if the attribute value is increasing and becomes equal to or
 * greater than the high threshold value, a {@link
 * MonitorNotification#THRESHOLD_HIGH_VALUE_EXCEEDED threshold high
 * notification} is sent. The notify high flag must be set to
 * <CODE>true</CODE>.
 *
 * <BR>Subsequent crossings of the high threshold value do not cause
 * further notifications unless the attribute value becomes equal to
 * or less than the low threshold value.</LI>
 *
 * <LI> if the attribute value is decreasing and becomes equal to or
 * less than the low threshold value, a {@link
 * MonitorNotification#THRESHOLD_LOW_VALUE_EXCEEDED threshold low
 * notification} is sent. The notify low flag must be set to
 * <CODE>true</CODE>.
 *
 * <BR>Subsequent crossings of the low threshold value do not cause
 * further notifications unless the attribute value becomes equal to
 * or greater than the high threshold value.</LI>
 *
 * </UL>
 *
 * This provides a hysteresis mechanism to avoid repeated triggering
 * of notifications when the attribute value makes small oscillations
 * around the high or low threshold value.
 *
 * <P> If the gauge difference mode is used, the value of the derived
 * gauge is calculated as the difference between the observed gauge
 * values for two successive observations.
 *
 * <BR>The derived gauge value (V[t]) is calculated using the following method:
 * <UL>
 * <LI>V[t] = gauge[t] - gauge[t-GP]</LI>
 * </UL>
 *
 * This implementation of the gauge monitor requires the observed
 * attribute to be of the type integer or floating-point
 * (<CODE>Byte</CODE>, <CODE>Integer</CODE>, <CODE>Short</CODE>,
 * <CODE>Long</CODE>, <CODE>Float</CODE>, <CODE>Double</CODE>).
 *
 *
 * @since 1.5
 */
public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {

    /*
     * ------------------------------------------
     *  PACKAGE CLASSES
     * ------------------------------------------
     */

    static class GaugeMonitorObservedObject extends ObservedObject {

        public GaugeMonitorObservedObject(ObjectName observedObject) {
            super(observedObject);
        }

        public final synchronized boolean getDerivedGaugeValid() {
            return derivedGaugeValid;
        }
        public final synchronized void setDerivedGaugeValid(
                                                 boolean derivedGaugeValid) {
            this.derivedGaugeValid = derivedGaugeValid;
        }
        public final synchronized NumericalType getType() {
            return type;
        }
        public final synchronized void setType(NumericalType type) {
            this.type = type;
        }
        public final synchronized Number getPreviousScanGauge() {
            return previousScanGauge;
        }
        public final synchronized void setPreviousScanGauge(
                                                  Number previousScanGauge) {
            this.previousScanGauge = previousScanGauge;
        }
        public final synchronized int getStatus() {
            return status;
        }
        public final synchronized void setStatus(int status) {
            this.status = status;
        }

        private boolean derivedGaugeValid;
        private NumericalType type;
        private Number previousScanGauge;
        private int status;
    }

    /*
     * ------------------------------------------
     *  PRIVATE VARIABLES
     * ------------------------------------------
     */

    /**
     * Gauge high threshold.
     *
     * <BR>The default value is a null Integer object.
     */
    private Number highThreshold = INTEGER_ZERO;

    /**
     * Gauge low threshold.
     *
     * <BR>The default value is a null Integer object.
     */
    private Number lowThreshold = INTEGER_ZERO;

    /**
     * Flag indicating if the gauge monitor notifies when exceeding
     * the high threshold.
     *
     * <BR>The default value is <CODE>false</CODE>.
     */
    private boolean notifyHigh = false;

    /**
     * Flag indicating if the gauge monitor notifies when exceeding
     * the low threshold.
     *
     * <BR>The default value is <CODE>false</CODE>.
     */
    private boolean notifyLow = false;

    /**
     * Flag indicating if the gauge difference mode is used.  If the
     * gauge difference mode is used, the derived gauge is the
     * difference between two consecutive observed values.  Otherwise,
     * the derived gauge is directly the value of the observed
     * attribute.
     *
     * <BR>The default value is set to <CODE>false</CODE>.
     */
    private boolean differenceMode = false;

    private static final String[] types = {
        RUNTIME_ERROR,
        OBSERVED_OBJECT_ERROR,
        OBSERVED_ATTRIBUTE_ERROR,
        OBSERVED_ATTRIBUTE_TYPE_ERROR,
        THRESHOLD_ERROR,
        THRESHOLD_HIGH_VALUE_EXCEEDED,
        THRESHOLD_LOW_VALUE_EXCEEDED
    };

    private static final MBeanNotificationInfo[] notifsInfo = {
        new MBeanNotificationInfo(
            types,
            "javax.management.monitor.MonitorNotification",
            "Notifications sent by the GaugeMonitor MBean")
    };

    // Flags needed to implement the hysteresis mechanism.
    //
    private static final int RISING             = 0;
    private static final int FALLING            = 1;
    private static final int RISING_OR_FALLING  = 2;

    /*
     * ------------------------------------------
     *  CONSTRUCTORS
     * ------------------------------------------
     */

    /**
     * Default constructor.
     */
    public GaugeMonitor() {
    }

    /*
     * ------------------------------------------
     *  PUBLIC METHODS
     * ------------------------------------------
     */

    /**
     * Starts the gauge monitor.
     */
    public synchronized void start() {
        if (isActive()) {
            MONITOR_LOGGER.logp(Level.FINER, GaugeMonitor.class.getName(),
                    "start", "the monitor is already active");
            return;
        }
        // Reset values.
        //
        for (ObservedObject o : observedObjects) {
            final GaugeMonitorObservedObject gmo =
                (GaugeMonitorObservedObject) o;
            gmo.setStatus(RISING_OR_FALLING);
            gmo.setPreviousScanGauge(null);
        }
        doStart();
    }

    /**
     * Stops the gauge monitor.
     */
    public synchronized void stop() {
        doStop();
    }

    // GETTERS AND SETTERS
    //--------------------

    /**
     * Gets the derived gauge of the specified object, if this object is
     * contained in the set of observed MBeans, or <code>null</code> otherwise.
     *
     * @param object the name of the MBean.
     *
     * @return The derived gauge of the specified object.
     *
     */
    public synchronized Number getDerivedGauge(ObjectName object) {
        return (Number) super.getDerivedGauge(object);
    }

    /**
     * Gets the derived gauge timestamp of the specified object, if
     * this object is contained in the set of observed MBeans, or
     * <code>0</code> otherwise.
     *
     * @param object the name of the object whose derived gauge
     * timestamp is to be returned.
     *
     * @return The derived gauge timestamp of the specified object.
     *
     */
    public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
        return super.getDerivedGaugeTimeStamp(object);
    }

    /**
     * Returns the derived gauge of the first object in the set of
     * observed MBeans.
     *
     * @return The derived gauge.
     *
     * @deprecated As of JMX 1.2, replaced by
     * {@link #getDerivedGauge(ObjectName)}
     */
    @Deprecated
    public synchronized Number getDerivedGauge() {
        if (observedObjects.isEmpty()) {
            return null;
        } else {
            return (Number) observedObjects.get(0).getDerivedGauge();
        }
    }

    /**
     * Gets the derived gauge timestamp of the first object in the set
     * of observed MBeans.
     *
     * @return The derived gauge timestamp.
     *
     * @deprecated As of JMX 1.2, replaced by
     * {@link #getDerivedGaugeTimeStamp(ObjectName)}
     */
    @Deprecated
    public synchronized long getDerivedGaugeTimeStamp() {
        if (observedObjects.isEmpty()) {
            return 0;
        } else {
            return observedObjects.get(0).getDerivedGaugeTimeStamp();
        }
    }

    /**
     * Gets the high threshold value common to all observed MBeans.
     *
     * @return The high threshold value.
     *
     * @see #setThresholds
     */
    public synchronized Number getHighThreshold() {
        return highThreshold;
    }

    /**
     * Gets the low threshold value common to all observed MBeans.
     *
     * @return The low threshold value.
     *
     * @see #setThresholds
     */
    public synchronized Number getLowThreshold() {
        return lowThreshold;
    }

    /**
     * Sets the high and the low threshold values common to all
     * observed MBeans.
     *
     * @param highValue The high threshold value.
     * @param lowValue The low threshold value.
     *
     * @exception IllegalArgumentException The specified high/low
     * threshold is null or the low threshold is greater than the high
     * threshold or the high threshold and the low threshold are not
     * of the same type.
     *
     * @see #getHighThreshold
     * @see #getLowThreshold
     */
    public synchronized void setThresholds(Number highValue, Number lowValue)
        throws IllegalArgumentException {

        if ((highValue == null) || (lowValue == null)) {
            throw new IllegalArgumentException("Null threshold value");
        }

        if (highValue.getClass() != lowValue.getClass()) {
            throw new IllegalArgumentException("Different type " +
                                               "threshold values");
        }

        if (isFirstStrictlyGreaterThanLast(lowValue, highValue,
                                           highValue.getClass().getName())) {
            throw new IllegalArgumentException("High threshold less than " +
                                               "low threshold");
        }

        if (highThreshold.equals(highValue) && lowThreshold.equals(lowValue))
            return;
        highThreshold = highValue;
        lowThreshold = lowValue;

        // Reset values.
        //
        int index = 0;
        for (ObservedObject o : observedObjects) {
            resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
            final GaugeMonitorObservedObject gmo =
                (GaugeMonitorObservedObject) o;
            gmo.setStatus(RISING_OR_FALLING);
        }
    }

    /**
     * Gets the high notification's on/off switch value common to all
     * observed MBeans.
     *
     * @return <CODE>true</CODE> if the gauge monitor notifies when
     * exceeding the high threshold, <CODE>false</CODE> otherwise.
     *
     * @see #setNotifyHigh
     */
    public synchronized boolean getNotifyHigh() {
        return notifyHigh;
    }

    /**
     * Sets the high notification's on/off switch value common to all
     * observed MBeans.
     *
     * @param value The high notification's on/off switch value.
     *
     * @see #getNotifyHigh
     */
    public synchronized void setNotifyHigh(boolean value) {
        if (notifyHigh == value)
            return;
        notifyHigh = value;
    }

    /**
     * Gets the low notification's on/off switch value common to all
     * observed MBeans.
     *
     * @return <CODE>true</CODE> if the gauge monitor notifies when
     * exceeding the low threshold, <CODE>false</CODE> otherwise.
     *
     * @see #setNotifyLow
     */
    public synchronized boolean getNotifyLow() {
        return notifyLow;
    }

    /**
     * Sets the low notification's on/off switch value common to all
     * observed MBeans.
     *
     * @param value The low notification's on/off switch value.
     *
     * @see #getNotifyLow
     */
    public synchronized void setNotifyLow(boolean value) {
        if (notifyLow == value)
            return;
        notifyLow = value;
    }

    /**
     * Gets the difference mode flag value common to all observed MBeans.
     *
     * @return <CODE>true</CODE> if the difference mode is used,
     * <CODE>false</CODE> otherwise.
     *
     * @see #setDifferenceMode
     */
    public synchronized boolean getDifferenceMode() {
        return differenceMode;
    }

    /**
     * Sets the difference mode flag value common to all observed MBeans.
     *
     * @param value The difference mode flag value.
     *
     * @see #getDifferenceMode
     */
    public synchronized void setDifferenceMode(boolean value) {
        if (differenceMode == value)
            return;
        differenceMode = value;

        // Reset values.
        //
        for (ObservedObject o : observedObjects) {
            final GaugeMonitorObservedObject gmo =
                (GaugeMonitorObservedObject) o;
            gmo.setStatus(RISING_OR_FALLING);
            gmo.setPreviousScanGauge(null);
        }
    }

   /**
     * Returns a <CODE>NotificationInfo</CODE> object containing the
     * name of the Java class of the notification and the notification
     * types sent by the gauge monitor.
     */
    public MBeanNotificationInfo[] getNotificationInfo() {
        return notifsInfo;
    }

    /*
     * ------------------------------------------
     *  PRIVATE METHODS
     * ------------------------------------------
     */

    /**
     * Updates the derived gauge attribute of the observed object.
     *
     * @param scanGauge The value of the observed attribute.
     * @param o The observed object.
     * @return <CODE>true</CODE> if the derived gauge value is valid,
     * <CODE>false</CODE> otherwise.  The derived gauge value is
     * invalid when the differenceMode flag is set to
     * <CODE>true</CODE> and it is the first notification (so we
     * haven't 2 consecutive values to update the derived gauge).
     */
    private synchronized boolean updateDerivedGauge(
        Object scanGauge, GaugeMonitorObservedObject o) {

        boolean is_derived_gauge_valid;

        // The gauge difference mode is used.
        //
        if (differenceMode) {

            // The previous scan gauge has been initialized.
            //
            if (o.getPreviousScanGauge() != null) {
                setDerivedGaugeWithDifference((Number)scanGauge, o);
                is_derived_gauge_valid = true;
            }
            // The previous scan gauge has not been initialized.
            // We cannot update the derived gauge...
            //
            else {
                is_derived_gauge_valid = false;
            }
            o.setPreviousScanGauge((Number)scanGauge);
        }
        // The gauge difference mode is not used.
        //
        else {
            o.setDerivedGauge((Number)scanGauge);
            is_derived_gauge_valid = true;
        }

        return is_derived_gauge_valid;
    }

    /**
     * Updates the notification attribute of the observed object
     * and notifies the listeners only once if the notify flag
     * is set to <CODE>true</CODE>.
     * @param o The observed object.
     */
    private synchronized MonitorNotification updateNotifications(
        GaugeMonitorObservedObject o) {

        MonitorNotification n = null;

        // Send high notification if notifyHigh is true.
        // Send low notification if notifyLow is true.
        //
        if (o.getStatus() == RISING_OR_FALLING) {
            if (isFirstGreaterThanLast((Number)o.getDerivedGauge(),
                                       highThreshold,
                                       o.getType())) {
                if (notifyHigh) {
                    n = new MonitorNotification(
                            THRESHOLD_HIGH_VALUE_EXCEEDED,
                            this,
                            0,
                            0,
                            "",
                            null,
                            null,
                            null,
                            highThreshold);
                }
                o.setStatus(FALLING);
            } else if (isFirstGreaterThanLast(lowThreshold,
                                              (Number)o.getDerivedGauge(),
                                              o.getType())) {
                if (notifyLow) {
                    n = new MonitorNotification(
                            THRESHOLD_LOW_VALUE_EXCEEDED,
                            this,
                            0,
                            0,
                            "",
                            null,
                            null,
                            null,
                            lowThreshold);
                }
                o.setStatus(RISING);
            }
        } else {
            if (o.getStatus() == RISING) {
                if (isFirstGreaterThanLast((Number)o.getDerivedGauge(),
                                           highThreshold,
                                           o.getType())) {
                    if (notifyHigh) {
                        n = new MonitorNotification(
                                THRESHOLD_HIGH_VALUE_EXCEEDED,
                                this,
                                0,
                                0,
                                "",
                                null,
                                null,
                                null,
                                highThreshold);
                    }
                    o.setStatus(FALLING);
                }
            } else if (o.getStatus() == FALLING) {
                if (isFirstGreaterThanLast(lowThreshold,
                                           (Number)o.getDerivedGauge(),
                                           o.getType())) {
                    if (notifyLow) {
                        n = new MonitorNotification(
                                THRESHOLD_LOW_VALUE_EXCEEDED,
                                this,
                                0,
                                0,
                                "",
                                null,
                                null,
                                null,
                                lowThreshold);
                    }
                    o.setStatus(RISING);
                }
            }
        }

        return n;
    }

    /**
     * Sets the derived gauge when the differenceMode flag is set to
     * <CODE>true</CODE>.  Both integer and floating-point types are
     * allowed.
     *
     * @param scanGauge The value of the observed attribute.
     * @param o The observed object.
     */
    private synchronized void setDerivedGaugeWithDifference(
        Number scanGauge, GaugeMonitorObservedObject o) {
        Number prev = o.getPreviousScanGauge();
        Number der;
        switch (o.getType()) {
        case INTEGER:
            der = new Integer(((Integer)scanGauge).intValue() -
                              ((Integer)prev).intValue());
            break;
        case BYTE:
            der = new Byte((byte)(((Byte)scanGauge).byteValue() -
                                  ((Byte)prev).byteValue()));
            break;
        case SHORT:
            der = new Short((short)(((Short)scanGauge).shortValue() -
                                    ((Short)prev).shortValue()));
            break;
        case LONG:
            der = new Long(((Long)scanGauge).longValue() -
                           ((Long)prev).longValue());
            break;
        case FLOAT:
            der = new Float(((Float)scanGauge).floatValue() -
                            ((Float)prev).floatValue());
            break;
        case DOUBLE:
            der = new Double(((Double)scanGauge).doubleValue() -
                             ((Double)prev).doubleValue());
            break;
        default:
            // Should never occur...
            MONITOR_LOGGER.logp(Level.FINEST, GaugeMonitor.class.getName(),
                    "setDerivedGaugeWithDifference",
                    "the threshold type is invalid");
            return;
        }
        o.setDerivedGauge(der);
    }

    /**
     * Tests if the first specified Number is greater than or equal to
     * the last.  Both integer and floating-point types are allowed.
     *
     * @param greater The first Number to compare with the second.
     * @param less The second Number to compare with the first.
     * @param type The number type.
     * @return <CODE>true</CODE> if the first specified Number is
     * greater than or equal to the last, <CODE>false</CODE>
     * otherwise.
     */
    private boolean isFirstGreaterThanLast(Number greater,
                                           Number less,
                                           NumericalType type) {

        switch (type) {
        case INTEGER:
        case BYTE:
        case SHORT:
        case LONG:
            return (greater.longValue() >= less.longValue());
        case FLOAT:
        case DOUBLE:
            return (greater.doubleValue() >= less.doubleValue());
        default:
            // Should never occur...
            MONITOR_LOGGER.logp(Level.FINEST, GaugeMonitor.class.getName(),
                    "isFirstGreaterThanLast",
                    "the threshold type is invalid");
            return false;
        }
    }

    /**
     * Tests if the first specified Number is strictly greater than the last.
     * Both integer and floating-point types are allowed.
     *
     * @param greater The first Number to compare with the second.
     * @param less The second Number to compare with the first.
     * @param className The number class name.
     * @return <CODE>true</CODE> if the first specified Number is
     * strictly greater than the last, <CODE>false</CODE> otherwise.
     */
    private boolean isFirstStrictlyGreaterThanLast(Number greater,
                                                   Number less,
                                                   String className) {

        if (className.equals("java.lang.Integer") ||
            className.equals("java.lang.Byte") ||
            className.equals("java.lang.Short") ||
            className.equals("java.lang.Long")) {

            return (greater.longValue() > less.longValue());
        }
        else if (className.equals("java.lang.Float") ||
                 className.equals("java.lang.Double")) {

            return (greater.doubleValue() > less.doubleValue());
        }
        else {
            // Should never occur...
            MONITOR_LOGGER.logp(Level.FINEST, GaugeMonitor.class.getName(),
                    "isFirstStrictlyGreaterThanLast",
                    "the threshold type is invalid");
            return false;
        }
    }

    /*
     * ------------------------------------------
     *  PACKAGE METHODS
     * ------------------------------------------
     */

    /**
     * Factory method for ObservedObject creation.
     *
     * @since 1.6
     */
    @Override
    ObservedObject createObservedObject(ObjectName object) {
        final GaugeMonitorObservedObject gmo =
            new GaugeMonitorObservedObject(object);
        gmo.setStatus(RISING_OR_FALLING);
        gmo.setPreviousScanGauge(null);
        return gmo;
    }

    /**
     * This method globally sets the derived gauge type for the given
     * "object" and "attribute" after checking that the type of the
     * supplied observed attribute value is one of the value types
     * supported by this monitor.
     */
    @Override
    synchronized boolean isComparableTypeValid(ObjectName object,
                                               String attribute,
                                               Comparable<?> value) {
        final GaugeMonitorObservedObject o =
            (GaugeMonitorObservedObject) getObservedObject(object);
        if (o == null)
            return false;

        // Check that the observed attribute is either of type
        // "Integer" or "Float".
        //
        if (value instanceof Integer) {
            o.setType(INTEGER);
        } else if (value instanceof Byte) {
            o.setType(BYTE);
        } else if (value instanceof Short) {
            o.setType(SHORT);
        } else if (value instanceof Long) {
            o.setType(LONG);
        } else if (value instanceof Float) {
            o.setType(FLOAT);
        } else if (value instanceof Double) {
            o.setType(DOUBLE);
        } else {
            return false;
        }
        return true;
    }

    @Override
    synchronized Comparable<?> getDerivedGaugeFromComparable(
                                                  ObjectName object,
                                                  String attribute,
                                                  Comparable<?> value) {
        final GaugeMonitorObservedObject o =
            (GaugeMonitorObservedObject) getObservedObject(object);
        if (o == null)
            return null;

        // Update the derived gauge attributes and check the
        // validity of the new value. The derived gauge value
        // is invalid when the differenceMode flag is set to
        // true and it is the first notification, i.e. we
        // haven't got 2 consecutive values to update the
        // derived gauge.
        //
        o.setDerivedGaugeValid(updateDerivedGauge(value, o));

        return (Comparable<?>) o.getDerivedGauge();
    }

    @Override
    synchronized void onErrorNotification(MonitorNotification notification) {
        final GaugeMonitorObservedObject o = (GaugeMonitorObservedObject)
            getObservedObject(notification.getObservedObject());
        if (o == null)
            return;

        // Reset values.
        //
        o.setStatus(RISING_OR_FALLING);
        o.setPreviousScanGauge(null);
    }

    @Override
    synchronized MonitorNotification buildAlarmNotification(
                                               ObjectName object,
                                               String attribute,
                                               Comparable<?> value) {
        final GaugeMonitorObservedObject o =
            (GaugeMonitorObservedObject) getObservedObject(object);
        if (o == null)
            return null;

        // Notify the listeners if the updated derived
        // gauge value is valid.
        //
        final MonitorNotification alarm;
        if (o.getDerivedGaugeValid())
            alarm = updateNotifications(o);
        else
            alarm = null;
        return alarm;
    }

    /**
     * Tests if the threshold high and threshold low are both of the
     * same type as the gauge.  Both integer and floating-point types
     * are allowed.
     *
     * Note:
     *   If the optional lowThreshold or highThreshold have not been
     *   initialized, their default value is an Integer object with
     *   a value equal to zero.
     *
     * @param object The observed object.
     * @param attribute The observed attribute.
     * @param value The sample value.
     * @return <CODE>true</CODE> if type is the same,
     * <CODE>false</CODE> otherwise.
     */
    @Override
    synchronized boolean isThresholdTypeValid(ObjectName object,
                                              String attribute,
                                              Comparable<?> value) {
        final GaugeMonitorObservedObject o =
            (GaugeMonitorObservedObject) getObservedObject(object);
        if (o == null)
            return false;

        Class<? extends Number> c = classForType(o.getType());
        return (isValidForType(highThreshold, c) &&
                isValidForType(lowThreshold, c));
    }
}
