Package javax.faces.component

Source Code of javax.faces.component.UIViewAction$ViewActionFacesContextWrapper

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package javax.faces.component;

import javax.el.MethodExpression;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextWrapper;
import javax.faces.el.MethodBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFListener;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;

/**
*
* @author Leonardo Uribe
* @since 2.2
*/
@JSFComponent(name = "f:viewAction")
public class UIViewAction extends UIComponentBase implements ActionSource2
{
    //private static final Logger log = Logger.getLogger(UIViewAction.class.getName());
    public static final String COMPONENT_FAMILY = "javax.faces.ViewAction";
    public static final String COMPONENT_TYPE = "javax.faces.ViewAction";
   
    /**
     * Key in facesContext attribute map to check if a viewAction broadcast is
     * being processed. This is used to check when a JSF lifecycle restart is required
     * by the NavigationHandler implementation.
     */
    private static final String BROADCAST_PROCESSING_KEY = "oam.viewAction.broadcast";
   
    /**
     * Key in facesContext attribute map to count the number of viewAction events that
     * remains to be processed.
     */
    private static final String EVENT_COUNT_KEY = "oam.viewAction.eventCount";

    public UIViewAction()
    {
        setRendererType(null);
    }

    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException
    {
        super.broadcast(event);
       
        FacesContext context = getFacesContext();
       
        if (context.getResponseComplete())
        {
            return;
        }
       
        UIComponent c = event.getComponent();
        UIViewRoot sourceViewRoot = null;
        do
        {
            if (c instanceof UIViewRoot)
            {
                sourceViewRoot = (UIViewRoot) c;
                break;
            }
            else
            {
                c = c.getParent();
            }
        } while (c != null);
       
        if (!context.getViewRoot().equals(sourceViewRoot))
        {
            return;
        }
       
        if (event instanceof ActionEvent)
        {
            ActionListener defaultActionListener = context.getApplication().getActionListener();
            if (defaultActionListener != null)
            {
                String  viewIdBeforeAction = context.getViewRoot().getViewId();
                Boolean oldBroadcastProcessing = (Boolean) context.getAttributes().
                    get(BROADCAST_PROCESSING_KEY);
                try
                {
                    context.getAttributes().put(BROADCAST_PROCESSING_KEY, Boolean.TRUE);

                    ViewActionFacesContextWrapper wrappedFacesContext = new ViewActionFacesContextWrapper(context);

                    try
                    {
                        wrappedFacesContext.setWrapperAsCurrentFacesContext();

                        MethodBinding mb = getActionListener();
                        if (mb != null)
                        {
                            mb.invoke(context, new Object[]
                            { event });
                        }

                        if (defaultActionListener != null)
                        {
                            defaultActionListener.processAction((ActionEvent) event);
                        }
                       
                        // Decrement count
                        Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
                        count = (count == null) ? 0 : count - 1;
                        context.getAttributes().put(EVENT_COUNT_KEY, count);
                    }
                    finally
                    {
                        wrappedFacesContext.restoreCurrentFacesContext();
                    }
                }
                finally
                {
                    context.getAttributes().put(BROADCAST_PROCESSING_KEY,
                        oldBroadcastProcessing == null ? Boolean.FALSE : oldBroadcastProcessing);
                }

                if (context.getResponseComplete())
                {
                    return;
                }
                else
                {
                    Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
                    count = (count == null) ? 0 : count;
                    String viewIdAfterAction = context.getViewRoot().getViewId();

                    if (viewIdBeforeAction.equals(viewIdAfterAction) && count == 0)
                    {
                        context.renderResponse();
                    }
                    // "... Otherwise, execute the lifecycle on the new UIViewRoot ..."
                    // Note these words are implemented in the NavigationHandler, but
                    // the original proposal from seam s:viewAction did a trick here
                    // to restart the JSF lifecycle.
                }
            }
        }
    }

    @Override
    public void decode(FacesContext context)
    {
        super.decode(context);
       
        if (context.isPostback() && !isOnPostback())
        {
            return;
        }
       
        if (!isRendered())
        {
            return;
        }
       
        ActionEvent evt = new ActionEvent(this);
        String phase = getPhase();
        PhaseId phaseId = (phase != null) ? PhaseId.phaseIdValueOf(phase) :
            isImmediate() ? PhaseId.APPLY_REQUEST_VALUES : PhaseId.INVOKE_APPLICATION;
        evt.setPhaseId(phaseId);
        this.queueEvent(evt);
       
        // "... Keep track of the number of events that are queued in this way
        // on this run through the lifecycle. ...". The are two options:
        // 1. Use an attribute over FacesContext attribute map
        // 2. Use an attribute over the component
        // If the view is recreated again with the same viewId, the component
        // state get lost, so the option 1 is preferred.
        Integer count = (Integer) context.getAttributes().get(EVENT_COUNT_KEY);
        count = (count == null) ? 1 : count + 1;
        context.getAttributes().put(EVENT_COUNT_KEY, count);
    }

