throw new NullPointerException(getMessages()
.getMessage("clay.null.facesContext"));
}
// create a new scoped symbol table
Map symbolTable = new Attributes();
// inherit the parents symbols
symbolTable.putAll(clayContext.getSymbols());
// override config (XML, HTML) symbols
symbolTable.putAll(displayElement.getSymbols());
// push to context
clayContext.setSymbols(symbolTable);
// evaluate nested symbols; symbols having symbols as values
realizeSymbols(clayContext);
UIComponent child = null;
Long jspId = new Long(displayElement.getJspId());
clayContext.getJspIds().add(jspId);
String facetName = displayElement.getFacetName();
if (facetName != null) {
facetName = replaceMnemonic(clayContext, facetName);
}
if (facetName != null) {
child = parent.getFacet(displayElement.getFacetName());
}
if (child == null) {
child = this.findComponentByJspId(parent, jspId);
}
// always burn an id; this is to support the early versions of myfaces & RI 1.1
// the UIViewRoot didn't persist the sequence that is used by the call to createUniqueId
String id = facesContext.getViewRoot().createUniqueId();
if (child == null) {
if (displayElement.getId() != null) {
id = replaceMnemonic(clayContext, displayElement.getId());
}
} else {
id = child.getId();
}
//Check to see if the replacement failed. This can happen if the
//symbol is missing. The id will still containing the symbol delimiter
//character. The other scenario is if the value of the symbol is null.
if (id == null || id.indexOf('@') > -1) {
if (id == null) {
id = displayElement.getId();
}
throw new RuntimeException(getMessages().getMessage("create.component.invalid.id",
new Object[] {id, symbolTable}));
}
if (child == null) {
try {
AttributeBean attr = displayElement.getAttribute("binding");
if (attr != null
&& attr.getValue() != null) {
clayContext.setAttribute(attr);
String expr = replaceMnemonic(clayContext);
ValueBinding vb = facesContext.getApplication().createValueBinding(expr);
child = facesContext.getApplication().createComponent(vb, facesContext,
displayElement.getComponentType());
child.setValueBinding("binding", vb);
} else {
child = facesContext.getApplication().createComponent(
displayElement.getComponentType());
}
} catch (Exception e) {
log.error(getMessages().getMessage("create.component.error",
new Object[] { displayElement }), e);
throw e;
}
child.setId(id);
child.getAttributes().put(Globals.CLAY_JSPID_ATTRIBUTE, jspId);
if (facetName != null) {
parent.getFacets().put(facetName, child);
if (log.isDebugEnabled()) {
log.debug(getMessages().getMessage("create.facet.component",
new Object[] { id, displayElement.getJsfid()}));
}
} else {
parent.getChildren().add(clayContext.getChildIndex(), child);
if (log.isDebugEnabled()) {
log.debug(getMessages().getMessage("create.component",
new Object[] { id, displayElement.getJsfid(), new Integer(clayContext.getChildIndex()) }));
}
}
if (child instanceof Clay) {
//save the display element used to create the component for exception
//reporting when the jsfid is null. This should only happen when using
//symbol replacement of a nested clay component with HTML views
child.getAttributes().put(Globals.CLAY_RESERVED_ATTRIBUTE, displayElement);
}
// continue with the addComponent chain
isFinal = false;
} else {
if (log.isDebugEnabled()) {
log.debug(getMessages().getMessage("create.component.exists",
new Object[] { id, displayElement.getJsfid(), new Integer(clayContext.getChildIndex()) }));
}
}
// if target is a Clay component it might contain symbols
if (child instanceof Clay) {
// override symbols from nested clay component
symbolTable.putAll(((Clay) child).getSymbols());
// capture current symbols for the root of the nested component
((Clay) child).getSymbols().putAll(symbolTable);
// push to context
clayContext.setSymbols(symbolTable);