|
|||||||||||||||||||
| 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 |
} |
|
||||||||||