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