aboutsummaryrefslogtreecommitdiff
path: root/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java
diff options
context:
space:
mode:
Diffstat (limited to 'velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java')
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java274
1 files changed, 274 insertions, 0 deletions
diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java b/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java
new file mode 100644
index 00000000..2fba374a
--- /dev/null
+++ b/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java
@@ -0,0 +1,274 @@
+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 :
+ *
+ * <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
+ * 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$
+ */
+
+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 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.
+ * <br><br>
+ * 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.
+ * <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(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 <code>null</code>
+ * 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, <code>null</code> if not
+ */
+ public Context getChainedContext()
+ {
+ return innerContext;
+ }
+
+}