/*
 * Copyright 2008 the original author or authors.
 * Copyright 2005 Sun Microsystems, Inc.
 *
 * Licensed 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.rioproject.watch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.List;

/**
 * The ThresholdManager is the keeper of ThresholdValues and determines when
 * Calculable items being recorded have crossed any thresholds. A
 * ThresholdManager provides threshold management processing, providing specific
 * behavior that may be used to remedy the situation where a threshold has been
 * crossed
 */
public abstract class ThresholdManager {
    protected final transient List<ThresholdListener> thresholdListeners = new LinkedList<ThresholdListener>();
    /** Holds value of property thresholdValues */
    protected ThresholdValues thresholdValues = new ThresholdValues();
    static Logger logger = LoggerFactory.getLogger(ThresholdManager.class.getName());

    /**
     * Check the threshold and determine if any action needs to occur
     *
     * @param calculable The Calculable to check
     */
    public abstract void checkThreshold(Calculable calculable);

    /**
     * Get the identifier for the  ThresholdManager
     */
    protected abstract String getID();

    /**
     * Get the type of threshold that has been crossed
     *
     * @return The type of threshold that has been crossed
     */
    public abstract boolean getThresholdCrossed();

    /**
     * Getter for property thresholdValues.
     * 
     * @return Value of property thresholdValues.
     */
    public ThresholdValues getThresholdValues() {
        return (thresholdValues);
    }

    /**
     * Setter for property thresholdValues.
     * 
     * @param thresholdValues New value of property thresholdValues.
     */
    public void setThresholdValues(ThresholdValues thresholdValues) {
        this.thresholdValues = thresholdValues;
        if(logger.isTraceEnabled())
            logger.trace(String.format("%s Set ThresholdValues, low=%f, high=%s",
                                        getID(),
                                        thresholdValues.getLowThreshold(),
                                        thresholdValues.getHighThreshold()));
    }

    /**
     * Notify all ThresholdListeners of a threshold being crossed
     * 
     * @param calculable The Calculable record
     * @param type The type of threshold, breached or cleared
     */
    protected void notifyListeners(Calculable calculable, ThresholdType type) {
        ThresholdListener[] tListeners = getThresholdListeners();
        if(logger.isTraceEnabled())
            logger.trace(String.format("%s Notify ThresholdListeners, number to notify: %d",
                                        getID(),
                                        tListeners.length));
        ThresholdValues thresholds = null;
        try {
            thresholds = (ThresholdValues)thresholdValues.clone();
        } catch (CloneNotSupportedException e) {
            //
        }

        for (ThresholdListener tListener : tListeners) {
            tListener.notify(calculable, thresholds, type);
        }
    }

    /**
     * Add a Threshold listener
     * 
     * @param listener the ThresholdListener to add
     */
    public void addThresholdListener(ThresholdListener listener) {
        synchronized(thresholdListeners) {
            if(!thresholdListeners.contains(listener))
                thresholdListeners.add(listener);
            if(logger.isTraceEnabled())
                logger.trace(String.format("%s Added a ThresholdListener, number now: %d",
                                            getID(),
                                            thresholdListeners.size()));
        }
    }

    /**
     * Remove a ThresholdListener
     * 
     * @param listener the ThresholdListener to remove
     */
    public void removeThresholdListener(ThresholdListener listener) {
        synchronized(thresholdListeners) {
            thresholdListeners.remove(listener);
            if(logger.isTraceEnabled())
                logger.trace(String.format("%s Removed a ThresholdListener, number now: %d",
                                            getID(),
                                            thresholdListeners.size()));
        }
    }

    /**
     * Get all registered ThresholdListener instances
     * 
     * @return Array of ThresholdListener[]. A new array will be allocated each
     * time this method is called. If there are no registered ThresholdListener
     * instances, a zero-length array will be returned
     */
    public ThresholdListener[] getThresholdListeners() {
        ThresholdListener[] tListeners;
        synchronized(thresholdListeners) {
            tListeners = thresholdListeners.toArray(new ThresholdListener[thresholdListeners.size()]);
        }
        return (tListeners);
    }

    /**
     * Remove all registered ThresholdListener instances
     */
    public void clear() {
        synchronized(thresholdListeners) {
            thresholdListeners.clear();
        }
    }
}

@@ -2457,78 +2457,24 @@
     
-if(logger.isTraceEnabled())%0A            logger.trace(String.format(%22%25s
+logger.trace(%22%7B%7D
  Set
@@ -2499,19 +2499,19 @@
 low=
-%25f
+%7B%7D
 , high=
-%25s
+%7B%7D
 %22,%0A 
@@ -2534,35 +2534,16 @@
     
-                 
-  
 getID(),
 %0A   
@@ -2542,123 +2542,43 @@
 D(),
-%0A                                        thresholdValues.getLowThreshold(),%0A                                       
+ thresholdValues.getLowThreshold(),
  thr
@@ -2609,17 +2609,16 @@
 shold())
-)
 ;%0A    %7D%0A
@@ -2967,48 +2967,8 @@
 ();%0A
-        if(logger.isTraceEnabled())%0A    
     
@@ -2984,33 +2984,19 @@
 r.trace(
-String.format(%22%25s
+%22%7B%7D
  Notify 
@@ -3037,101 +3037,21 @@
 fy: 
-%25d%22,%0A                                        getID(),%0A                                       
+%7B%7D%22, getID(),
  tLi
@@ -3065,17 +3065,16 @@
 .length)
-)
 ;%0A      
@@ -3727,52 +3727,8 @@
 r);%0A
-            if(logger.isTraceEnabled())%0A    
     
@@ -3748,33 +3748,19 @@
 r.trace(
-String.format(%22%25s
+%22%7B%7D
  Added a
@@ -3795,109 +3795,21 @@
 ow: 
-%25d%22,%0A                                            getID(),%0A                                           
+%7B%7D%22, getID(),
  thr
@@ -3823,33 +3823,32 @@
 isteners.size())
-)
 ;%0A        %7D%0A    
@@ -4129,52 +4129,8 @@
 r);%0A
-            if(logger.isTraceEnabled())%0A    
     
@@ -4154,25 +4154,11 @@
 ace(
-String.format(%22%25s
+%22%7B%7D
  Rem
@@ -4199,109 +4199,21 @@
 ow: 
-%25d%22,%0A                                            getID(),%0A                                           
+%7B%7D%22, getID(),
  thr
@@ -4235,17 +4235,16 @@
 .size())
-)
 ;%0A      

Use parameterized logging