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 }