001: package org.apache.velocity.context;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: /**
023: * This class is the abstract base class for all conventional
024: * Velocity Context implementations. Simply extend this class
025: * and implement the abstract routines that access your preferred
026: * storage method.
027: *
028: * Takes care of context chaining.
029: *
030: * Also handles / enforces policy on null keys and values :
031: *
032: * <ul>
033: * <li> Null keys and values are accepted and basically dropped.
034: * <li> If you place an object into the context with a null key, it
035: * will be ignored and logged.
036: * <li> If you try to place a null into the context with any key, it
037: * will be dropped and logged.
038: * </ul>
039: *
040: * The default implementation of this for application use is
041: * org.apache.velocity.VelocityContext.
042: *
043: * All thanks to Fedor for the chaining idea.
044: *
045: * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
046: * @author <a href="mailto:fedor.karpelevitch@home.com">Fedor Karpelevitch</a>
047: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
048: * @version $Id: AbstractContext.java 463298 2006-10-12 16:10:32Z henning $
049: */
050:
051: public abstract class AbstractContext extends InternalContextBase
052: implements Context {
053: /**
054: * the chained Context if any
055: */
056: private Context innerContext = null;
057:
058: /**
059: * Implement to return a value from the context storage.
060: * <br><br>
061: * The implementation of this method is required for proper
062: * operation of a Context implementation in general
063: * Velocity use.
064: *
065: * @param key key whose associated value is to be returned
066: * @return object stored in the context
067: */
068: public abstract Object internalGet(String key);
069:
070: /**
071: * Implement to put a value into the context storage.
072: * <br><br>
073: * The implementation of this method is required for
074: * proper operation of a Context implementation in
075: * general Velocity use.
076: *
077: * @param key key with which to associate the value
078: * @param value value to be associated with the key
079: * @return previously stored value if exists, or null
080: */
081: public abstract Object internalPut(String key, Object value);
082:
083: /**
084: * Implement to determine if a key is in the storage.
085: * <br><br>
086: * Currently, this method is not used internally by
087: * the Velocity engine.
088: *
089: * @param key key to test for existance
090: * @return true if found, false if not
091: */
092: public abstract boolean internalContainsKey(Object key);
093:
094: /**
095: * Implement to return an object array of key
096: * strings from your storage.
097: * <br><br>
098: * Currently, this method is not used internally by
099: * the Velocity engine.
100: *
101: * @return array of keys
102: */
103: public abstract Object[] internalGetKeys();
104:
105: /**
106: * I mplement to remove an item from your storage.
107: * <br><br>
108: * Currently, this method is not used internally by
109: * the Velocity engine.
110: *
111: * @param key key to remove
112: * @return object removed if exists, else null
113: */
114: public abstract Object internalRemove(Object key);
115:
116: /**
117: * default CTOR
118: */
119: public AbstractContext() {
120: }
121:
122: /**
123: * Chaining constructor accepts a Context argument.
124: * It will relay get() operations into this Context
125: * in the even the 'local' get() returns null.
126: *
127: * @param inner context to be chained
128: */
129: public AbstractContext(Context inner) {
130: innerContext = inner;
131:
132: /*
133: * now, do a 'forward pull' of event cartridge so
134: * it's accessable, bringing to the top level.
135: */
136:
137: if (innerContext instanceof InternalEventContext) {
138: attachEventCartridge(((InternalEventContext) innerContext)
139: .getEventCartridge());
140: }
141: }
142:
143: /**
144: * Adds a name/value pair to the context.
145: *
146: * @param key The name to key the provided value with.
147: * @param value The corresponding value.
148: * @return Object that was replaced in the the Context if
149: * applicable or null if not.
150: */
151: public Object put(String key, Object value) {
152: /*
153: * don't even continue if key or value is null
154: */
155:
156: if (key == null) {
157: return null;
158: } else if (value == null) {
159: return null;
160: }
161:
162: return internalPut(key, value);
163: }
164:
165: /**
166: * Gets the value corresponding to the provided key from the context.
167: *
168: * Supports the chaining context mechanism. If the 'local' context
169: * doesn't have the value, we try to get it from the chained context.
170: *
171: * @param key The name of the desired value.
172: * @return The value corresponding to the provided key or null if
173: * the key param is null.
174: */
175: public Object get(String key) {
176: /*
177: * punt if key is null
178: */
179:
180: if (key == null) {
181: return null;
182: }
183:
184: /*
185: * get the object for this key. If null, and we are chaining another Context
186: * call the get() on it.
187: */
188:
189: Object o = internalGet(key);
190:
191: if (o == null && innerContext != null) {
192: o = innerContext.get(key);
193: }
194:
195: return o;
196: }
197:
198: /**
199: * Indicates whether the specified key is in the context. Provided for
200: * debugging purposes.
201: *
202: * @param key The key to look for.
203: * @return true if the key is in the context, false if not.
204: */
205: public boolean containsKey(Object key) {
206: if (key == null) {
207: return false;
208: }
209:
210: return internalContainsKey(key);
211: }
212:
213: /**
214: * Get all the keys for the values in the context
215: * @return Object[] of keys in the Context. Does not return
216: * keys in chained context.
217: */
218: public Object[] getKeys() {
219: return internalGetKeys();
220: }
221:
222: /**
223: * Removes the value associated with the specified key from the context.
224: *
225: * @param key The name of the value to remove.
226: * @return The value that the key was mapped to, or <code>null</code>
227: * if unmapped.
228: */
229: public Object remove(Object key) {
230: if (key == null) {
231: return null;
232: }
233:
234: return internalRemove(key);
235: }
236:
237: /**
238: * returns innerContext if one is chained
239: *
240: * @return Context if chained, <code>null</code> if not
241: */
242: public Context getChainedContext() {
243: return innerContext;
244: }
245:
246: }
|