in impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java [2464:2620]
public UIComponent createComponent(FacesContext context,
String taglibURI, String tagName, Map<String, Object> attributes)
{
Assert.notNull(context, "context");
UIComponent createdComponent = null;
try
{
Facelet componentFacelet;
FaceletFactory.setInstance(faceletFactory);
try
{
componentFacelet
= faceletFactory.compileComponentFacelet(taglibURI, tagName, attributes);
}
finally
{
FaceletFactory.setInstance(null);
}
if (componentFacelet == null)
{
return null;
}
// Create a temporal component base class where all components will be put, but we are only
// interested in the inner UIComponent and if multiple are created, return this one.
boolean requiresDynamicRefresh = false;
boolean requiresFaceletDynamicRefresh = false;
UIPanel tempParent
= (UIPanel) context.getApplication().createComponent(
context, UIPanel.COMPONENT_TYPE, null);
tempParent.setId(context.getViewRoot().createUniqueId(context, null));
String baseKey = tempParent.getId();
baseKey = baseKey.startsWith(UIViewRoot.UNIQUE_ID_PREFIX) ? baseKey.substring(4) : baseKey;
try
{
tempParent.pushComponentToEL(context, tempParent);
((AbstractFacelet)componentFacelet).applyDynamicComponentHandler(
context, tempParent, baseKey);
}
finally
{
tempParent.popComponentFromEL(context);
// There are two cases:
// 1. If we are under facelets algorithm control (binding case), the refreshing logic will be done
// outside this block. We can check that condition easily with FaceletCompositionContext
// 2. If we are not under facelets algorithm control, check if the dynamic component requires refresh,
// if that so, mark the view to be refreshed and reset the flag, otherwise continue. This check
// allows us to decide if we add a third listener to refresh on transient build.
// Check if the current component requires dynamic refresh and if that so,
FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(context);
if (fcc != null)
{
requiresFaceletDynamicRefresh = true;
}
else if (FaceletViewDeclarationLanguageBase.isDynamicComponentNeedsRefresh(context))
{
FaceletViewDeclarationLanguageBase.activateDynamicComponentRefreshTransientBuild(context);
FaceletViewDeclarationLanguageBase.resetDynamicComponentNeedsRefreshFlag(context);
requiresDynamicRefresh = true;
}
}
if (tempParent.getChildCount() > 1)
{
// Multiple child. The tempParent will be returned. No need to
// save MARK_CREATED.
createdComponent = tempParent;
tempParent.getAttributes().put(DYN_WRAPPER, baseKey);
tempParent.subscribeToEvent(PostRestoreStateEvent.class, new
RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
if (requiresFaceletDynamicRefresh)
{
FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
}
}
else if (tempParent.getChildCount() == 1)
{
createdComponent = tempParent.getChildren().get(0);
boolean requiresRefresh = false;
// One child. In that case there are three choices:
if (UIComponent.isCompositeComponent(createdComponent))
{
// 1. Composite component. Needs special handling because
// facets will be added programmatically. The algorithm that
// process the composite component content should occur
// after the component is added to the view (PostAddToViewEvent).
// Requires refresh. To do that, we need to save the MARK_CREATED
// value and set it only when the full component is refreshed after
// restore it.
createdComponent.getAttributes().put(GEN_MARK_ID,
createdComponent.getAttributes().get(ComponentSupport.MARK_CREATED));
createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
createdComponent.subscribeToEvent(PostAddToViewEvent.class, new
CreateDynamicCompositeComponentListener(taglibURI, tagName, attributes, baseKey));
requiresRefresh = true;
if (requiresFaceletDynamicRefresh)
{
FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
}
}
else if (createdComponent.getChildCount() > 0)
{
// 2. Single component with children inside.
// Requires refresh. To do that, we need to save the MARK_CREATED
// value and set it only when the full component is refreshed after
// restore it.
createdComponent.getAttributes().put(GEN_MARK_ID,
createdComponent.getAttributes().get(ComponentSupport.MARK_CREATED));
createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
requiresRefresh = true;
if (requiresFaceletDynamicRefresh)
{
FaceletViewDeclarationLanguageBase.dynamicComponentNeedsRefresh(context);
}
}
else if (createdComponent.isTransient())
{
// Just transient markup inside. It is necessary to wrap
// that content into a component. Requires refresh. No need to
// save MARK_CREATED. No requires dynamic refresh.
createdComponent = tempParent;
tempParent.getAttributes().put(DYN_WRAPPER, baseKey);
requiresRefresh = true;
}
else
{
// 4. Single component without children:
// Remove MARK_CREATED because it does not requires
// refresh on restore. When it is added to the component
// tree, it will be saved and restored as if was a programmatically
// added component.
createdComponent.getAttributes().put(ComponentSupport.MARK_CREATED, null);
}
if (requiresRefresh)
{
createdComponent.subscribeToEvent(PostRestoreStateEvent.class, new
RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
}
if (requiresDynamicRefresh)
{
createdComponent.subscribeToEvent(DynamicComponentRefreshTransientBuildEvent.class, new
RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
createdComponent.getAttributes().put(
DynamicComponentRefreshTransientBuildEvent.DYN_COMP_REFRESH_FLAG, Boolean.TRUE);
}
if (requiresFaceletDynamicRefresh)
{
createdComponent.subscribeToEvent(FaceletDynamicComponentRefreshTransientBuildEvent.class, new
RefreshDynamicComponentListener(taglibURI, tagName, attributes, baseKey));
}
}
}
catch (IOException e)
{
throw new FacesException(e);
}
return createdComponent;
}