org.apache.velocity.context.AbstractContext Maven / Gradle / Ivy
The newest version!
package 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 :
*
*
* - Null keys and values are accepted and basically dropped.
*
- If you place an object into the context with a null key, it
* will be ignored and logged.
*
- If you try to place a null into the context with any key, it
* will be dropped and logged.
*
*
* The default implementation of this for application use is
* org.apache.velocity.VelocityContext.
*
* All thanks to Fedor for the chaining idea.
*
* @author Geir Magnusson Jr.
* @author Fedor Karpelevitch
* @author Jason van Zyl
* @version $Id$
*/
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.
*
* 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.
*
* 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.
*
* Currently, this method is not used internally by
* the Velocity engine.
*
* @param key key to test for existence
* @return true if found, false if not
*/
public abstract boolean internalContainsKey(String key);
/**
* Implement to return an object array of key
* strings from your storage.
*
* Currently, this method is not used internally by
* the Velocity engine.
*
* @return array of keys
*/
public abstract String[] internalGetKeys();
/**
* Implement to remove an item from your storage.
*
* 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(String 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 accessible, 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.
*/
@Override
public Object put(String key, Object value)
{
/*
* don't even continue if key is null
*/
if (key == null)
{
return null;
}
/*
* We always use string interning here:
* 1) speed is generally less critical when populating the context than during parsing or rendering
* 2) a context key is very likely to be used several times, or even a lot of times, in the template (but does it save memory if runtime.string_interning is false?)
* 3) last but not least: we don't have access to RuntimeServices from here, the reengineering would be painful...
*/
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.
*/
@Override
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.
*/
@Override
public boolean containsKey(String 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.
*/
@Override
public String[] 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 null
* if unmapped.
*/
@Override
public Object remove(String key)
{
if (key == null)
{
return null;
}
return internalRemove(key);
}
/**
* returns innerContext if one is chained
*
* @return Context if chained, null
if not
*/
public Context getChainedContext()
{
return innerContext;
}
}