1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  package org.apache.tiles.impl.mgmt;
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.tiles.Definition;
27  import org.apache.tiles.TilesContainer;
28  import org.apache.tiles.TilesContainerWrapper;
29  import org.apache.tiles.definition.NoSuchDefinitionException;
30  import org.apache.tiles.mgmt.MutableTilesContainer;
31  import org.apache.tiles.request.Request;
32  
33  
34  
35  
36  
37  
38  
39  public class CachingTilesContainer extends TilesContainerWrapper implements MutableTilesContainer {
40  
41      
42  
43  
44      private static final String DEFAULT_DEFINITIONS_ATTRIBUTE_NAME =
45          "org.apache.tiles.impl.mgmt.DefinitionManager.DEFINITIONS";
46  
47      
48  
49  
50      private String definitionsAttributeName;
51  
52      
53  
54  
55  
56      public CachingTilesContainer(TilesContainer originalContainer) {
57          super(originalContainer);
58          definitionsAttributeName = DEFAULT_DEFINITIONS_ATTRIBUTE_NAME;
59      }
60  
61      
62  
63  
64  
65  
66  
67      public CachingTilesContainer(TilesContainer originalContainer, String definitionsAttributeName) {
68          super(originalContainer);
69          this.definitionsAttributeName = definitionsAttributeName;
70          if (this.definitionsAttributeName == null) {
71              this.definitionsAttributeName = DEFAULT_DEFINITIONS_ATTRIBUTE_NAME;
72          }
73      }
74  
75      
76  
77  
78  
79  
80  
81  
82  
83  
84      public Definition getDefinition(String definition,
85              Request request) {
86          Definition retValue = null;
87          retValue = getCustomDefinition(definition, request);
88          if (retValue == null) {
89              retValue = super.getDefinition(definition, request);
90          }
91          return retValue;
92      }
93  
94      
95      @Override
96      public boolean isValidDefinition(String definition, Request request) {
97          if (getCustomDefinition(definition, request) != null) {
98              return true;
99          }
100         return super.isValidDefinition(definition, request);
101     }
102 
103     
104     @Override
105     public void register(Definition definition, Request request) {
106         Map<String, Definition> definitions = getOrCreateDefinitions(request);
107         if (definition.getName() == null) {
108             definition.setName(getNextUniqueDefinitionName(definitions));
109         }
110 
111         if (definition.isExtending()) {
112             this.resolveInheritance(definition, request);
113         }
114 
115         definitions.put(definition.getName(), definition);
116     }
117 
118     
119     @Override
120     public void render(String definition, Request request) {
121         Definition toRender = getDefinition(definition, request);
122         if (toRender == null) {
123             throw new NoSuchDefinitionException(
124                     "Cannot find definition named '" + definition + "'");
125         }
126         super.render(toRender, request);
127     }
128 
129     
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
141 
142     private void resolveInheritance(Definition definition,
143             Request request) {
144         
145         if (!definition.isExtending()) {
146             return;
147         }
148 
149         String parentDefinitionName = definition.getExtends();
150 
151         boolean recurse = true;
152         Definition parent = getCustomDefinition(parentDefinitionName, request);
153         if (parent == null) {
154             parent = container.getDefinition(parentDefinitionName, request);
155             recurse = false;
156         }
157 
158         if (parent == null) {
159             throw new NoSuchDefinitionException(
160                     "Error while resolving definition inheritance: child '"
161                             + definition.getName()
162                             + "' can't find its ancestor '"
163                             + parentDefinitionName
164                             + "'. Please check your description file.");
165         }
166 
167         
168         if (recurse) {
169             resolveInheritance(parent, request);
170         }
171         definition.inherit(parent);
172     }
173 
174     
175 
176 
177 
178 
179 
180     @SuppressWarnings("unchecked")
181     private Map<String, Definition> getDefinitions(
182             Request request) {
183         return (Map<String, Definition>) request.getContext("request")
184                 .get(definitionsAttributeName);
185     }
186 
187     
188 
189 
190 
191 
192 
193 
194     @SuppressWarnings("unchecked")
195     private Map<String, Definition> getOrCreateDefinitions(
196             Request request) {
197         Map<String, Definition> definitions =
198             (Map<String, Definition>) request.getContext("request").get(definitionsAttributeName);
199         if (definitions == null) {
200             definitions = new HashMap<String, Definition>();
201             request.getContext("request")
202                     .put(definitionsAttributeName, definitions);
203         }
204 
205         return definitions;
206     }
207 
208     
209 
210 
211 
212 
213 
214 
215     private String getNextUniqueDefinitionName(
216             Map<String, Definition> definitions) {
217         String candidate;
218         int anonymousDefinitionIndex = 1;
219 
220         do {
221             candidate = "$anonymousMutableDefinition" + anonymousDefinitionIndex;
222             anonymousDefinitionIndex++;
223         } while (definitions.containsKey(candidate));
224 
225         return candidate;
226     }
227 
228     
229 
230 
231 
232 
233 
234 
235     private Definition getCustomDefinition(String definition, Request request) {
236         Map<String, Definition> definitions = getDefinitions(request);
237         if (definitions != null) {
238             return definitions.get(definition);
239         }
240         return null;
241     }
242 }