package bboss.org.apache.velocity.context; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * This class is the abstract base class for all conventional * Velocity Context implementations. Simply extend this class * and implement the abstract routines that access your preferred * storage method. * * Takes care of context chaining. * * Also handles / enforces policy on null keys and values : * * <ul> * <li> Null keys and values are accepted and basically dropped. * <li> If you place an object into the context with a null key, it * will be ignored and logged. * <li> If you try to place a null into the context with any key, it * will be dropped and logged. * </ul> * * The default implementation of this for application use is * bboss.org.apache.velocity.VelocityContext. * * All thanks to Fedor for the chaining idea. * * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> * @author <a href="mailto:fedor.karpelevitch@home.com">Fedor Karpelevitch</a> * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> * @version $Id: AbstractContext.java 732250 2009-01-07 07:37:10Z byron $ */ public abstract class AbstractContext extends InternalContextBase implements Context { /** * the chained Context if any */ private Context innerContext = null; /** * Implement to return a value from the context storage. * <br><br> * The implementation of this method is required for proper * operation of a Context implementation in general * Velocity use. * * @param key key whose associated value is to be returned * @return object stored in the context */ public abstract Object internalGet( String key ); /** * Implement to put a value into the context storage. * <br><br> * The implementation of this method is required for * proper operation of a Context implementation in * general Velocity use. * * @param key key with which to associate the value * @param value value to be associated with the key * @return previously stored value if exists, or null */ public abstract Object internalPut( String key, Object value ); /** * Implement to determine if a key is in the storage. * <br><br> * Currently, this method is not used internally by * the Velocity engine. * * @param key key to test for existance * @return true if found, false if not */ public abstract boolean internalContainsKey(Object key); /** * Implement to return an object array of key * strings from your storage. * <br><br> * Currently, this method is not used internally by * the Velocity engine. * * @return array of keys */ public abstract Object[] internalGetKeys(); /** * I mplement to remove an item from your storage. * <br><br> * Currently, this method is not used internally by * the Velocity engine. * * @param key key to remove * @return object removed if exists, else null */ public abstract Object internalRemove(Object key); /** * default CTOR */ public AbstractContext() { } /** * Chaining constructor accepts a Context argument. * It will relay get() operations into this Context * in the even the 'local' get() returns null. * * @param inner context to be chained */ public AbstractContext( Context inner ) { innerContext = inner; /* * now, do a 'forward pull' of event cartridge so * it's accessable, bringing to the top level. */ if (innerContext instanceof InternalEventContext ) { attachEventCartridge( ( (InternalEventContext) innerContext).getEventCartridge() ); } } /** * Adds a name/value pair to the context. * * @param key The name to key the provided value with. * @param value The corresponding value. * @return Object that was replaced in the the Context if * applicable or null if not. */ public Object put(String key, Object value) { /* * don't even continue if key is null */ if (key == null) { return null; } return internalPut(key.intern(), value); } /** * Gets the value corresponding to the provided key from the context. * * Supports the chaining context mechanism. If the 'local' context * doesn't have the value, we try to get it from the chained context. * * @param key The name of the desired value. * @return The value corresponding to the provided key or null if * the key param is null. */ public Object get(String key) { /* * punt if key is null */ if (key == null) { return null; } /* * get the object for this key. If null, and we are chaining another Context * call the get() on it. */ Object o = internalGet( key ); if (o == null && innerContext != null) { o = innerContext.get( key ); } return o; } /** * Indicates whether the specified key is in the context. Provided for * debugging purposes. * * @param key The key to look for. * @return true if the key is in the context, false if not. */ public boolean containsKey(Object key) { if (key == null) { return false; } boolean exists = internalContainsKey(key); if (!exists && innerContext != null) { exists = innerContext.containsKey(key); } return exists; } /** * Get all the keys for the values in the context * @return Object[] of keys in the Context. Does not return * keys in chained context. */ public Object[] getKeys() { return internalGetKeys(); } /** * Removes the value associated with the specified key from the context. * * @param key The name of the value to remove. * @return The value that the key was mapped to, or <code>null</code> * if unmapped. */ public Object remove(Object key) { if (key == null) { return null; } return internalRemove(key); } /** * returns innerContext if one is chained * * @return Context if chained, <code>null</code> if not */ public Context getChainedContext() { return innerContext; } }