001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * You may obtain a copy of the License at 
008     * 
009     * http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS, 
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
014     * See the License for the specific language governing permissions and 
015     * limitations under the License. 
016     * 
017     **/
018    
019    package org.activemq.capacity;
020    import java.util.Iterator;
021    import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
022    
023    /**
024     * BasicCapacityMonitor implementation
025     * @version $Revision: 1.1.1.1 $
026     */
027    public class BasicCapacityMonitor implements CapacityMonitor {
028        private String name;
029        private long valueLimit;
030        private long currentValue = 0;
031        private int currentCapacity = 100;
032        private int roundedCapacity = 100;
033        private int roundingFactor = 10;
034        private CopyOnWriteArrayList listeners = new CopyOnWriteArrayList();
035    
036        /**
037         * Construct a CapacityMonitor
038         * 
039         * @param name
040         * @param valueLimit
041         */
042        public BasicCapacityMonitor(String name, long valueLimit) {
043            this.name = name;
044            this.valueLimit = valueLimit;
045        }
046    
047        /**
048         * Get the name of the CapacityMonitor
049         * 
050         * @return
051         */
052        public String getName() {
053            return name;
054        }
055        
056        /**
057         * @param newName
058         */
059        public void setName(String newName){
060            name = newName;
061        }
062        
063        /**
064         * Get the rounding factor - default is 10
065         * @return the rounding factor
066         */
067        public int getRoundingFactor(){
068            return roundingFactor;
069        }
070        
071        /**
072         * Set the rounding factor (between 1-100)
073         * @param newRoundingFactor
074         */
075        public void setRoundingFactor(int newRoundingFactor){
076            if (newRoundingFactor < 1 || newRoundingFactor > 100){
077                throw new IllegalArgumentException("invalid roundingFactor: " + newRoundingFactor);
078            }
079            roundingFactor = newRoundingFactor;
080        }
081    
082        /**
083         * Add a CapacityMonitorEventListener
084         * 
085         * @param l
086         */
087        public void addCapacityEventListener(CapacityMonitorEventListener l) {
088            listeners.add(l);
089        }
090    
091        /**
092         * Remove a CapacityMonitorEventListener
093         * 
094         * @param l
095         */
096        public void removeCapacityEventListener(CapacityMonitorEventListener l) {
097            listeners.remove(l);
098        }
099    
100        /**
101         * Get the current capscity of the service as a percentage
102         * 
103         * @return
104         */
105        public int getCurrentCapacity() {
106            return currentCapacity;
107        }
108        
109        /**
110         * Calculates the capacity rounded down to the rounding factor
111         * @return
112         */
113        public int getRoundedCapacity(){
114            return roundedCapacity;
115        }
116    
117        /**
118         * Get the current value of the CapacityMonitor
119         * 
120         * @return
121         */
122        public long getCurrentValue() {
123            return currentValue;
124        }
125    
126        /**
127         * set the current value of the capacity
128         * 
129         * @param newCurrentValue
130         */
131        public void setCurrentValue(long newCurrentValue) {
132            currentValue = newCurrentValue;
133            int newCapacity = calculateCapacity();
134            int newRoundedCapacity = newCapacity > 0 ?  (newCapacity/roundingFactor)*roundingFactor : 0;
135            updateCapacityChanged(newRoundedCapacity);
136            currentCapacity = newCapacity;
137            roundedCapacity = newRoundedCapacity;
138        }
139    
140        /**
141         * @return The upper limit of the value of the CapacityMonitor
142         */
143        public long getValueLimit() {
144            return valueLimit;
145        }
146    
147        /**
148         * set a new value limit for the CapacityMonitor
149         * 
150         * @param newValueLimit
151         */
152        public void setValueLimit(long newValueLimit) {
153            valueLimit = newValueLimit;
154            //this could have changed the capacity
155            setCurrentValue(currentValue);
156            
157        }
158        
159        /**
160         * @return a CapacityMontorEvent for the currentCapacity
161         */
162        public CapacityMonitorEvent generateCapacityMonitorEvent(){
163            CapacityMonitorEvent event = new CapacityMonitorEvent(name, roundedCapacity);
164            return event;
165        }
166    
167        private void updateCapacityChanged(int newRoundedCapacity) {
168            if (listeners.size() > 0 && newRoundedCapacity != roundedCapacity) {
169                CapacityMonitorEvent event = new CapacityMonitorEvent(name, newRoundedCapacity);
170                for (Iterator i = listeners.iterator();i.hasNext();) {
171                    CapacityMonitorEventListener listener = (CapacityMonitorEventListener) i.next();
172                    listener.capacityChanged(event);
173                }
174            }
175            
176        }
177    
178        private int calculateCapacity() {
179            int result = 100;
180            if (currentValue != 0){
181                result = (int) (100-(currentValue * 100)/valueLimit);
182            }
183            return result;
184        }
185    }