Clover coverage report - brownies library - 1.0-beta-1 Coverage timestamp: 月 8 16 2004 17:14:42 GMT+09:00 FRAMES NO FRAMES |
file stats: | LOC: | 541 |  | Methods: | 17
| NCLOC: | 328 |  | Classes: | 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
Source file | Conditionals | Statements | Methods | TOTAL
BaseDesktopComponentTemplateLoader.java | 0% | 0% | 0% | 0% |

1 |  |
     /*
2 |  |
      * Joey and its relative products are published under the terms
3 |  |
      * of the Apache Software License.
4 |  |
      */
5 |  |
     package org.asyrinx.brownie.tapestry.components.layer;
6 |  |
7 |  |
     import java.util.HashSet;
8 |  |
     import java.util.Iterator;
9 |  |
     import java.util.Map;
10 |  |
     import java.util.Set;
11 |  |
12 |  |
     import org.apache.commons.lang.builder.ToStringBuilder;
13 |  |
     import org.apache.commons.logging.Log;
14 |  |
     import org.apache.commons.logging.LogFactory;
15 |  |
     import org.apache.tapestry.ApplicationRuntimeException;
16 |  |
     import org.apache.tapestry.IBinding;
17 |  |
     import org.apache.tapestry.IComponent;
18 |  |
     import org.apache.tapestry.ILocation;
19 |  |
     import org.apache.tapestry.IMarkupWriter;
20 |  |
     import org.apache.tapestry.IRender;
21 |  |
     import org.apache.tapestry.IRequestCycle;
22 |  |
     import org.apache.tapestry.Tapestry;
23 |  |
     import org.apache.tapestry.binding.ExpressionBinding;
24 |  |
     import org.apache.tapestry.binding.StaticBinding;
25 |  |
     import org.apache.tapestry.binding.StringBinding;
26 |  |
     import org.apache.tapestry.engine.IPageLoader;
27 |  |
     import org.apache.tapestry.engine.IPageSource;
28 |  |
     import org.apache.tapestry.engine.ITemplateSource;
29 |  |
     import org.apache.tapestry.parse.AttributeType;
30 |  |
     import org.apache.tapestry.parse.CloseToken;
31 |  |
     import org.apache.tapestry.parse.ComponentTemplate;
32 |  |
     import org.apache.tapestry.parse.LocalizationToken;
33 |  |
     import org.apache.tapestry.parse.OpenToken;
34 |  |
     import org.apache.tapestry.parse.TemplateAttribute;
35 |  |
     import org.apache.tapestry.parse.TemplateToken;
36 |  |
     import org.apache.tapestry.parse.TextToken;
37 |  |
     import org.apache.tapestry.parse.TokenType;
38 |  |
     import org.apache.tapestry.spec.IComponentSpecification;
39 |  |
40 |  |
     /**
41 |  |
      **/
