/**
   * This method is called before the {@link PhaseId#INVOKE_APPLICATION} phase of the JSF lifecycle
   * is executed. The purpose of this timing is to handle the case when the user clicks on a {@link
   * UICommand} component (like h:commandButton or h:commandLink) that has been either
   * Auto-ajaxified by ICEfaces, or manually Ajaxified by the developer using code like the
   * following:
   *
   * <p><code>&lt;f:ajax execute="@form" render=" @form" /&gt;</code>
   *
   * <p>When this happens, we need to somehow remember the list of JavaScript and/or CSS resources
   * that are currently in the &lt;head&gt; section of the portal page. This is because a
   * navigation-rule might fire which could cause a new view to be rendered in the {@link
   * PhaseId#RENDER_RESPONSE} phase that is about to follow this {@link PhaseId#INVOKE_APPLICATION}
   * phase. The list of resources would be contained in the {@link HeadManagedBean} {@link
   * ViewScoped} instance that is managed by the JSF managed-bean facility. The list would have been
   * populated initially in the {@link HeadManagedBean} by the {@link HeadRender} during the initial
   * HTTP-GET of the portal page. The way we "remember" the list is by placing it into the JSF 2
   * {@link Flash} scope. This scope is used because it is very short-lived and survives any
   * navigation-rules that might fire, thereby causing the rendering of a new JSF view.
   *
   * <p>The story is continued in the {@link #beforeRenderResponsePhase(PhaseEvent)} method below...
   */
  protected void beforeInvokeApplicationPhase(PhaseEvent phaseEvent) {

    // Get the list of resourceIds that might be contained in the Flash scope. Note that they would
    // have been
    // placed into the Flash scope by this very same method, except during in the case below for the
    // RENDER_RESPONSE phase.
    FacesContext facesContext = phaseEvent.getFacesContext();
    Flash flash = facesContext.getExternalContext().getFlash();

    @SuppressWarnings("unchecked")
    Set<String> headResourceIdsFromFlash = (Set<String>) flash.get("HEAD_RESOURCE_IDS");

    // Log the viewId so that it can be visually compared with the value that is to be logged after
    // the
    // INVOKE_APPLICATION phase completes.
    logger.debug("Before INVOKE_APPLICATION: viewId=[{0}]", facesContext.getViewRoot().getViewId());

    // If the Flash scope does not yet contain a list of head resourceIds, then the scope needs to
    // be populated
    // with a list so that the {@link #beforeRenderResponsePhase(PhaseEvent)} method below can
    // retrieve it.
    if (headResourceIdsFromFlash == null) {

      HeadManagedBean headManagedBean = HeadManagedBean.getInstance(facesContext);

      // Note that in the case where a portlet RESOURCE_PHASE was invoked with a "portlet:resource"
      // type of URL,
      // there will be no HeadManagedBean available.
      if (headManagedBean != null) {
        flash.put("HEAD_RESOURCE_IDS", headManagedBean.getHeadResourceIds());
      }
    }
  }
  /**
   * This method is called before the {@link PhaseId#RENDER_RESPONSE} phase of the JSF lifecycle is
   * executed. The purpose of this timing is to pick up where the {@link
   * #beforeInvokeApplicationPhase(PhaseEvent)} method left off. It might be the case that a
   * navigation-rule has fired and a NEW JSF view has been loaded up after the INVOKE_APPLICATION
   * phase completed. If this is the case, then the list of head resourceIds in the {@link
   * HeadManagedBean} needs to be repopulated from the list found in the Flash scope.
   */
  protected void beforeRenderResponsePhase(PhaseEvent phaseEvent) {
    FacesContext facesContext = phaseEvent.getFacesContext();
    Flash flash = facesContext.getExternalContext().getFlash();
    String viewId = facesContext.getViewRoot().getViewId();

    @SuppressWarnings("unchecked")
    Set<String> headResourceIdsFromFlash = (Set<String>) flash.get("HEAD_RESOURCE_IDS");

    if (headResourceIdsFromFlash != null) {
      HeadManagedBean headManagedBean = HeadManagedBean.getInstance(facesContext);
      Set<String> managedBeanResourceIds = headManagedBean.getHeadResourceIds();

      for (String resourceIdFromFlash : headResourceIdsFromFlash) {

        if (!managedBeanResourceIds.contains(resourceIdFromFlash)) {
          managedBeanResourceIds.add(resourceIdFromFlash);
          logger.debug(
              "Added resourceId=[{0}] from the Flash scope to the list of resourceIds in the HeadManagedBean for viewId=[{1}]",
              resourceIdFromFlash, viewId);
        }
      }
    }
  }