in impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java [309:532]
public void buildView(FacesContext context, UIViewRoot view) throws IOException
{
if (isFilledView(context, view))
{
if (view != null &&
FaceletViewDeclarationLanguageBase.isDynamicComponentRefreshTransientBuildActive(context, view))
{
// don't return
}
else
{
return;
}
}
String viewId = view.getViewId();
if (log.isLoggable(Level.FINEST))
{
log.finest("Building View: " + viewId);
}
boolean usePartialStateSavingOnThisView = _usePartialStateSavingOnThisView(viewId);
boolean refreshTransientBuild = view.getChildCount() > 0;
boolean refreshTransientBuildOnPSS = usePartialStateSavingOnThisView && config.isRefreshTransientBuildOnPSS();
boolean refreshPartialView = false;
if (viewPoolProcessor != null && !refreshTransientBuild)
{
RestoreViewFromPoolResult result = tryRestoreViewFromCache(context, view);
if (result != null)
{
// Since all transient stuff has been removed, add listeners that keep
// track of tree updates.
if (RestoreViewFromPoolResult.COMPLETE.equals(result))
{
if (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
{
((PartialStateManagementStrategy)
getStateManagementStrategy(context, view.getViewId())).
subscribeListeners(view);
}
// If the result is complete, the view restored here is static.
// static views can be marked as filled.
if (!refreshTransientBuildOnPSS)
{
// This option will be true on this cases:
// -pss is true and refresh is not active
setFilledView(context, view);
}
//At this point refreshTransientBuild = false && refreshTransientBuildOnPSS is true
else if (config.isRefreshTransientBuildOnPSSAuto() &&
!context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE))
{
setFilledView(context, view);
}
return;
}
else
{
// We need to refresh a partial view.
refreshTransientBuild = true;
refreshPartialView = true;
}
}
}
if (usePartialStateSavingOnThisView)
{
// Before apply we need to make sure the current view has
// a clientId that will be used as a key to save and restore
// the current view. Note that getClientId is never called (or used)
// from UIViewRoot.
if (view.getId() == null)
{
view.setId(view.createUniqueId(context, null));
}
context.getAttributes().put(USING_PSS_ON_THIS_VIEW, Boolean.TRUE);
//Add a key to indicate ComponentTagHandlerDelegate to
//call UIComponent.markInitialState after it is populated
if (!refreshTransientBuild || refreshPartialView)
{
context.getAttributes().put(StateManager.IS_BUILDING_INITIAL_STATE, Boolean.TRUE);
context.getAttributes().put(IS_BUILDING_INITIAL_STATE_KEY_ALIAS, Boolean.TRUE);
}
if (!refreshTransientBuild && config.isMarkInitialStateWhenApplyBuildView())
{
context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
}
if (refreshTransientBuildOnPSS)
{
//This value is only set when _refreshTransientBuildOnPSSMode is "auto" or "true"
context.getAttributes().put(REFRESH_TRANSIENT_BUILD_ON_PSS,
config.isRefreshTransientBuildOnPSSAuto() ? "auto" : "true");
}
}
try
{
if (refreshTransientBuild)
{
context.getAttributes().put(REFRESHING_TRANSIENT_BUILD, Boolean.TRUE);
// In theory, this should be disabled on ComponentTagHandlerDelegate,
// otherwise we could lost PostAddToViewEvent / PreRemoveFromViewEvent
// caused by c:if effect or facelets cleanup algorithm
//context.setProcessingEvents(false);
}
// populate UIViewRoot
_getFacelet(context, viewId).apply(context, view);
}
finally
{
if (refreshTransientBuildOnPSS)
{
context.getAttributes().remove(REFRESH_TRANSIENT_BUILD_ON_PSS);
}
if (refreshTransientBuild)
{
//context.setProcessingEvents(true);
if (FaceletViewDeclarationLanguageBase.isDynamicComponentRefreshTransientBuildActive(context))
{
VisitContext visitContext = getVisitContextFactory().
getVisitContext(context, null, MyFacesVisitHints.SET_SKIP_ITERATION);
view.visitTree(visitContext, PublishDynamicComponentRefreshTransientBuildCallback.INSTANCE);
}
if (!usePartialStateSavingOnThisView || refreshTransientBuildOnPSS)
{
// When the facelet is applied, all components are removed and added from view,
// but the difference resides in the ordering. Since the view is
// being refreshed, if we don't do this manually, some tags like
// cc:insertChildren or cc:insertFacet will not work correctly, because
// we expect PostAddToViewEvent will be propagated from parent to child, and
// facelets refreshing algorithm do the opposite.
//FaceletViewDeclarationLanguage._publishPreRemoveFromViewEvent(context, view);
//FaceletViewDeclarationLanguage._publishPostAddToViewEvent(context, view);
}
context.getAttributes().remove(REFRESHING_TRANSIENT_BUILD);
}
else
{
// Publish PostAddToView over UIViewRoot, because this is not done automatically.
context.getApplication().publishEvent(context, PostAddToViewEvent.class, UIViewRoot.class, view);
}
}
// set this view as filled
if (refreshTransientBuild)
{
//This option will be true on this cases:
//- pss is false, but we are refreshing
//- pss is true, and we are refreshing a view already filled
setFilledView(context, view);
}
else if (!refreshTransientBuildOnPSS)
{
// This option will be true on this cases:
// -pss is true and refresh is not active
setFilledView(context, view);
}
//At this point refreshTransientBuild = false && refreshTransientBuildOnPSS is true
else if (config.isRefreshTransientBuildOnPSSAuto()
&& !context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE))
{
setFilledView(context, view);
}
// Subscribe listeners if we are using partialStateSaving
if (usePartialStateSavingOnThisView)
{
// UIViewRoot.markInitialState() is not called because it does
// not have a facelet tag handler class that create it, instead
// new instances are created programmatically.
if (!refreshTransientBuild || refreshPartialView)
{
// Save the state
if (viewPoolProcessor != null &&
viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
{
viewPoolProcessor.storeViewStructureMetadata(context, view);
}
if (config.isMarkInitialStateWhenApplyBuildView())
{
if (!refreshTransientBuildOnPSS ||
!view.getAttributes().containsKey(COMPONENT_ADDED_AFTER_BUILD_VIEW))
{
view.markInitialState();
}
//Remove the key that indicate we need to call UIComponent.markInitialState
//on the current tree
context.getAttributes().remove(MARK_INITIAL_STATE_KEY);
}
else
{
context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
_markInitialStateOnView(view, refreshTransientBuildOnPSS);
context.getAttributes().remove(MARK_INITIAL_STATE_KEY);
}
context.getAttributes().remove(StateManager.IS_BUILDING_INITIAL_STATE);
context.getAttributes().remove(IS_BUILDING_INITIAL_STATE_KEY_ALIAS);
}
// We need to subscribe the listeners of changes in the component tree
// only the first time here. Later we subscribe this listeners on
// DefaultFaceletsStateManagement.restoreView, to ensure
// relocated components are not retrieved later on getClientIdsRemoved().
if (!(refreshTransientBuild && PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
&& !view.isTransient())
{
((PartialStateManagementStrategy) getStateManagementStrategy(context, view.getViewId())).
subscribeListeners(view);
}
context.getAttributes().remove(USING_PSS_ON_THIS_VIEW);
}
// Remove this var from faces context because this one prevent AjaxHandler
// register the standard script library on Post-Redirect-Get pattern or
// in the next view
context.getAttributes().remove(AjaxHandler.FACES_JS_DYNAMICALLY_ADDED);
}