{
ResponseStateManager manager;
Object state[];
Map<String, Object> states;
UIViewRoot view = null;
// Get previous state from ResponseStateManager.
manager = RendererUtils.getResponseStateManager (context, renderKitId);
if (context.getApplication().getStateManager().isSavingStateInClient(context))
{
state = (Object[]) manager.getState (context, viewId);
}
else
{
Integer serverStateId = helper.getServerStateId((Object[]) manager.getState(context, viewId));
state = (Object[]) helper.getSerializedViewFromServletSession(context, viewId, serverStateId);
}
if (state != null && state[1] instanceof Object[])
{
Object[] fullState = (Object[]) state[1];
view = (UIViewRoot) internalRestoreTreeStructure((TreeStructComponent)fullState[0]);
if (view != null) {
context.setViewRoot (view);
view.processRestoreState(context, fullState[1]);
}
}
else
{
// Per the spec: build the view.
try {
ViewMetadata metadata = vdl.getViewMetadata (context, viewId);
Collection<UIViewParameter> viewParameters = null;
if (metadata != null)
{
view = metadata.createMetadataView(context);
if (view != null)
{
viewParameters = metadata.getViewParameters(view);
}
}
if (view == null)
{
view = vdl.createView(context, viewId);
}
context.setViewRoot (view);
// TODO: Why is necessary enable event processing?
// ANS: On RestoreViewExecutor, setProcessingEvents is called first to false
// and then to true when postback. Since we need listeners registered to PostAddToViewEvent
// event to be handled, we should enable it again. We are waiting a response from EG about
// the behavior of those listeners, because for partial state saving we need this listeners
// be called from here and relocate components properly, but for now we have to let this code as is.
try
{
context.setProcessingEvents (true);
vdl.buildView (context, view);
// In the latest code related to PostAddToView, it is
// triggered no matter if it is applied on postback. It seems that MYFACES-2389,
// TRINIDAD-1670 and TRINIDAD-1671 are related.
// This code is no longer necessary, but better let it here.
//_publishPostBuildComponentTreeOnRestoreViewEvent(context, view);
suscribeListeners(view);
}
finally
{
context.setProcessingEvents (false);
}
}
catch (Throwable e) {
throw new FacesException ("unable to create view \"" + viewId + "\"", e);
}
if (state != null && state[1] != null)
{
states = (Map<String, Object>) state[1];
// Visit the children and restore their state.
//view.visitTree (VisitContext.createVisitContext (context), new RestoreStateVisitor (states));
//Restore state of current components
restoreStateFromMap(context, states, view);
// TODO: handle dynamic add/removes as mandated by the spec. Not sure how to do handle this yet.
List<String> clientIdsRemoved = getClientIdsRemoved(view);
if (clientIdsRemoved != null)
{
for (String clientId : clientIdsRemoved)
{
view.invokeOnComponent(context, clientId, new ContextCallback()
{
public void invokeContextCallback(FacesContext context,
UIComponent target)
{
if (target.getParent() != null)
{
target.getParent().getChildren().remove(target);
}
}
});
}
}
List<String> clientIdsAdded = getClientIdsAdded(view);
if (clientIdsAdded != null)
{
for (String clientId : clientIdsAdded)
{
final AttachedFullStateWrapper wrapper = (AttachedFullStateWrapper) states.get(clientId);
if (wrapper != null)
{
final Object[] addedState = (Object[]) wrapper.getWrappedStateObject();
if (addedState != null)
{
if (addedState.length == 2)
{
view = (UIViewRoot) internalRestoreTreeStructure((TreeStructComponent) addedState[0]);
view.processRestoreState(context, addedState[1]);
break;
}
else
{
final String parentClientId = (String) addedState[0];
view.invokeOnComponent(context, parentClientId, new ContextCallback()
{
public void invokeContextCallback(FacesContext context,
UIComponent target)
{
if (addedState[1] != null)
{
String facetName = (String) addedState[1];
UIComponent child = internalRestoreTreeStructure((TreeStructComponent) addedState[3]);
child.processRestoreState(context, addedState[4]);
target.getFacets().put(facetName,child);
}
else
{
Integer childIndex = (Integer) addedState[2];
UIComponent child = internalRestoreTreeStructure((TreeStructComponent) addedState[3]);
child.processRestoreState(context, addedState[4]);
try
{
target.getChildren().add(childIndex, child);
}
catch (IndexOutOfBoundsException e)
{
// We can't be sure about where should be this
// item, so just add it.
target.getChildren().add(child);
}
}
}
});
}
}
}
}
}
}
}
// Restore binding, because UIViewRoot.processRestoreState() is never called
//boolean oldContextEventState = context.isProcessingEvents();
//the event processing has to be enabled because of the restore view event triggers
//TODO ask the EG the this is a spec violation if we do it that way
//see Section 2.2.1
//context.setProcessingEvents(true);
//try {
view.visitTree(VisitContext.createVisitContext(context), new RestoreStateCallback());
//} finally {
// context.setProcessingEvents(oldContextEventState);
//}
return view;
}