View Javadoc

1   /*
2    * Copyright 1999-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  package org.apache.commons.workflow.base;
18  
19  
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.Map;
24  import java.util.Set;
25  import org.apache.commons.jxpath.JXPathIntrospector;
26  import org.apache.commons.jxpath.MapDynamicPropertyHandler;
27  import org.apache.commons.workflow.Scope;
28  import org.apache.commons.workflow.ScopeListener;
29  import org.apache.commons.workflow.util.ScopeSupport;
30  
31  
32  /**
33   * <strong>BaseScope</strong> is a basic <code>Scope</code> implementation
34   * that maintains its bean collection in an in-memory HashMap.  This can
35   * also serve as a convenient base class for more sophisticated
36   * <code>Scope</code> implementations.
37   *
38   * <p><strong>WARNING</strong> - No synchronization is performed within this
39   * class.  If it is used in a multiple thread environment, callers must
40   * take suitable precations.</p>
41   *
42   * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
43   * @author Craig R. McClanahan
44   */
45  
46  public class BaseScope implements Scope {
47  
48  
49      // -------------------------------------------------- Static Initialization
50  
51  
52      /**
53       * Register ourselves with JXPathIntrospector as an instance of a
54       * dynamic class (in JXPath terminology).
55       */
56      static {
57          JXPathIntrospector.registerDynamicClass
58              (BaseScope.class, MapDynamicPropertyHandler.class);
59      }
60  
61  
62      // ----------------------------------------------------- Instance Variables
63  
64  
65      /**
66       * The HashMap that contains our registered keys and beans.
67       */
68      protected HashMap map = new HashMap();
69  
70  
71      /**
72       * The event listener support object for this <code>Scope</code>.
73       */
74      protected ScopeSupport support = new ScopeSupport(this);
75  
76  
77      // ------------------------------------------------------------ Map Methods
78  
79  
80      /**
81       * Remove all beans from this Map and call <code>scopeCleared() on
82       * all registered <code>ScopeListeners</code>.
83       */
84      public void clear() {
85  
86          map.clear();
87          support.fireScopeCleared();
88  
89      }
90  
91  
92      /**
93       * Return <code>true</code> if this map contains the specified key.
94       *
95       * @param key Key to be looked up
96       */
97      public boolean containsKey(Object key) {
98  
99          return (map.containsKey(key));
100 
101     }
102 
103 
104     /**
105      * Return <code>true</code> if this map contains the specified value.
106      *
107      * @param value Value to be looked up
108      */
109     public boolean containsValue(Object value) {
110 
111         return (map.containsValue(value));
112 
113     }
114 
115 
116     /**
117      * Return a set view of the mappings contained in this map.
118      */
119     public Set entrySet() {
120 
121         return (map.entrySet());
122 
123     }
124 
125 
126     /**
127      * Compare the specified object with this map for equality.
128      *
129      * @param object Object to be compared
130      */
131     public boolean equals(Object object) {
132 
133         return (map.equals(object));
134 
135     }
136 
137 
138     /**
139      * Return the value to which this map maps the specified key.
140      *
141      * @param key Key to be looked up
142      */
143     public Object get(Object key) {
144 
145         return (get((String) key));
146 
147     }
148 
149 
150     /**
151      * Return the value to which this map maps the specified key.
152      *
153      * @param key Key to be looked up
154      */
155     public Object get(String key) {
156 
157         return (map.get(key));
158 
159     }
160 
161 
162     /**
163      * Return the hash code value for this map.
164      */
165     public int hashCode() {
166 
167         return (map.hashCode());
168 
169     }
170 
171 
172     /**
173      * Return <code>true</code> if this map is empty.
174      */
175     public boolean isEmpty() {
176 
177         return (map.isEmpty());
178 
179     }
180 
181 
182     /**
183      * Return a set view of the keys contained in this map.
184      */
185     public Set keySet() {
186 
187         return (map.keySet());
188 
189     }
190 
191 
192     /**
193      * Add or replace the bean associated with the specified key.
194      *
195      * @param key Key with which the new value should be associated
196      *  (cannot be null)
197      * @param bean Bean to be associated with this key (cannot be null)
198      */
199     public Object put(Object key, Object bean) {
200 
201         return (put((String) key, bean));
202 
203     }
204 
205 
206     /**
207      * Add the specified bean, associated with the specified key, to this
208      * scope and replace any previous bean associated with this key.  If
209      * the bean was added, call <code>beanAdded()</code> on all registered
210      * listeners after the add is done.  If an old bean was replaced,
211      * call <code>beanReplaced()</code> (passing the old value in the event)
212      * on all registered <code>ScopeListeners</code> after the removal
213      * is done.  If a bean was replaced, the old value is also returned;
214      * otherwise <code>null</code> is returned.
215      *
216      * @param key Key with which the new value should be associated
217      *  (cannot be null)
218      * @param bean Bean to be associated with this key (cannot be null)
219      *
220      * @exception IllegalArgumentException if <code>key</code> or
221      *  <code>bean</code> is null
222      */
223     public Object put(String key, Object bean) {
224 
225         if (key == null)
226             throw new IllegalArgumentException("Key cannot be null");
227         if (bean == null)
228             throw new IllegalArgumentException("Value cannot be null");
229 
230         Object old = get(key);
231         if (map.containsKey(key)) {
232             map.put(key, bean);
233             support.fireBeanReplaced(key, old);
234         } else {
235             map.put(key, bean);
236             support.fireBeanAdded(key, bean);
237         }
238         return (old);
239             
240     }
241 
242 
243     /**
244      * Copy all of the mappings from the specified map into this map,
245      * firing appropriate <code>beanAdded()</code> and
246      * <code>beanReplaced()</code> events along the way.
247      *
248      * @param in Map whose contents are to be added
249      */
250     public void putAll(Map in) {
251 
252         Iterator keys = in.keySet().iterator();
253         while (keys.hasNext()) {
254             Object key = keys.next();
255             put(key, in.get(key));
256         }
257 
258     }
259 
260 
261     /**
262      * Remove the bean associated with the specified key (if any), and return
263      * the old value if removed.
264      *
265      * @param key Key of the bean to remove (cannot be null)
266      */
267     public Object remove(Object key) {
268 
269         return (remove((String) key));
270 
271     }
272 
273 
274 
275     /**
276      * Remove the bean associated with the specified key (if any).  If such
277      * a bean is found and removed, call <code>beanRemoved()</code> on all
278      * registered <code>ScopeListeners</code> after the removal is done.
279      * Return the old value (if any); otherwise return <code>null</code>.
280      *
281      * @param key Key of the bean to remove (cannot be null)
282      *
283      * @exception IllegalArgumentException if <code>key</code> is null
284      */
285     public Object remove(String key) {
286 
287         if (map.containsKey(key)) {
288             Object old = map.remove(key);
289             support.fireBeanRemoved(key, old);
290             return (old);
291         }
292         return (null);
293 
294     }
295 
296 
297     /**
298      * Return the number of key-value mappings in this map.
299      */
300     public int size() {
301 
302         return (map.size());
303 
304     }
305 
306 
307     /**
308      * Return a Collection view of the values contained in this map.
309      */
310     public Collection values() {
311 
312         return (map.values());
313 
314     }
315 
316 
317     // ------------------------------------------------- Event Listener Methods
318 
319 
320     /**
321      * Add a listener that is notified each time beans are added,
322      * replaced, or removed in this scope.
323      *
324      * @param listener The ScopeListener to be added
325      */
326     public void addScopeListener(ScopeListener listener) {
327 
328         support.addScopeListener(listener);
329 
330     }
331 
332 
333     /**
334      * Remove a listener that is notified each time beans are added,
335      * replaced, or removed in this scope.
336      *
337      * @param listener The ScopeListener to be removed
338      */
339     public void removeScopeListener(ScopeListener listener) {
340 
341         support.removeScopeListener(listener);
342 
343     }
344 
345 
346 }