    @Override
    public void queueEvent(FacesEvent event)
    {
        if (event != null && event instanceof ActionEvent)
        {
            UIComponent component = event.getComponent();
            if (component instanceof ActionSource)
            {
                if (((ActionSource)component).isImmediate())
                {
                    event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
                }
                else
                {
                    event.setPhaseId(PhaseId.INVOKE_APPLICATION);
                }
            }
        }
        super.queueEvent(event);
    }
   
    public MethodBinding getAction()
    {
        MethodExpression actionExpression = getActionExpression();
        if (actionExpression instanceof _MethodBindingToMethodExpression)
        {
            return ((_MethodBindingToMethodExpression) actionExpression)
                    .getMethodBinding();
        }
        if (actionExpression != null)
        {
            return new _MethodExpressionToMethodBinding(actionExpression);
        }
        return null;
    }

    /**
     * @deprecated Use setActionExpression instead.
     */
    public void setAction(MethodBinding action)
    {
        if (action != null)
        {
            setActionExpression(new _MethodBindingToMethodExpression(action));
        }
        else
        {
            setActionExpression(null);
        }
    }

    @JSFProperty
    public boolean isImmediate()
    {
        return (Boolean) getStateHelper().eval(PropertyKeys.immediate, Boolean.FALSE);
    }

    public void setImmediate(boolean immediate)
    {
        getStateHelper().put(PropertyKeys.immediate, immediate );
    }

    @JSFProperty
    public Object getValue()
    {
        return  getStateHelper().eval(PropertyKeys.value);
    }

    public void setValue(Object value)
    {
        getStateHelper().put(PropertyKeys.value, value );
    }

    @JSFProperty(stateHolder=true, returnSignature = "java.lang.Object", jspName = "action", clientEvent="action")
    public MethodExpression getActionExpression()
    {
        return (MethodExpression) getStateHelper().eval(PropertyKeys.actionExpression);
    }

    public void setActionExpression(MethodExpression actionExpression)
    {
        getStateHelper().put(PropertyKeys.actionExpression, actionExpression);
    }

    @JSFProperty(stateHolder=true, returnSignature = "void", methodSignature = "javax.faces.event.ActionEvent")
    public MethodBinding getActionListener()
    {
        return (MethodBinding) getStateHelper().eval(PropertyKeys.actionListener);
    }

    /**
     * @deprecated
     */
    @JSFProperty(returnSignature="void",methodSignature="javax.faces.event.ActionEvent")
    public void setActionListener(MethodBinding actionListener)
    {
        getStateHelper().put(PropertyKeys.actionListener, actionListener);
        // Note f:viewAction does not have actionListener property defined.
        //throw new UnsupportedOperationException();
    }

    public void addActionListener(ActionListener listener)
    {
        addFacesListener(listener);
    }

    public void removeActionListener(ActionListener listener)
    {
        removeFacesListener(listener);
    }

    @JSFListener(event="javax.faces.event.ActionEvent",
            phases="Invoke Application, Apply Request Values")
    public ActionListener[] getActionListeners()
    {
        return (ActionListener[]) getFacesListeners(ActionListener.class);
    }
   
    @JSFProperty
    public String getPhase()
    {
        return (String) getStateHelper().get(PropertyKeys.phase);
    }
   
    public void setPhase(String phase)
    {
        getStateHelper().put(PropertyKeys.phase, phase);
    }
   
    @JSFProperty
    public boolean isOnPostback()
    {
        return (Boolean) getStateHelper().eval(PropertyKeys.onPostback, Boolean.FALSE);
    }

    public void setOnPostback(boolean onPostback)
    {
        getStateHelper().put(PropertyKeys.onPostback, onPostback );
    }   
   
    public static boolean isProcessingBroadcast(FacesContext context)
    {
        return Boolean.TRUE.equals(context.getAttributes().get(BROADCAST_PROCESSING_KEY));
    }

    enum PropertyKeys
    {
         immediate
        , value
        , actionExpression
        , actionListener
        , phase
        , onPostback
    }

    @Override
    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }
   
    private static class ViewActionFacesContextWrapper extends FacesContextWrapper
    {
        private FacesContext delegate;
        private boolean renderResponseCalled;

        public ViewActionFacesContextWrapper(FacesContext delegate)
        {
            this.delegate = delegate;
            this.renderResponseCalled = false;
        }

        @Override
        public void renderResponse()
        {
            //Take no action
            renderResponseCalled = true;
        }
       
        public boolean isRenderResponseCalled()
        {
            return renderResponseCalled;
        }
       
        @Override
        public FacesContext getWrapped()
        {
            return delegate;
        }
       
        void setWrapperAsCurrentFacesContext()
        {
            setCurrentInstance(this);
        }
       
        void restoreCurrentFacesContext()
        {
            setCurrentInstance(delegate);
        }
    }
}
TOP

Related Classes of javax.faces.component.UIViewAction$ViewActionFacesContextWrapper

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.