1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.tiles;
23
24 import static org.apache.tiles.CompareUtil.*;
25
26 import java.io.Serializable;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Set;
30
31
32
33
34
35
36
37
38 public class BasicAttributeContext implements AttributeContext, Serializable {
39
40
41
42
43
44
45 protected Attribute templateAttribute;
46
47
48
49
50
51
52 protected String preparer = null;
53
54
55
56
57
58 protected Map<String, Attribute> attributes = null;
59
60
61
62
63
64 protected Map<String, Attribute> cascadedAttributes = null;
65
66
67
68
69
70
71 public BasicAttributeContext() {
72 }
73
74
75
76
77
78
79
80
81 public BasicAttributeContext(Map<String, Attribute> attributes) {
82 if (attributes != null) {
83 this.attributes = deepCopyAttributeMap(attributes);
84 }
85 }
86
87
88
89
90
91
92
93 public BasicAttributeContext(AttributeContext context) {
94 if (context instanceof BasicAttributeContext) {
95 copyBasicAttributeContext((BasicAttributeContext) context);
96 } else {
97 Attribute parentTemplateAttribute = context.getTemplateAttribute();
98 if (parentTemplateAttribute != null) {
99 this.templateAttribute = new Attribute(parentTemplateAttribute);
100 }
101 this.preparer = context.getPreparer();
102 this.attributes = new HashMap<String, Attribute>();
103 Set<String> parentAttributeNames = context.getLocalAttributeNames();
104 if (parentAttributeNames != null) {
105 for (String name : parentAttributeNames) {
106 attributes.put(name, new Attribute(context.getLocalAttribute(name)));
107 }
108 }
109 inheritCascadedAttributes(context);
110 }
111 }
112
113
114
115
116
117
118
119 public BasicAttributeContext(BasicAttributeContext context) {
120 copyBasicAttributeContext(context);
121 }
122
123
124 public Attribute getTemplateAttribute() {
125 return templateAttribute;
126 }
127
128
129 public void setTemplateAttribute(Attribute templateAttribute) {
130 this.templateAttribute = templateAttribute;
131 }
132
133
134 public String getPreparer() {
135 return preparer;
136 }
137
138
139 public void setPreparer(String url) {
140 this.preparer = url;
141 }
142
143
144 public void inheritCascadedAttributes(AttributeContext context) {
145 if (context instanceof BasicAttributeContext) {
146 copyCascadedAttributes((BasicAttributeContext) context);
147 } else {
148 this.cascadedAttributes = new HashMap<String, Attribute>();
149 Set<String> parentAttributeNames = context.getCascadedAttributeNames();
150 if (parentAttributeNames != null) {
151 for (String name : parentAttributeNames) {
152 cascadedAttributes.put(name, new Attribute(context
153 .getCascadedAttribute(name)));
154 }
155 }
156 }
157 }
158
159
160 public void inherit(AttributeContext parent) {
161 if (parent instanceof BasicAttributeContext) {
162 inherit((BasicAttributeContext) parent);
163 } else {
164
165 Attribute parentTemplateAttribute = parent.getTemplateAttribute();
166 inheritParentTemplateAttribute(parentTemplateAttribute);
167 if (preparer == null) {
168 preparer = parent.getPreparer();
169 }
170
171
172 Set<String> names = parent.getCascadedAttributeNames();
173 if (names != null && !names.isEmpty()) {
174 for (String name : names) {
175 Attribute attribute = parent.getCascadedAttribute(name);
176 Attribute destAttribute = getCascadedAttribute(name);
177 if (destAttribute == null) {
178 putAttribute(name, attribute, true);
179 } else if (attribute instanceof ListAttribute
180 && destAttribute instanceof ListAttribute
181 && ((ListAttribute) destAttribute).isInherit()) {
182 ((ListAttribute) destAttribute).inherit((ListAttribute) attribute);
183 }
184 }
185 }
186 names = parent.getLocalAttributeNames();
187 if (names != null && !names.isEmpty()) {
188 for (String name : names) {
189 Attribute attribute = parent.getLocalAttribute(name);
190 Attribute destAttribute = getLocalAttribute(name);
191 if (destAttribute == null) {
192 putAttribute(name, attribute, false);
193 } else if (attribute instanceof ListAttribute
194 && destAttribute instanceof ListAttribute
195 && ((ListAttribute) destAttribute).isInherit()) {
196 ((ListAttribute) destAttribute).inherit((ListAttribute) attribute);
197 }
198 }
199 }
200 }
201 }
202
203
204
205
206
207
208
209
210 public void inherit(BasicAttributeContext parent) {
211
212 inheritParentTemplateAttribute(parent.getTemplateAttribute());
213 if (preparer == null) {
214 preparer = parent.preparer;
215 }
216
217
218 cascadedAttributes = addMissingAttributes(parent.cascadedAttributes,
219 cascadedAttributes);
220 attributes = addMissingAttributes(parent.attributes, attributes);
221 }
222
223
224
225
226
227
228
229
230
231
232 public void addAll(Map<String, Attribute> newAttributes) {
233 if (newAttributes == null) {
234 return;
235 }
236
237 if (attributes == null) {
238 attributes = new HashMap<String, Attribute>(newAttributes);
239 return;
240 }
241
242 attributes.putAll(newAttributes);
243 }
244
245
246
247
248
249
250
251
252
253
254 public void addMissing(Map<String, Attribute> defaultAttributes) {
255 if (defaultAttributes == null) {
256 return;
257 }
258
259 if (attributes == null) {
260 attributes = new HashMap<String, Attribute>();
261 if (cascadedAttributes == null || cascadedAttributes.isEmpty()) {
262 attributes.putAll(defaultAttributes);
263 return;
264 }
265 }
266
267 Set<Map.Entry<String, Attribute>> entries = defaultAttributes.entrySet();
268 for (Map.Entry<String, Attribute> entry : entries) {
269 String key = entry.getKey();
270 if (!attributes.containsKey(key)
271 && (cascadedAttributes == null || !cascadedAttributes
272 .containsKey(key))) {
273 attributes.put(entry.getKey(), entry.getValue());
274 }
275 }
276 }
277
278
279 public Attribute getAttribute(String name) {
280 Attribute retValue = null;
281 if (attributes != null) {
282 retValue = attributes.get(name);
283 }
284
285 if (retValue == null && cascadedAttributes != null) {
286 retValue = cascadedAttributes.get(name);
287 }
288
289 return retValue;
290 }
291
292
293 public Attribute getLocalAttribute(String name) {
294 if (attributes == null) {
295 return null;
296 }
297
298 return attributes.get(name);
299 }
300
301
302 public Attribute getCascadedAttribute(String name) {
303 if (cascadedAttributes == null) {
304 return null;
305 }
306
307 return cascadedAttributes.get(name);
308 }
309
310
311 public Set<String> getLocalAttributeNames() {
312 if (attributes != null && !attributes.isEmpty()) {
313 return attributes.keySet();
314 }
315 return null;
316 }
317
318
319 public Set<String> getCascadedAttributeNames() {
320 if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) {
321 return cascadedAttributes.keySet();
322 }
323 return null;
324 }
325
326
327 public void putAttribute(String name, Attribute value) {
328 if (attributes == null) {
329 attributes = new HashMap<String, Attribute>();
330 }
331
332 attributes.put(name, value);
333 }
334
335
336 public void putAttribute(String name, Attribute value, boolean cascade) {
337 Map<String, Attribute> mapToUse;
338 if (cascade) {
339 if (cascadedAttributes == null) {
340 cascadedAttributes = new HashMap<String, Attribute>();
341 }
342 mapToUse = cascadedAttributes;
343 } else {
344 if (attributes == null) {
345 attributes = new HashMap<String, Attribute>();
346 }
347 mapToUse = attributes;
348 }
349 mapToUse.put(name, value);
350 }
351
352
353 public void clear() {
354 templateAttribute = null;
355 preparer = null;
356 attributes.clear();
357 cascadedAttributes.clear();
358 }
359
360
361 @Override
362 public boolean equals(Object obj) {
363 BasicAttributeContext bac = (BasicAttributeContext) obj;
364 return nullSafeEquals(templateAttribute, bac.templateAttribute)
365 && nullSafeEquals(preparer, bac.preparer)
366 && nullSafeEquals(attributes, bac.attributes)
367 && nullSafeEquals(cascadedAttributes, bac.cascadedAttributes);
368 }
369
370
371 @Override
372 public int hashCode() {
373 return nullSafeHashCode(templateAttribute) + nullSafeHashCode(preparer)
374 + nullSafeHashCode(attributes)
375 + nullSafeHashCode(cascadedAttributes);
376 }
377
378
379
380
381
382
383 private void inheritParentTemplateAttribute(
384 Attribute parentTemplateAttribute) {
385 if (parentTemplateAttribute != null) {
386 if (templateAttribute == null) {
387 templateAttribute = new Attribute(parentTemplateAttribute);
388 } else {
389 templateAttribute.inherit(parentTemplateAttribute);
390 }
391 }
392 }
393
394
395
396
397
398
399 private void copyBasicAttributeContext(BasicAttributeContext context) {
400 Attribute parentTemplateAttribute = context.getTemplateAttribute();
401 if (parentTemplateAttribute != null) {
402 this.templateAttribute = new Attribute(parentTemplateAttribute);
403 }
404 preparer = context.preparer;
405 if (context.attributes != null && !context.attributes.isEmpty()) {
406 attributes = deepCopyAttributeMap(context.attributes);
407 }
408 copyCascadedAttributes(context);
409 }
410
411
412
413
414
415
416 private void copyCascadedAttributes(BasicAttributeContext context) {
417 if (context.cascadedAttributes != null
418 && !context.cascadedAttributes.isEmpty()) {
419 cascadedAttributes = deepCopyAttributeMap(context.cascadedAttributes);
420 }
421 }
422
423
424
425
426
427
428
429
430 private Map<String, Attribute> addMissingAttributes(Map<String, Attribute> source,
431 Map<String, Attribute> destination) {
432 if (source != null && !source.isEmpty()) {
433 if (destination == null) {
434 destination = new HashMap<String, Attribute>();
435 }
436 for (Map.Entry<String, Attribute> entry : source.entrySet()) {
437 String key = entry.getKey();
438 Attribute destAttribute = destination.get(key);
439 if (destAttribute == null) {
440 destination.put(key, entry.getValue());
441 } else if (destAttribute instanceof ListAttribute
442 && entry.getValue() instanceof ListAttribute
443 && ((ListAttribute) destAttribute).isInherit()) {
444 ((ListAttribute) destAttribute)
445 .inherit((ListAttribute) entry.getValue());
446 }
447 }
448 }
449
450 return destination;
451 }
452
453
454
455
456
457
458
459
460 private Map<String, Attribute> deepCopyAttributeMap(
461 Map<String, Attribute> attributes) {
462 Map<String, Attribute> retValue = new HashMap<String, Attribute>(attributes.size());
463 for (Map.Entry<String, Attribute> entry : attributes.entrySet()) {
464 Attribute toCopy = entry.getValue();
465 if (toCopy != null) {
466 retValue.put(entry.getKey(), toCopy.clone());
467 }
468 }
469 return retValue;
470 }
471 }