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