1 package org.apache.velocity.context; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 /** 23 * This class is the abstract base class for all conventional 24 * Velocity Context implementations. Simply extend this class 25 * and implement the abstract routines that access your preferred 26 * storage method. 27 * 28 * Takes care of context chaining. 29 * 30 * Also handles / enforces policy on null keys and values : 31 * 32 * <ul> 33 * <li> Null keys and values are accepted and basically dropped. 34 * <li> If you place an object into the context with a null key, it 35 * will be ignored and logged. 36 * <li> If you try to place a null into the context with any key, it 37 * will be dropped and logged. 38 * </ul> 39 * 40 * The default implementation of this for application use is 41 * org.apache.velocity.VelocityContext. 42 * 43 * All thanks to Fedor for the chaining idea. 44 * 45 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> 46 * @author <a href="mailto:fedor.karpelevitch@home.com">Fedor Karpelevitch</a> 47 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 48 * @version $Id: AbstractContext.java 702218 2008-10-06 18:15:18Z nbubna $ 49 */ 50 51 public abstract class AbstractContext extends InternalContextBase 52 implements Context 53 { 54 /** 55 * the chained Context if any 56 */ 57 private Context innerContext = null; 58 59 /** 60 * Implement to return a value from the context storage. 61 * <br><br> 62 * The implementation of this method is required for proper 63 * operation of a Context implementation in general 64 * Velocity use. 65 * 66 * @param key key whose associated value is to be returned 67 * @return object stored in the context 68 */ 69 public abstract Object internalGet( String key ); 70 71 /** 72 * Implement to put a value into the context storage. 73 * <br><br> 74 * The implementation of this method is required for 75 * proper operation of a Context implementation in 76 * general Velocity use. 77 * 78 * @param key key with which to associate the value 79 * @param value value to be associated with the key 80 * @return previously stored value if exists, or null 81 */ 82 public abstract Object internalPut( String key, Object value ); 83 84 /** 85 * Implement to determine if a key is in the storage. 86 * <br><br> 87 * Currently, this method is not used internally by 88 * the Velocity engine. 89 * 90 * @param key key to test for existance 91 * @return true if found, false if not 92 */ 93 public abstract boolean internalContainsKey(Object key); 94 95 /** 96 * Implement to return an object array of key 97 * strings from your storage. 98 * <br><br> 99 * Currently, this method is not used internally by 100 * the Velocity engine. 101 * 102 * @return array of keys 103 */ 104 public abstract Object[] internalGetKeys(); 105 106 /** 107 * I mplement to remove an item from your storage. 108 * <br><br> 109 * Currently, this method is not used internally by 110 * the Velocity engine. 111 * 112 * @param key key to remove 113 * @return object removed if exists, else null 114 */ 115 public abstract Object internalRemove(Object key); 116 117 /** 118 * default CTOR 119 */ 120 public AbstractContext() 121 { 122 } 123 124 /** 125 * Chaining constructor accepts a Context argument. 126 * It will relay get() operations into this Context 127 * in the even the 'local' get() returns null. 128 * 129 * @param inner context to be chained 130 */ 131 public AbstractContext( Context inner ) 132 { 133 innerContext = inner; 134 135 /* 136 * now, do a 'forward pull' of event cartridge so 137 * it's accessable, bringing to the top level. 138 */ 139 140 if (innerContext instanceof InternalEventContext ) 141 { 142 attachEventCartridge( ( (InternalEventContext) innerContext).getEventCartridge() ); 143 } 144 } 145 146 /** 147 * Adds a name/value pair to the context. 148 * 149 * @param key The name to key the provided value with. 150 * @param value The corresponding value. 151 * @return Object that was replaced in the the Context if 152 * applicable or null if not. 153 */ 154 public Object put(String key, Object value) 155 { 156 /* 157 * don't even continue if key is null 158 */ 159 if (key == null) 160 { 161 return null; 162 } 163 164 return internalPut(key, value); 165 } 166 167 /** 168 * Gets the value corresponding to the provided key from the context. 169 * 170 * Supports the chaining context mechanism. If the 'local' context 171 * doesn't have the value, we try to get it from the chained context. 172 * 173 * @param key The name of the desired value. 174 * @return The value corresponding to the provided key or null if 175 * the key param is null. 176 */ 177 public Object get(String key) 178 { 179 /* 180 * punt if key is null 181 */ 182 183 if (key == null) 184 { 185 return null; 186 } 187 188 /* 189 * get the object for this key. If null, and we are chaining another Context 190 * call the get() on it. 191 */ 192 193 Object o = internalGet( key ); 194 195 if (o == null && innerContext != null) 196 { 197 o = innerContext.get( key ); 198 } 199 200 return o; 201 } 202 203 /** 204 * Indicates whether the specified key is in the context. Provided for 205 * debugging purposes. 206 * 207 * @param key The key to look for. 208 * @return true if the key is in the context, false if not. 209 */ 210 public boolean containsKey(Object key) 211 { 212 if (key == null) 213 { 214 return false; 215 } 216 217 boolean exists = internalContainsKey(key); 218 if (!exists && innerContext != null) 219 { 220 exists = innerContext.containsKey(key); 221 } 222 223 return exists; 224 } 225 226 /** 227 * Get all the keys for the values in the context 228 * @return Object[] of keys in the Context. Does not return 229 * keys in chained context. 230 */ 231 public Object[] getKeys() 232 { 233 return internalGetKeys(); 234 } 235 236 /** 237 * Removes the value associated with the specified key from the context. 238 * 239 * @param key The name of the value to remove. 240 * @return The value that the key was mapped to, or <code>null</code> 241 * if unmapped. 242 */ 243 public Object remove(Object key) 244 { 245 if (key == null) 246 { 247 return null; 248 } 249 250 return internalRemove(key); 251 } 252 253 /** 254 * returns innerContext if one is chained 255 * 256 * @return Context if chained, <code>null</code> if not 257 */ 258 public Context getChainedContext() 259 { 260 return innerContext; 261 } 262 263 } 264 265 266