Package org.ajax4jsf.component

Source Code of org.ajax4jsf.component.AjaxViewRoot

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

package org.ajax4jsf.component;

import java.io.IOException;
import java.util.NoSuchElementException;

import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;

import org.ajax4jsf.Messages;
import org.ajax4jsf.application.AjaxSingleException;
import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.context.AjaxContextImpl;
import org.ajax4jsf.context.InvokerCallback;
import org.ajax4jsf.context.ViewIdHolder;
import org.ajax4jsf.event.AjaxListener;
import org.ajax4jsf.event.EventsQueue;
import org.ajax4jsf.renderkit.AjaxContainerRenderer;

/**
* Custom ViewRoot for support render parts of tree for Ajax requests. Main
* difference from default ViewRoot - store events queue and unique id counter
* in request-scope variables. In common realisation, store request-scope
* variables in component produce errors in case of concurrent requests to same
* view.
*
* @author asmirnov@exadel.com (latest modification by $Author: alexsmirnov $)
* @version $Revision: 1.1.2.4 $ $Date: 2007/02/28 17:01:01 $
*
*/
public class AjaxViewRoot extends UIViewRoot implements AjaxContainer {

    public static final String ROOT_ID = "_viewRoot";

    private AjaxRegionBrige _brige;

    /**
         *
         */
    public AjaxViewRoot() {
  super();
  super.setId(ROOT_ID);
  _brige = new AjaxRegionBrige(this);
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIComponentBase#getId()
         */
    // public String getId() {
    // return ROOT_ID;
    // }
    public String getRendererType() {
  return (COMPONENT_FAMILY);
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#broadcast(javax.faces.event.FacesEvent)
         */
    public void broadcast(FacesEvent event) throws AbortProcessingException {
  super.broadcast(event);
  getBrige().broadcast(event);
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#getAjaxListener()
         */
    public MethodBinding getAjaxListener() {
  return getBrige().getAjaxListener();
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isImmediate()
         */
    public boolean isImmediate() {
  return getBrige().isImmediate();
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSubmitted()
         */
    public boolean isSubmitted() {
  return getBrige().isSubmitted();
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIComponent#queueEvent(javax.faces.event.FacesEvent)
         */
    public void queueEvent(FacesEvent event) {
  if (event == null)
      throw new NullPointerException(Messages
        .getMessage(Messages.NULL_EVENT_SUBMITTED_ERROR));
  if (event.getPhaseId().compareTo(PhaseId.RENDER_RESPONSE) == 0) {
      // HACK - Special case - Ajax Events to RenderResponse phase
      // queue.
      // in future, with JSF 1.2 it must be done by invokeOnComponent
      // method.
      // In 1.1 , events to RENDER_RESPONSE phase not used.
      getAjaxEventsQueue(getFacesContext()).add(event);
  } else {
      getEventsQueue(getFacesContext(), event.getPhaseId()).add(event);
  }
    }

    /**
         * Broadcast events for specified Phase
         *
         * @param context
         * @param phaseId -
         *                phase, for wich events must be processed.
         */
    void broadcastEvents(FacesContext context, PhaseId phaseId) {
  EventsQueue[] events = getEvents(context);
  EventsQueue anyPhaseEvents = events[PhaseId.ANY_PHASE.getOrdinal()];
  EventsQueue phaseEvents = events[phaseId.getOrdinal()];
  if (phaseEvents.isEmpty() && anyPhaseEvents.isEmpty())
      return;
  // FacesEvent event = null;
  boolean haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
  boolean havePhaseEvents = !phaseEvents.isEmpty();
  do {
      // ANY_PHASE first
      processEvents(anyPhaseEvents, haveAnyPhaseEvents);

      processEvents(phaseEvents, havePhaseEvents);
      // Events can queued in other events processing
      haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
      havePhaseEvents = !phaseEvents.isEmpty();
  } while (haveAnyPhaseEvents || havePhaseEvents);
  if (context.getRenderResponse() || context.getResponseComplete()) {
      clearEvents(context);
  }

    }

    /**
         * @param phaseEventsQueue
         * @param havePhaseEvents
         */
    public void processEvents(EventsQueue phaseEventsQueue, boolean havePhaseEvents) {
  FacesEvent event;
  while (havePhaseEvents) {
      try {
    event = (FacesEvent) phaseEventsQueue.remove();
    UIComponent source = event.getComponent();
    try {
        source.broadcast(event);
    } catch (AbortProcessingException e) {
        // abort event processing
        // Page 3-30 of JSF 1.1 spec: "Throw an
        // AbortProcessingException, to tell the JSF
        // implementation
        // that no further broadcast of this event, or any
        // further
        // events, should take place."
        // clearEvents();
        // return;
    }
      } catch (NoSuchElementException e) {
    havePhaseEvents = false;
      }
  }
    }

    public void broadcastAjaxEvents(FacesContext context) {
  EventsQueue queue = getAjaxEventsQueue(context);
  processEvents(queue, !queue.isEmpty());
    }

    private EventsQueue[] events;

    private EventsQueue ajaxEvents = new EventsQueue();

    /**
         * Use FIFO buffers for hold Faces Events. Hold this buffers in Request
         * scope parameters for support any concurrent requests for same
         * component tree ( since RI hold component tree in session ).
         *
         * @param context
         * @param phase
         * @return
         */
    protected EventsQueue getEventsQueue(FacesContext context, PhaseId phase) {
  return getEvents(context)[phase.getOrdinal()];
    }

    /**
         * @return
         */
    protected EventsQueue[] getEvents(FacesContext context) {
  if (events == null) {
      clearEvents(context);
  }
  return events;
    }

    /**
         * Special Fifo Buffer for ajax events to Render Responce phase.
         *
         * @param context
         * @return
         */
    protected EventsQueue getAjaxEventsQueue(FacesContext context) {

  return ajaxEvents;
    }

    public void clearEvents(FacesContext context) {
  int len;
  events = new EventsQueue[len = PhaseId.VALUES.size()];
  for (int i = 0; i < len; i++) {
      events[i] = new EventsQueue();
  }
    }

    private InvokerCallback _decodeInvoker = new InvokerCallback() {

  public void invoke(FacesContext context, UIComponent component) {
      component.processDecodes(context);
  }

  public void invokeRoot(FacesContext context) {
      AjaxViewRoot.super.processDecodes(context);
  }

    };

    private UIComponent singleComponent = null;

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processDecodes(javax.faces.context.FacesContext)
         */
    public void processDecodes(FacesContext context) {
  if (context == null)
      throw new NullPointerException("context");
  singleComponent = null;
  AjaxContextImpl.invokeOnRegionOrRoot(this, context, _decodeInvoker);
  try {
      broadcastEvents(context, PhaseId.APPLY_REQUEST_VALUES);
  } catch (AjaxSingleException e) {
      singleComponent = e.getComponent();
  }
    }

    private InvokerCallback _updatesInvoker = new InvokerCallback() {

  public void invoke(FacesContext context, UIComponent component) {
      component.processUpdates(context);
  }

  public void invokeRoot(FacesContext context) {
      AjaxViewRoot.super.processUpdates(context);
  }

    };

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processUpdates(javax.faces.context.FacesContext)
         */
    public void processUpdates(FacesContext context) {
  if (context == null)
      throw new NullPointerException("context");
  if (null == singleComponent) {
      AjaxContextImpl.invokeOnRegionOrRoot(this, context, _updatesInvoker);
  } else {
      singleComponent.processUpdates(context);
  }
  broadcastEvents(context, PhaseId.UPDATE_MODEL_VALUES);
    }

    private InvokerCallback _validatorsInvoker = new InvokerCallback() {

  public void invoke(FacesContext context, UIComponent component) {
      component.processValidators(context);
  }

  public void invokeRoot(FacesContext context) {
      AjaxViewRoot.super.processValidators(context);
  }

    };

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processValidators(javax.faces.context.FacesContext)
         */
    public void processValidators(FacesContext context) {
  if (context == null)
      throw new NullPointerException("context");
  if (null == singleComponent) {
      AjaxContextImpl.invokeOnRegionOrRoot(this, context, _validatorsInvoker);
  } else {
      singleComponent.processValidators(context);
  }
  broadcastEvents(context, PhaseId.PROCESS_VALIDATIONS);
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIViewRoot#processApplication(javax.faces.context.FacesContext)
         */
    public void processApplication(FacesContext context) {
  if (context == null)
      throw new NullPointerException("context");
  // UIComponent component = getSubmittedRegion(context);
  // TODO - process JSF 1.2 listeners
  broadcastEvents(context, PhaseId.INVOKE_APPLICATION);
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIViewRoot#encodeBegin(javax.faces.context.FacesContext)
         */
    // public void encodeBegin(FacesContext context) throws IOException {
    // UIComponent submittedComponent = getSubmittedRegion(context);
    // if(null == submittedComponent){
    // super.encodeBegin(context);
    // } else {
    // submittedComponent.encodeBegin(context);
    // }
    // }
    private InvokerCallback _ajaxInvoker = new InvokerCallback() {

  public void invoke(FacesContext context, UIComponent component) {
      try {
    if (component instanceof AjaxContainer) {
        AjaxContainer ajax = (AjaxContainer) component;
        ajax.encodeAjax(context);
    } else {
        // Container not found, use Root for encode.
        encodeAjax(context);
    }
      } catch (IOException e) {
    throw new FacesException(e);
      }
  }

  public void invokeRoot(FacesContext context) {
      try {
    encodeAjax(context);
      } catch (IOException e) {
    throw new FacesException(e);
      }
  }

    };

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
         */
    public void encodeChildren(FacesContext context) throws IOException {
  if (!isHavePage()
    && AjaxContext.getCurrentInstance(context).isAjaxRequest(
      context)) {
      AjaxContextImpl.invokeOnRegionOrRoot(this, context, _ajaxInvoker);
  } else {
      super.encodeChildren(context);
  }
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
         */
    // public void encodeEnd(FacesContext context) throws IOException {
    // UIComponent submittedComponent = getSubmittedRegion(context);
    // if (null == submittedComponent) {
    // super.encodeEnd(context);
    // } else {
    // submittedComponent.encodeEnd(context);
    // }
    // }
    public void restoreState(FacesContext context, Object state) {
  Object[] mystate = (Object[]) state;
  super.restoreState(context, mystate[0]);
  getBrige().restoreState(context, mystate[1]);
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#saveState(javax.faces.context.FacesContext)
         */
    public Object saveState(FacesContext context) {
  Object[] state = new Object[2];
  state[0] = super.saveState(context);
  state[1] = getBrige().saveState(context);
  return state;
    }

    public String getViewId() {
  ViewIdHolder viewIdHolder = AjaxContext.getCurrentInstance()
    .getViewIdHolder();
  String viewId;
  if (null != viewIdHolder) {
      viewId = viewIdHolder.getViewId();
  } else {
      viewId = super.getViewId();
  }
  return viewId;
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setAjaxListener(javax.faces.el.MethodBinding)
         */
    public void setAjaxListener(MethodBinding ajaxListener) {
  getBrige().setAjaxListener(ajaxListener);
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setImmediate(boolean)
         */
    public void setImmediate(boolean immediate) {
  getBrige().setImmediate(immediate);
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSubmitted(boolean)
         */
    public void setSubmitted(boolean submitted) {
  getBrige().setSubmitted(submitted);
    }

    public void addAjaxListener(AjaxListener listener) {
  addFacesListener(listener);
    }

    public AjaxListener[] getAjaxListeners() {
  return (AjaxListener[]) getFacesListeners(AjaxListener.class);
    }

    public void removeAjaxListener(AjaxListener listener) {
  removeFacesListener(listener);

    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSelfRendered()
         */
    public boolean isSelfRendered() {
  return false;// _brige.isSelfRendered();
    }

    /*
         * (non-Javadoc)
         *
         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSelfRendered(boolean)
         */
    public void setSelfRendered(boolean selfRendered) {
  // _brige.setSelfRendered(selfRendered);
    }

    /**
         * Check for AjaxContainer component in childreh. This is workaround for
         * MyFaces JSP tag implementation, not called any encode... methods in
         * <f:view> tag. If only one AjaxContainer present as children for
         * viewRoot, decoding methods delegated to them.
         *
         * @return Returns the havePage.
         */
    public boolean isHavePage() {
  return (getChildCount() == 1 && getChildren().get(0) instanceof AjaxContainer);
    }

    /*
         * (non-Javadoc)
         *
         * @see javax.faces.component.UIComponentBase#getRendersChildren()
         */
    public boolean getRendersChildren() {
  FacesContext context = FacesContext.getCurrentInstance();
  // For non Ajax request, view root not render children
  if (!AjaxContext.getCurrentInstance(context).isAjaxRequest(context)) {
      return false;
  }
  // Also, if have page component as clild - delegate rendering of
  // children to it.
  if (isHavePage()) {
      return false;
  }
  // Ajax Request. Control all output.
  return true;
    }

    public boolean isRenderRegionOnly() {
  // for viewroot it not applicable.
  return false;
    }

    public void setRenderRegionOnly(boolean reRenderPage) {
  // TODO Auto-generated method stub

    }

    public void encodeAjax(FacesContext context) throws IOException {
  String rendererType = getRendererType();
  if (rendererType != null) {
      ((AjaxContainerRenderer) getRenderer(context)).encodeAjax(context,
        this);
  }

    }

    /**
         * @return the brige
         */
    protected AjaxRegionBrige getBrige() {
  return _brige;
    }

}
TOP

Related Classes of org.ajax4jsf.component.AjaxViewRoot

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.