42 |  |
43 |  |
     public class BaseDesktopComponentTemplateLoader {
44 |  |
         private static final Log LOG = LogFactory
45 |  |
                 .getLog(BaseDesktopComponentTemplateLoader.class);
46 |  |
47 |  |
         private IPageLoader _pageLoader;
48 |  |
49 |  |
         private IRequestCycle _requestCycle;
50 |  |
51 |  |
         private BaseDesktopComponent _loadComponent;
52 |  |
53 |  |
         private IPageSource _pageSource;
54 |  |
55 |  |
         private ComponentTemplate _template;
56 |  |
57 |  |
         private IComponent[] _stack;
58 |  |
59 |  |
         private int _stackx = 0;
60 |  |
61 |  |
         private IComponent _activeComponent = null;
62 |  |
63 |  |
         private Set _seenIds = new HashSet();
64 |  |
65 |  |
         /**
66 |  |
          * A class used with invisible localizations. Constructed from a
67 |  |
          * {@link TextToken}.
68 |  |
          *
69 |  |
          *
70 |  |
          */
71 |  |
72 |  |
         private static class LocalizedStringRender implements IRender {
73 |  |
             private IComponent _component;
74 |  |
75 |  |
             private String _key;
76 |  |
77 |  |
             private Map _attributes;
78 |  |
79 |  |
             private String _value;
80 |  |
81 |  |
             private boolean _raw;
82 |  |
83 | 0 |
             private LocalizedStringRender(IComponent component,
84 |  |
                     LocalizationToken token) {
85 | 0 |
                 _component = component;
86 | 0 |
                 _key = token.getKey();
87 | 0 |
                 _raw = token.isRaw();
88 | 0 |
                 _attributes = token.getAttributes();
89 |  |
             }
90 |  |
91 | 0 |
             public void render(IMarkupWriter writer, IRequestCycle cycle) {
92 | 0 |
                 if (cycle.isRewinding())
93 | 0 |
                     return;
94 |  |
95 | 0 |
                 if (_attributes != null) {
96 | 0 |
                     writer.begin("span");
97 |  |
98 | 0 |
                     Iterator i = _attributes.entrySet().iterator();
99 |  |
100 | 0 |
                     while (i.hasNext()) {
101 | 0 |
                         Map.Entry entry = (Map.Entry) i.next();
102 | 0 |
                         String attributeName = (String) entry.getKey();
103 | 0 |
                         String attributeValue = (String) entry.getValue();
104 |  |
105 | 0 |
                         writer.attribute(attributeName, attributeValue);
106 |  |
                     }
107 |  |
                 }
108 |  |
109 | 0 |
                 if (_value == null)
110 | 0 |
                     _value = _component.getMessage(_key);
111 |  |
112 | 0 |
                 if (_raw)
113 | 0 |
                     writer.printRaw(_value);
114 |  |
                 else
115 | 0 |
                     writer.print(_value);
116 |  |
117 | 0 |
                 if (_attributes != null)
118 | 0 |
                     writer.end();
119 |  |
             }
120 |  |
121 | 0 |
             public String toString() {
122 | 0 |
                 ToStringBuilder builder = new ToStringBuilder(this);
123 |  |
124 | 0 |
                 builder.append("component", _component);
125 | 0 |
                 builder.append("key", _key);
126 | 0 |
                 builder.append("raw", _raw);
127 | 0 |
                 builder.append("attributes", _attributes);
128 |  |
129 | 0 |
                 return builder.toString();
130 |  |
             }
131 |  |
132 |  |
         }
133 |  |
134 | 0 |
         public BaseDesktopComponentTemplateLoader(IRequestCycle requestCycle,
135 |  |
                 IPageLoader pageLoader, BaseDesktopComponent loadComponent,
136 |  |
                 ComponentTemplate template, IPageSource pageSource) {
137 | 0 |
             _requestCycle = requestCycle;
138 | 0 |
             _pageLoader = pageLoader;
139 | 0 |
             _loadComponent = loadComponent;
140 | 0 |
             _template = template;
141 | 0 |
             _pageSource = pageSource;
142 |  |
143 | 0 |
             _stack = new IComponent[template.getTokenCount()];
144 |  |
         }
145 |  |
146 | 0 |
         public void process() {
147 | 0 |
             int count = _template.getTokenCount();
148 |  |
149 | 0 |
             for (int i = 0; i < count; i++) {
150 | 0 |
                 TemplateToken token = _template.getToken(i);
151 |  |
152 | 0 |
                 TokenType type = token.getType();
153 |  |
154 | 0 |
                 if (type == TokenType.TEXT) {
155 | 0 |
                     process((TextToken) token);
156 | 0 |
                     continue;
157 |  |
                 }
158 |  |
159 | 0 |
                 if (type == TokenType.OPEN) {
160 | 0 |
                     process((OpenToken) token);
161 | 0 |
                     continue;
162 |  |
                 }
163 |  |
164 | 0 |
                 if (type == TokenType.CLOSE) {
165 | 0 |
                     process((CloseToken) token);
166 | 0 |
                     continue;
167 |  |
                 }
168 |  |
169 | 0 |
                 if (type == TokenType.LOCALIZATION) {
170 | 0 |
                     process((LocalizationToken) token);
171 | 0 |
                     continue;
172 |  |
                 }
173 |  |
             }
174 |  |
175 |  |
             // This is also pretty much unreachable, and the message is kind of out
176 |  |
             // of date, too.
177 |  |
178 | 0 |
             if (_stackx != 0)
179 | 0 |
                 throw new ApplicationRuntimeException(Tapestry
180 |  |
                         .getMessage("BaseDesktopComponent.unbalance-open-tags"),
181 |  |
                         _loadComponent, null, null);
182 |  |
183 | 0 |
             checkAllComponentsReferenced();
184 |  |
         }
185 |  |
186 |  |
         /**
187 |  |
          * Adds the token (which implements {@link IRender}) to the active
188 |  |
          * component (using {@link IComponent#addBody(IRender)}), or to this
189 |  |
          * component {@link #addOuter(IRender)}.
190 |  |
          *
191 |  |
          * <p>
192 |  |
          * A check is made that the active component allows a body.
193 |  |
          *
194 |  |
          */
195 |  |
196 | 0 |
         private void process(TextToken token) {
197 | 0 |
             if (_activeComponent == null) {
198 | 0 |
                 _loadComponent.addOuter(token);
199 | 0 |
                 return;
200 |  |
             }
201 |  |
202 | 0 |
             if (!_activeComponent.getSpecification().getAllowBody())
203 | 0 |
                 throw createBodylessComponentException(_activeComponent);
204 |  |
205 | 0 |
             _activeComponent.addBody(token);
206 |  |
         }
207 |  |
208 | 0 |
         private void process(OpenToken token) {
209 | 0 |
             String id = token.getId();
210 | 0 |
             IComponent component = null;
211 | 0 |
             String componentType = token.getComponentType();
212 |  |
213 | 0 |
             if (componentType == null)
214 | 0 |
                 component = getEmbeddedComponent(id);
215 |  |
             else
216 | 0 |
                 component = createImplicitComponent(id, componentType, token
217 |  |
                         .getLocation());
218 |  |
219 |  |
             // Make sure the template contains each component only once.
220 |  |
221 | 0 |
             if (_seenIds.contains(id))
222 | 0 |
                 throw new ApplicationRuntimeException(Tapestry.format(
223 |  |
                         "BaseDesktopComponent.multiple-component-references",
224 |  |
                         _loadComponent.getExtendedId(), id), _loadComponent, token
225 |  |
                         .getLocation(), null);
226 |  |
227 | 0 |
             _seenIds.add(id);
228 |  |
229 | 0 |
             if (_activeComponent == null)
230 | 0 |
                 _loadComponent.addOuter(component);
231 |  |
             else {
232 |  |
                 // Note: this code may no longer be reachable (because the
233 |  |
                 // template parser does this check first).
234 |  |
235 | 0 |
                 if (!_activeComponent.getSpecification().getAllowBody())
236 | 0 |
                     throw createBodylessComponentException(_activeComponent);
237 |  |
238 | 0 |
                 _activeComponent.addBody(component);
239 |  |
             }
240 |  |
241 | 0 |
             addTemplateBindings(component, token);
242 |  |
243 | 0 |
             _stack[_stackx++] = _activeComponent;
244 |  |
245 | 0 |
             _activeComponent = component;
246 |  |
         }
247 |  |
248 | 0 |
         private IComponent createImplicitComponent(String id, String componentType,
249 |  |
                 ILocation location) {
250 | 0 |
             IComponent result = _pageLoader.createImplicitComponent(_requestCycle,
251 |  |
                     _loadComponent, id, componentType, location);
252 |  |
253 | 0 |
             return result;
254 |  |
         }
255 |  |
256 | 0 |
         private IComponent getEmbeddedComponent(String id) {
257 | 0 |
             return _loadComponent.getComponent(id);
258 |  |
         }
259 |  |
260 | 0 |
         private void process(CloseToken token) {
261 |  |
             // Again, this is pretty much impossible to reach because
262 |  |
             // the template parser does a great job.
263 |  |
264 | 0 |
             if (_stackx <= 0)
265 | 0 |
                 throw new ApplicationRuntimeException(Tapestry
266 |  |
                         .getMessage("BaseDesktopComponent.unbalanced-close-tags"),
267 |  |
                         _loadComponent, token.getLocation(), null);
268 |  |
269 |  |
             // Null and forget the top element on the stack.
270 |  |
271 | 0 |
             _stack[_stackx--] = null;
272 |  |
273 | 0 |
             _activeComponent = _stack[_stackx];
274 |  |
         }
275 |  |
276 | 0 |
         private void process(LocalizationToken token) {
277 | 0 |
             IRender render = new LocalizedStringRender(_loadComponent, token);
278 |  |
279 | 0 |
             if (_activeComponent == null)
280 | 0 |
                 _loadComponent.addOuter(render);
281 |  |
             else
282 | 0 |
                 _activeComponent.addBody(render);
283 |  |
         }
284 |  |
285 |  |
         /**
286 |  |
          * Adds bindings based on attributes in the template.
287 |  |
          *
288 |  |
          * @since 3.0
289 |  |
          *
290 |  |
          */
291 |  |
292 | 0 |
         private void addTemplateBindings(IComponent component, OpenToken token) {
293 | 0 |
             IComponentSpecification spec = component.getSpecification();
294 |  |
295 |  |
             // add a static binding carrying the template tag
296 | 0 |
             addStaticBinding(component, spec,
297 |  |
                     ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME, token.getTag(),
298 |  |
                     token.getLocation());
299 |  |
300 | 0 |
             Map attributes = token.getAttributesMap();
301 |  |
302 | 0 |
             if (attributes == null)
303 | 0 |
                 return;
304 |  |
305 | 0 |
             Iterator i = attributes.entrySet().iterator();
306 |  |
307 | 0 |
             while (i.hasNext()) {
308 | 0 |
                 Map.Entry entry = (Map.Entry) i.next();
309 |  |
310 | 0 |
                 String name = (String) entry.getKey();
311 | 0 |
                 TemplateAttribute attribute = (TemplateAttribute) entry.getValue();
312 | 0 |
                 AttributeType type = attribute.getType();
313 |  |
314 | 0 |
                 if (type == AttributeType.OGNL_EXPRESSION) {
315 | 0 |
                     addExpressionBinding(component, spec, name, attribute
316 |  |
                             .getValue(), token.getLocation());
317 | 0 |
                     continue;
318 |  |
                 }
319 |  |
320 | 0 |
                 if (type == AttributeType.LOCALIZATION_KEY) {
321 | 0 |
                     addStringBinding(component, spec, name, attribute.getValue(),
322 |  |
                             token.getLocation());
323 | 0 |
                     continue;
324 |  |
                 }
325 |  |
326 | 0 |
                 if (type == AttributeType.LITERAL)
327 | 0 |
                     addStaticBinding(component, spec, name, attribute.getValue(),
328 |  |
                             token.getLocation());
329 |  |
             }
330 |  |
         }
331 |  |
332 |  |
         /**
333 |  |
          * Adds an expression binding, checking for errors related to reserved and
334 |  |
          * informal parameters.
335 |  |
          *
336 |  |
          * <p>
337 |  |
          * It is an error to specify expression bindings in both the specification
338 |  |
          * and the template.
339 |  |
          *
340 |  |
          * @since 3.0
341 |  |
          */
342 |  |
343 | 0 |
         private void addExpressionBinding(IComponent component,
344 |  |
                 IComponentSpecification spec, String name, String expression,
345 |  |
                 ILocation location) {
346 |  |
347 |  |
             // If matches a formal parameter name, allow it to be set
348 |  |
             // unless there's already a binding.
349 |  |
350 | 0 |
             boolean isFormal = (spec.getParameter(name) != null);
351 |  |
352 | 0 |
             if (isFormal) {
353 | 0 |
                 if (component.getBinding(name) != null)
354 | 0 |
                     throw new ApplicationRuntimeException(Tapestry.format(
355 |  |
                             "BaseDesktopComponent.dupe-template-expression", name,
356 |  |
                             component.getExtendedId(), _loadComponent
357 |  |
                                     .getExtendedId()), component, location, null);
358 |  |
             } else {
359 | 0 |
                 if (!spec.getAllowInformalParameters())
360 | 0 |
                     throw new ApplicationRuntimeException(
361 |  |
                             Tapestry
362 |  |
                                     .format(
363 |  |
                                             "BaseDesktopComponent.template-expression-for-informal-parameter",
364 |  |
                                             name, component.getExtendedId(),
365 |  |
                                             _loadComponent.getExtendedId()),
366 |  |
                             component, location, null);
367 |  |
368 |  |
                 // If the name is reserved (matches a formal parameter
369 |  |
                 // or reserved name, caselessly), then skip it.
370 |  |
371 | 0 |
                 if (spec.isReservedParameterName(name))
372 | 0 |
                     throw new ApplicationRuntimeException(
373 |  |
                             Tapestry
374 |  |
                                     .format(
375 |  |
                                             "BaseDesktopComponent.template-expression-for-reserved-parameter",
376 |  |
                                             name, component.getExtendedId(),
377 |  |
                                             _loadComponent.getExtendedId()),
378 |  |
                             component, location, null);
379 |  |
             }
380 |  |
381 | 0 |
             IBinding binding = new ExpressionBinding(_pageSource
382 |  |
                     .getResourceResolver(), _loadComponent, expression, location);
383 |  |
384 | 0 |
             component.setBinding(name, binding);
385 |  |
         }
386 |  |
387 |  |
         /**
388 |  |
          * Adds an expression binding, checking for errors related to reserved and
389 |  |
          * informal parameters.
390 |  |
          *
391 |  |
          * <p>
392 |  |
          * It is an error to specify expression bindings in both the specification
393 |  |
          * and the template.
394 |  |
          *
395 |  |
          * @since 3.0
396 |  |
          */
397 |  |
398 | 0 |
         private void addStringBinding(IComponent component,
399 |  |
                 IComponentSpecification spec, String name, String localizationKey,
400 |  |
                 ILocation location) {
401 |  |
             // If matches a formal parameter name, allow it to be set
402 |  |
             // unless there's already a binding.
403 |  |
404 | 0 |
             boolean isFormal = (spec.getParameter(name) != null);
405 |  |
406 | 0 |
             if (isFormal) {
407 | 0 |
                 if (component.getBinding(name) != null)
408 | 0 |
                     throw new ApplicationRuntimeException(Tapestry.format(
409 |  |
                             "BaseDesktopComponent.dupe-string", name, component
410 |  |
                                     .getExtendedId(), _loadComponent
411 |  |
                                     .getExtendedId()), component, location, null);
412 |  |
             } else {
413 | 0 |
                 if (!spec.getAllowInformalParameters())
414 | 0 |
                     throw new ApplicationRuntimeException(
415 |  |
                             Tapestry
416 |  |
                                     .format(
417 |  |
                                             "BaseDesktopComponent.template-expression-for-informal-parameter",
418 |  |
                                             name, component.getExtendedId(),
419 |  |
                                             _loadComponent.getExtendedId()),
420 |  |
                             component, location, null);
421 |  |
422 |  |
                 // If the name is reserved (matches a formal parameter
423 |  |
                 // or reserved name, caselessly), then skip it.
424 |  |
425 | 0 |
                 if (spec.isReservedParameterName(name))
426 | 0 |
                     throw new ApplicationRuntimeException(
427 |  |
                             Tapestry
428 |  |
                                     .format(
429 |  |
                                             "BaseDesktopComponent.template-expression-for-reserved-parameter",
430 |  |
                                             name, component.getExtendedId(),
431 |  |
                                             _loadComponent.getExtendedId()),
432 |  |
                             component, location, null);
433 |  |
             }
434 |  |
435 | 0 |
             IBinding binding = new StringBinding(_loadComponent, localizationKey,
436 |  |
                     location);
437 |  |
438 | 0 |
             component.setBinding(name, binding);
439 |  |
         }
440 |  |
441 |  |
         /**
442 |  |
          * Adds a static binding, checking for errors related to reserved and
443 |  |
          * informal parameters.
444 |  |
          *
445 |  |
          * <p>
446 |  |
          * Static bindings that conflict with bindings in the specification are
447 |  |
          * quietly ignored.
448 |  |
          *
449 |  |
          * @since 3.0
450 |  |
          *
451 |  |
          */
452 |  |
453 | 0 |
         private void addStaticBinding(IComponent component,
454 |  |
                 IComponentSpecification spec, String name, String staticValue,
455 |  |
                 ILocation location) {
456 |  |
457 | 0 |
             if (component.getBinding(name) != null)
458 | 0 |
                 return;
459 |  |
460 |  |
             // If matches a formal parameter name, allow it to be set
461 |  |
             // unless there's already a binding.
462 |  |
463 | 0 |
             boolean isFormal = (spec.getParameter(name) != null);
464 |  |
465 | 0 |
             if (!isFormal) {
466 |  |
                 // Skip informal parameters if the component doesn't allow them.
467 |  |
468 | 0 |
                 if (!spec.getAllowInformalParameters())
469 | 0 |
                     return;
470 |  |
471 |  |
                 // If the name is reserved (matches a formal parameter
472 |  |
                 // or reserved name, caselessly), then skip it.
473 |  |
474 | 0 |
                 if (spec.isReservedParameterName(name))
475 | 0 |
                     return;
476 |  |
             }
477 |  |
478 | 0 |
             IBinding binding = new StaticBinding(staticValue, location);
479 |  |
480 | 0 |
             component.setBinding(name, binding);
481 |  |
         }
482 |  |
483 | 0 |
         private void checkAllComponentsReferenced() {
484 |  |
             // First, contruct a modifiable copy of the ids of all expected
485 |  |
             // components
486 |  |
             // (that is, components declared in the specification).
487 |  |
488 | 0 |
             Map components = _loadComponent.getComponents();
489 |  |
490 | 0 |
             Set ids = components.keySet();
491 |  |
492 |  |
             // If the seen ids ... ids referenced in the template, matches
493 |  |
             // all the ids in the specification then we're fine.
494 |  |
495 | 0 |
             if (_seenIds.containsAll(ids))
496 | 0 |
                 return;
497 |  |
498 |  |
             // Create a modifiable copy. Remove the ids that are referenced in
499 |  |
             // the template. The remainder are worthy of note.
500 |  |
501 | 0 |
             ids = new HashSet(ids);
502 | 0 |
             ids.removeAll(_seenIds);
503 |  |
504 | 0 |
             int count = ids.size();
505 |  |
506 | 0 |
             String key = (count == 1) ? "BaseDesktopComponent.missing-component-spec-single"
507 |  |
                     : "BaseDesktopComponent.missing-component-spec-multi";
508 |  |
509 | 0 |
             StringBuffer buffer = new StringBuffer(Tapestry.format(key,
510 |  |
                     _loadComponent.getExtendedId()));
511 |  |
512 | 0 |
             Iterator i = ids.iterator();
513 | 0 |
             int j = 1;
514 |  |
515 | 0 |
             while (i.hasNext()) {
516 | 0 |
                 if (j == 1)
517 | 0 |
                     buffer.append(' ');
518 | 0 |
                 else if (j == count) {
519 | 0 |
                     buffer.append(' ');
520 | 0 |
                     buffer.append(Tapestry.getMessage("BaseDesktopComponent.and"));
521 | 0 |
                     buffer.append(' ');
522 |  |
                 } else
523 | 0 |
                     buffer.append(", ");
524 |  |
525 | 0 |
                 buffer.append(i.next());
526 |  |
527 | 0 |
                 j++;
528 |  |
             }
529 |  |
530 | 0 |
             buffer.append('.');
531 |  |
532 | 0 |
             LOG.error(buffer.toString());
533 |  |
         }
534 |  |
535 | 0 |
         protected ApplicationRuntimeException createBodylessComponentException(
536 |  |
                 IComponent component) {
537 | 0 |
             return new ApplicationRuntimeException(Tapestry
538 |  |
                     .getMessage("BaseComponentTemplateLoader.bodyless-component"),
539 |  |
                     component, null, null);
540 |  |
         }
541 |  |
     }