View Javadoc

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 463298 2006-10-12 16:10:32Z henning $
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 or value is null
158          */
159 
160         if (key == null)
161         {
162             return null;
163         }
164         else if (value == null)
165         {
166             return null;
167         }
168 
169         return internalPut(key, value);
170     }
171 
172     /**
173      *  Gets the value corresponding to the provided key from the context.
174      *
175      *  Supports the chaining context mechanism.  If the 'local' context
176      *  doesn't have the value, we try to get it from the chained context.
177      *
178      *  @param key The name of the desired value.
179      *  @return    The value corresponding to the provided key or null if
180      *             the key param is null.
181      */
182     public Object get(String key)
183     {
184         /*
185          *  punt if key is null
186          */
187 
188         if (key == null)
189         {
190             return null;
191         }
192 
193         /*
194          *  get the object for this key.  If null, and we are chaining another Context
195          *  call the get() on it.
196          */
197 
198         Object o = internalGet( key );
199 
200         if (o == null && innerContext != null)
201         {
202             o = innerContext.get( key );
203         }
204 
205         return o;
206     }
207 
208     /**
209      *  Indicates whether the specified key is in the context.  Provided for
210      *  debugging purposes.
211      *
212      * @param key The key to look for.
213      * @return true if the key is in the context, false if not.
214      */
215     public boolean containsKey(Object key)
216     {
217         if (key == null)
218         {
219             return false;
220         }
221 
222         return internalContainsKey(key);
223     }
224 
225     /**
226      *  Get all the keys for the values in the context
227      *  @return Object[] of keys in the Context. Does not return
228      *          keys in chained context.
229      */
230     public Object[] getKeys()
231     {
232         return internalGetKeys();
233     }
234 
235     /**
236      * Removes the value associated with the specified key from the context.
237      *
238      * @param key The name of the value to remove.
239      * @return    The value that the key was mapped to, or <code>null</code>
240      *            if unmapped.
241      */
242     public Object remove(Object key)
243     {
244         if (key == null)
245         {
246             return null;
247         }
248 
249         return internalRemove(key);
250     }
251 
252     /**
253      *  returns innerContext if one is chained
254      *
255      *  @return Context if chained, <code>null</code> if not
256      */
257     public Context getChainedContext()
258     {
259         return innerContext;
260     }
261 
262 }
263 
264 
265