001    /*
002      Copyright (C) 2001 Renaud Pawlak <renaud@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.wrappers;
019    
020    import org.aopalliance.intercept.ConstructorInvocation;
021    import org.aopalliance.intercept.MethodInvocation;
022    import org.objectweb.jac.core.AspectComponent;
023    import org.objectweb.jac.core.Interaction;
024    import org.objectweb.jac.core.Wrapper;
025    
026    /**
027     * <code>LimiterWrapper</code> implements a wrapper that tests a
028     * counter value before calling the wrappee object. If the counter is
029     * not with the max and min limits, it raises the
030     * <code>LimiterException</code>
031     * 
032     * <p>Use this wrapper as follows:
033     *
034     * <ul><pre>
035     * LimiterWrapper lw = new LimiterWrapper(0, 100);
036     * a_stack.wrap(lw, "inc", "push");
037     * a_stack.wrap(lw, "dec", "pop");
038     * a_stack.wrap(lw, "testMax", "push");
039     * a_stack.wrap(lw, "testMin", "pop");
040     * </pre></ul>
041     * 
042     * <p>Where <code>a_stack</code> is an instance of a class
043     * <code>Stack</code>. When wrapping the stack, it will raise a
044     * <code>LimiterException</code> if a push is done and that the
045     * counter is greater or equal to 100 or if a pop is done and that the
046     * counter is lower or equal to 0.
047     *
048     * <p> NOTE: this class cannot be used alone. Its instances must 
049     * wrap some instances of other objects (possibly other
050     * wrappers).
051     *
052     * @see org.objectweb.jac.core.Wrappee
053     * @see org.objectweb.jac.core.Wrapping#wrap(Wrappee,Wrapper,AbstractMethodItem)
054     * @see org.objectweb.jac.wrappers.LimiterException */
055    
056    public class LimiterWrapper extends Wrapper {
057    
058       /** Store the maximum bound of the limiter. */
059        protected int max;
060       /** Store the minimum bound of the limiter. */
061        protected int min;
062       /** Store the counter of the limiter. */
063        protected int counter = 0;
064    
065       /**
066        * Construct a new limiter and initialize the bounds.
067        *
068        * @param min the minimum counter value.
069        * @param max the maximum counter value.
070        */
071       public LimiterWrapper(AspectComponent ac, int min, int max) {
072          super(ac);
073          this.min = min;
074          this.max = max;
075       }
076    
077       /**
078        * Return the max bound of the limiter.
079        *
080        * @return the max bound
081        */
082       public int getMax() {
083          return max;
084       }
085       
086       /**
087        * Set the max bound of the limiter.
088        *
089        * @param max the new max bound
090        */
091       public void setMax(int max) {
092          this.max = max;
093       }
094    
095       /**
096         * Return the current counter of the limiter.
097         *
098         * @return the counter
099         */
100       public int getCounter() {
101          return counter;
102       }
103    
104        /**
105         * This wrapping method increments the limiter counter and calls
106         * the wrappee method.
107         *
108         * <p>For instance, <code>inc</code> could wrap the
109         * <code>push</code> method of a stack so that the counter is
110         * incremented when a new element is placed on the top of the
111         * stack.
112         *
113         * <p>NOTE: this method do not test the bounds. Use
114         * <code>testMax</code> to do this.
115         *
116         * @see LimiterWrapper#testMax(Interaction)
117         *
118         * @return the original method return value
119         */
120        
121        public Object inc(Interaction interaction) {
122           counter++;
123           return proceed(interaction);
124        }
125    
126        /**
127         * This wrapping method decrements the limiter counter and calls
128         * the wrappee method.
129         *
130         * <p>For instance, <code>dec</code> could wrap the
131         * <code>pop</code> method of a stack so that the counter is
132         * incremented when an element is removed from it.
133         *
134         * <p>NOTE: this method do not test the bounds. Use
135         * <code>testMin</code> to do this.
136         *
137         * @see LimiterWrapper#testMin(Interaction)
138         *
139         * @return the original method return value
140         */
141         
142        public Object dec(Interaction interaction) {
143           counter--;
144           return proceed(interaction);
145        }
146        
147        /**
148         * This wrapping method tests the counter of the limiter and
149         * raises the <code>LimiterExeption</code> when when it is over
150         * the maximum value.
151         *
152         * <p>NOTE: this method must be used with the <code>inc</code> and
153         * <code>dec</code> wrapping methods that mofify the counter
154         * value.
155         *
156         * @see LimiterWrapper#inc(Interaction)
157         * @see LimiterWrapper#dec(Interaction)
158         *
159         * @return the original method return value or raise an exception
160         */
161         
162        public Object testMax(Interaction interaction)
163           throws LimiterException {
164           if(counter >= max) {
165              throw new LimiterException("counter reached its maximum count");
166           }
167           return proceed(interaction);
168        }
169    
170        /**
171         * This wrapping method tests the counter of the limiter and
172         * raises the <code>LimiterExeption</code> when when it is below
173         * the minimum value.
174         *
175         * <p>NOTE: this method must be used with the <code>inc</code> and
176         * <code>dec</code> wrapping methods that mofify the counter
177         * value.
178         *
179         * @see LimiterWrapper#inc(Interaction)
180         * @see LimiterWrapper#dec(Interaction)
181         *
182         * @return the original method return value or raise an exception
183         */
184         
185        public Object testMin(Interaction interaction)
186           throws LimiterException {
187           if(counter <= min) {
188              throw new LimiterException("counter reached its minimum count");
189           }
190           return proceed(interaction);
191        }
192    
193            /* (non-Javadoc)
194             * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
195             */
196            public Object invoke(MethodInvocation invocation) throws Throwable {
197                    // TODO Auto-generated method stub
198                    return null;
199            }
200    
201            /* (non-Javadoc)
202             * @see org.aopalliance.intercept.ConstructorInterceptor#construct(org.aopalliance.intercept.ConstructorInvocation)
203             */
204            public Object construct(ConstructorInvocation invocation) throws Throwable {
205                    // TODO Auto-generated method stub
206                    return null;
207            }
208    
209    }