This project has retired. For details please refer to its Attic page.
BasicAttributeContext xref
View Javadoc

1   /*
2    * $Id: BasicAttributeContext.java 788344 2009-06-25 12:47:40Z apetrelli $
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  package org.apache.tiles;
23  
24  import java.io.Serializable;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.Iterator;
29  import java.util.Map;
30  import java.util.Set;
31  
32  
33  /***
34   * Basic implementation for <code>AttributeContext</code>.
35   *
36   * @version $Rev: 788344 $ $Date: 2009-06-25 14:47:40 +0200 (gio, 25 giu 2009) $
37   * @since 2.1.0
38   */
39  public class BasicAttributeContext implements AttributeContext, Serializable {
40  
41      /***
42       * The template attribute, to render a template.
43       *
44       * @since 2.1.2
45       */
46      protected Attribute templateAttribute;
47  
48      /***
49       * Associated ViewPreparer URL or classname, if defined.
50       *
51       * @since 2.1.0
52       */
53      protected String preparer = null;
54  
55      /***
56       * Template attributes.
57       * @since 2.1.0
58       */
59      protected Map<String, Attribute> attributes = null;
60  
61      /***
62       * Cascaded template attributes.
63       * @since 2.1.0
64       */
65      protected Map<String, Attribute> cascadedAttributes = null;
66  
67      /***
68       * Constructor.
69       *
70       * @since 2.1.0
71       */
72      public BasicAttributeContext() {
73          super();
74      }
75  
76      /***
77       * Constructor.
78       * Create a context and set specified attributes.
79       *
80       * @param attributes Attributes to initialize context.
81       * @since 2.1.0
82       */
83      public BasicAttributeContext(Map<String, Attribute> attributes) {
84          if (attributes != null) {
85              this.attributes = deepCopyAttributeMap(attributes);
86          }
87      }
88  
89      /***
90       * Copy constructor.
91       *
92       * @param context The constructor to copy.
93       * @since 2.1.0
94       */
95      public BasicAttributeContext(AttributeContext context) {
96          if (context instanceof BasicAttributeContext) {
97              copyBasicAttributeContext((BasicAttributeContext) context);
98          } else {
99              Attribute parentTemplateAttribute = context.getTemplateAttribute();
100             if (parentTemplateAttribute != null) {
101                 this.templateAttribute = new Attribute(parentTemplateAttribute);
102             }
103             this.preparer = context.getPreparer();
104             this.attributes = new HashMap<String, Attribute>();
105             for (String name : context.getLocalAttributeNames()) {
106                 attributes.put(name, new Attribute(context.getLocalAttribute(name)));
107             }
108             inheritCascadedAttributes(context);
109         }
110     }
111 
112     /***
113      * Copy constructor.
114      *
115      * @param context The constructor to copy.
116      * @since 2.1.0
117      */
118     public BasicAttributeContext(BasicAttributeContext context) {
119         copyBasicAttributeContext(context);
120     }
121 
122     /*** {@inheritDoc} */
123     public Attribute getTemplateAttribute() {
124         return templateAttribute;
125     }
126 
127     /*** {@inheritDoc} */
128     public void setTemplateAttribute(Attribute templateAttribute) {
129         this.templateAttribute = templateAttribute;
130     }
131 
132     /*** {@inheritDoc} */
133     public String getPreparer() {
134         return preparer;
135     }
136 
137     /*** {@inheritDoc} */
138     public void setPreparer(String url) {
139         this.preparer = url;
140     }
141 
142     /*** {@inheritDoc} */
143     public void inheritCascadedAttributes(AttributeContext context) {
144         if (context instanceof BasicAttributeContext) {
145             copyCascadedAttributes((BasicAttributeContext) context);
146         } else {
147             this.cascadedAttributes = new HashMap<String, Attribute>();
148             for (String name : context.getCascadedAttributeNames()) {
149                 cascadedAttributes.put(name, new Attribute(context
150                         .getCascadedAttribute(name)));
151             }
152         }
153     }
154 
155     /*** {@inheritDoc} */
156     public void inherit(AttributeContext parent) {
157         if (parent instanceof BasicAttributeContext) {
158             inherit((BasicAttributeContext) parent);
159         } else {
160             // Inheriting template, roles and preparer.
161             Attribute parentTemplateAttribute = parent.getTemplateAttribute();
162             inheritParentTemplateAttribute(parentTemplateAttribute);
163             if (preparer == null) {
164                 preparer = parent.getPreparer();
165             }
166 
167             // Inheriting attributes.
168             Set<String> names = parent.getCascadedAttributeNames();
169             if (names != null && !names.isEmpty()) {
170                 for (String name : names) {
171                     Attribute attribute = parent.getCascadedAttribute(name);
172                     Attribute destAttribute = getCascadedAttribute(name);
173                     if (destAttribute == null) {
174                         putAttribute(name, attribute, true);
175                     } else if (attribute instanceof ListAttribute
176                             && destAttribute instanceof ListAttribute
177                             && ((ListAttribute) destAttribute).isInherit()) {
178                         ((ListAttribute) destAttribute).inherit((ListAttribute) attribute);
179                     }
180                 }
181             }
182             names = parent.getLocalAttributeNames();
183             if (names != null && !names.isEmpty()) {
184                 for (String name : names) {
185                     Attribute attribute = parent.getLocalAttribute(name);
186                     Attribute destAttribute = getLocalAttribute(name);
187                     if (destAttribute == null) {
188                         putAttribute(name, attribute, false);
189                     } else if (attribute instanceof ListAttribute
190                             && destAttribute instanceof ListAttribute
191                             && ((ListAttribute) destAttribute).isInherit()) {
192                         ((ListAttribute) destAttribute).inherit((ListAttribute) attribute);
193                     }
194                 }
195             }
196         }
197     }
198 
199     /***
200      * Inherits the attribute context, inheriting, i.e. copying if not present,
201      * the attributes.
202      *
203      * @param parent The attribute context to inherit.
204      * @since 2.1.0
205      */
206     public void inherit(BasicAttributeContext parent) {
207         // Set template, roles and preparer if not set.
208         inheritParentTemplateAttribute(parent.getTemplateAttribute());
209         if (preparer == null) {
210             preparer = parent.preparer;
211         }
212 
213         // Sets attributes.
214         cascadedAttributes = addMissingAttributes(
215                 ((BasicAttributeContext) parent).cascadedAttributes,
216                 cascadedAttributes);
217         attributes = addMissingAttributes(
218                 ((BasicAttributeContext) parent).attributes, attributes);
219     }
220 
221     /***
222      * Add all attributes to this context.
223      * Copies all of the mappings from the specified attribute map to this context.
224      * New attribute mappings will replace any mappings that this context had for any of the keys
225      * currently in the specified attribute map.
226      *
227      * @param newAttributes Attributes to add.
228      * @since 2.1.0
229      */
230     public void addAll(Map<String, Attribute> newAttributes) {
231         if (newAttributes == null) {
232             return;
233         }
234 
235         if (attributes == null) {
236             attributes = new HashMap<String, Attribute>(newAttributes);
237             return;
238         }
239 
240         attributes.putAll(newAttributes);
241     }
242 
243     /***
244      * Add all missing attributes to this context.
245      * Copies all of the mappings from the specified attributes map to this context.
246      * New attribute mappings will be added only if they don't already exist in
247      * this context.
248      *
249      * @param defaultAttributes Attributes to add.
250      * @since 2.1.0
251      */
252     public void addMissing(Map<String, Attribute> defaultAttributes) {
253         if (defaultAttributes == null) {
254             return;
255         }
256 
257         if (attributes == null) {
258             attributes = new HashMap<String, Attribute>(defaultAttributes);
259             if (cascadedAttributes == null || cascadedAttributes.isEmpty()) {
260                 return;
261             }
262         }
263 
264         Set<Map.Entry<String, Attribute>> entries = defaultAttributes.entrySet();
265         for (Map.Entry<String, Attribute> entry : entries) {
266             String key = entry.getKey();
267             if (!attributes.containsKey(key)
268                     && (cascadedAttributes == null || cascadedAttributes
269                             .containsKey(key))) {
270                 attributes.put(entry.getKey(), entry.getValue());
271             }
272         }
273     }
274 
275     /*** {@inheritDoc} */
276     public Attribute getAttribute(String name) {
277         Attribute retValue = null;
278         if (attributes != null) {
279             retValue = attributes.get(name);
280         }
281 
282         if (retValue == null && cascadedAttributes != null) {
283             retValue = cascadedAttributes.get(name);
284         }
285 
286         return retValue;
287     }
288 
289     /*** {@inheritDoc} */
290     public Attribute getLocalAttribute(String name) {
291         if (attributes == null) {
292             return null;
293         }
294 
295         return attributes.get(name);
296     }
297 
298     /*** {@inheritDoc} */
299     public Attribute getCascadedAttribute(String name) {
300         if (cascadedAttributes == null) {
301             return null;
302         }
303 
304         return cascadedAttributes.get(name);
305     }
306 
307     /*** {@inheritDoc} */
308     public Iterator<String> getAttributeNames() {
309         Set<String> attributeSet = null;
310 
311         if (attributes != null && !attributes.isEmpty()) {
312             attributeSet = new HashSet<String>(attributes
313                     .keySet());
314             if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) {
315                 attributeSet.addAll(cascadedAttributes.keySet());
316             }
317         } else if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) {
318             attributeSet = new HashSet<String>(cascadedAttributes.keySet());
319         }
320 
321         if (attributeSet != null) {
322             return attributeSet.iterator();
323         } else {
324             return new ArrayList<String>().iterator();
325         }
326     }
327 
328     /*** {@inheritDoc} */
329     public Set<String> getLocalAttributeNames() {
330         if (attributes != null && !attributes.isEmpty()) {
331             return attributes.keySet();
332         } else {
333             return null;
334         }
335     }
336 
337     /*** {@inheritDoc} */
338     public Set<String> getCascadedAttributeNames() {
339         if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) {
340             return cascadedAttributes.keySet();
341         } else {
342             return null;
343         }
344     }
345 
346     /*** {@inheritDoc} */
347     public void putAttribute(String name, Attribute value) {
348         if (attributes == null) {
349             attributes = new HashMap<String, Attribute>();
350         }
351 
352         attributes.put(name, value);
353     }
354 
355     /*** {@inheritDoc} */
356     public void putAttribute(String name, Attribute value, boolean cascade) {
357         Map<String, Attribute> mapToUse;
358         if (cascade) {
359             if (cascadedAttributes == null) {
360                 cascadedAttributes = new HashMap<String, Attribute>();
361             }
362             mapToUse = cascadedAttributes;
363         } else {
364             if (attributes == null) {
365                 attributes = new HashMap<String, Attribute>();
366             }
367             mapToUse = attributes;
368         }
369         mapToUse.put(name, value);
370     }
371 
372     /*** {@inheritDoc} */
373     public void clear() {
374         templateAttribute = null;
375         preparer = null;
376         attributes.clear();
377         cascadedAttributes.clear();
378     }
379 
380     /***
381      * Inherits the parent template attribute.
382      *
383      * @param parentTemplateAttribute The parent template attribute.
384      */
385     private void inheritParentTemplateAttribute(
386             Attribute parentTemplateAttribute) {
387         if (parentTemplateAttribute != null) {
388             if (templateAttribute == null) {
389                 templateAttribute = new Attribute(parentTemplateAttribute);
390             } else {
391                 templateAttribute.inherit(parentTemplateAttribute);
392             }
393         }
394     }
395 
396     /***
397      * Copies a BasicAttributeContext in an easier way.
398      *
399      * @param context The context to copy.
400      */
401     private void copyBasicAttributeContext(BasicAttributeContext context) {
402         Attribute parentTemplateAttribute = context.getTemplateAttribute();
403         if (parentTemplateAttribute != null) {
404             this.templateAttribute = new Attribute(parentTemplateAttribute);
405         }
406         preparer = context.preparer;
407         if (context.attributes != null && !context.attributes.isEmpty()) {
408             attributes = deepCopyAttributeMap(context.attributes);
409         }
410         copyCascadedAttributes(context);
411     }
412 
413     /***
414      * Copies the cascaded attributes to the current context.
415      *
416      * @param context The context to copy from.
417      */
418     private void copyCascadedAttributes(BasicAttributeContext context) {
419         if (context.cascadedAttributes != null
420                 && !context.cascadedAttributes.isEmpty()) {
421             cascadedAttributes = deepCopyAttributeMap(context.cascadedAttributes);
422         }
423     }
424 
425     /***
426      * Adds missing attributes to the destination map.
427      *
428      * @param source The source attribute map.
429      * @param destination The destination attribute map.
430      * @return The destination attribute map if not null, a new one otherwise.
431      */
432     private Map<String, Attribute> addMissingAttributes(Map<String, Attribute> source,
433             Map<String, Attribute> destination) {
434         if (source != null && !source.isEmpty()) {
435             if (destination == null) {
436                 destination = new HashMap<String, Attribute>();
437             }
438             for (Map.Entry<String, Attribute> entry : source.entrySet()) {
439                 String key = entry.getKey();
440                 Attribute destAttribute = destination.get(key);
441                 if (destAttribute == null) {
442                     destination.put(key, entry.getValue());
443                 } else if (destAttribute instanceof ListAttribute
444                         && entry.getValue() instanceof ListAttribute
445                         && ((ListAttribute) destAttribute).isInherit()) {
446                     ((ListAttribute) destAttribute)
447                             .inherit((ListAttribute) entry.getValue());
448                 }
449             }
450         }
451 
452         return destination;
453     }
454 
455     /***
456      * Deep copies the attribute map, by creating clones (using copy
457      * constructors) of the attributes.
458      *
459      * @param attributes The attribute map to copy.
460      * @return The copied map.
461      */
462     private Map<String, Attribute> deepCopyAttributeMap(
463             Map<String, Attribute> attributes) {
464         Map<String, Attribute> retValue = new HashMap<String, Attribute>(attributes.size());
465         for (Map.Entry<String, Attribute> entry : attributes.entrySet()) {
466             Attribute toCopy = entry.getValue();
467             if (toCopy != null) {
468                 retValue.put(entry.getKey(), toCopy.clone());
469             }
470         }
471         return retValue;
472     }
473 }