View Javadoc

1   package org.apache.velocity.runtime.directive;
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  import java.util.AbstractMap;
23  import java.util.HashMap;
24  import java.util.Map;
25  import java.util.Set;
26  import org.apache.velocity.Template;
27  
28  /**
29   * This handles context scoping and metadata for directives.
30   *
31   * @author Nathan Bubna
32   * @version $Id$
33   */
34  public class Scope extends AbstractMap
35  {
36      private Map storage;
37      private Object replaced;
38      private Scope parent;
39      private Info info;
40      protected final Object owner;
41  
42      public Scope(Object owner, Object previous)
43      {
44          this.owner = owner;
45          if (previous != null)
46          {
47              try
48              {
49                  this.parent = (Scope)previous;
50              }
51              catch (ClassCastException cce)
52              {
53                  this.replaced = previous;
54              }
55          }
56      }
57  
58      private Map getStorage()
59      {
60          if (storage == null)
61          {
62              storage = new HashMap();
63          }
64          return storage;
65      }
66  
67      public Set entrySet()
68      {
69          return getStorage().entrySet();
70      }
71  
72      public Object get(Object key)
73      {
74          Object o = super.get(key);
75          if (o == null && parent != null && !containsKey(key))
76          {
77              return parent.get(key);
78          }
79          return o;
80      }
81  
82      public Object put(Object key, Object value)
83      {
84          return getStorage().put(key, value);
85      }
86  
87      /**
88       * Allows #stop to easily trigger the proper StopCommand for this scope.
89       */
90      protected void stop()
91      {
92          throw new StopCommand(owner);
93      }
94  
95      /**
96       * Returns the number of control arguments of this type
97       * that are stacked up.  This is the distance between this
98       * instance and the topmost instance, plus one. This value
99       * will never be negative or zero.
100      */
101     protected int getDepth()
102     {
103         if (parent == null)
104         {
105             return 1;
106         }
107         return parent.getDepth() + 1;
108     }
109 
110     /**
111      * Returns the topmost parent control reference, retrieved
112      * by simple recursion on {@link #getParent}.
113      */
114     public Scope getTopmost()
115     {
116         if (parent == null)
117         {
118             return this;
119         }
120         return parent.getTopmost();
121     }
122 
123     /**
124      * Returns the parent control reference overridden by the placement
125      * of this instance in the context.
126      */
127     public Scope getParent()
128     {
129         return parent;
130     }
131 
132     /**
133      * Returns the user's context reference overridden by the placement
134      * of this instance in the context.  If there was none (as is hoped),
135      * then this will return null.  This never returns parent controls;
136      * those are returned by {@link #getParent}.
137      */
138     public Object getReplaced()
139     {
140         if (replaced == null && parent != null)
141         {
142             return parent.getReplaced();
143         }
144         return replaced;
145     }
146 
147     /**
148      * Returns info about the current scope for debugging purposes.
149      */
150     public Info getInfo()
151     {
152         if (info == null)
153         {
154             info = new Info(this, owner);
155         }
156         return info;
157     }
158 
159     /**
160      * Class to encapsulate and provide access to info about
161      * the current scope for debugging.
162      */
163     public static class Info
164     {
165         private Scope scope;
166         private Directive directive;
167         private Template template;
168 
169         public Info(Scope scope, Object owner)
170         {
171             if (owner instanceof Directive)
172             {
173                 directive = (Directive)owner;
174             }
175             if (owner instanceof Template)
176             {
177                 template = (Template)owner;
178             }
179         }
180 
181         public int getDepth()
182         {
183             return scope.getDepth();
184         }
185 
186         public String getName()
187         {
188             if (directive != null)
189             {
190                 return directive.getName();
191             }
192             if (template != null)
193             {
194                 return template.getName();
195             }
196             return null;
197         }
198 
199         public int getLine()
200         {
201             if (directive != null)
202             {
203                 return directive.getLine();
204             }
205             return 0;
206         }
207 
208         public int getColumn()
209         {
210             if (directive != null)
211             {
212                 return directive.getColumn();
213             }
214             return 0;
215         }
216 
217         public String getType()
218         {
219             if (directive != null)
220             {
221                 switch (directive.getType())
222                 {
223                     case Directive.BLOCK:
224                         return "block";
225                     case Directive.LINE:
226                         return "line";
227                 }
228             }
229             if (template != null)
230             {
231                 return template.getEncoding();
232             }
233             return null;
234         }
235 
236         public String getTemplate()
237         {
238             if (directive != null)
239             {
240                 return directive.getTemplateName();
241             }
242             if (template != null)
243             {
244                 return template.getName();
245             }
246             return null;
247         }
248     }
249 
250 }