View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package javax.faces.component;
20  
21  import javax.faces.context.FacesContext;
22  import javax.faces.el.EvaluationException;
23  import javax.faces.el.MethodBinding;
24  import javax.faces.el.ValueBinding;
25  import javax.faces.event.*;
26  
27  /**
28   * UICommand is a base abstraction for components that implement ActionSource.
29   * <p>
30   * See the javadoc for this class in the
31   * <a href="http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html">JSF Specification</a>
32   * for further details.
33   *
34   * @JSFComponent
35   *   type = "javax.faces.Command"
36   *   family = "javax.faces.Command"
37   *   desc = "UICommand executes an action"
38   *
39   * @author Manfred Geiler (latest modification by $Author: skitching $)
40   * @version $Revision: 685669 $ $Date: 2008-08-13 15:25:49 -0500 (Wed, 13 Aug 2008) $
41   */
42  public class UICommand extends UIComponentBase implements ActionSource
43  {
44      public static final String COMPONENT_TYPE = "javax.faces.Command";
45      public static final String COMPONENT_FAMILY = "javax.faces.Command";
46      private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Button";
47      private static final boolean DEFAULT_IMMEDIATE = false;
48  
49      private Boolean _immediate = null;
50      private Object _value = null;
51  
52      private MethodBinding _action = null;
53      private MethodBinding _actionListener = null;
54  
55      public void setAction(MethodBinding action)
56      {
57          _action = action;
58      }
59  
60      /**
61       * Specifies the action to take when this command is invoked.
62       *
63       * If the value is an expression, it is expected to be a method 
64       * binding EL expression that identifies an action method. An action method
65       * accepts no parameters and has a String return value, called the action
66       * outcome, that identifies the next view displayed. The phase that this
67       * event is fired in can be controlled via the immediate attribute.
68       *
69       * If the value is a string literal, it is treated as a navigation outcome
70       * for the current view.  This is functionally equivalent to a reference to
71       * an action method that returns the string literal.
72       * 
73       * @JSFProperty
74       *   returnSignature="java.lang.String"
75       */
76      public MethodBinding getAction()
77      {
78          return _action;
79      }
80  
81      public void setActionListener(MethodBinding actionListener)
82      {
83          _actionListener = actionListener;
84      }
85  
86      /**
87       * A method binding EL expression that identifies an action listener method
88       * to be invoked if this component is activated by the user. An action
89       * listener method accepts a parameter of type javax.faces.event.ActionEvent
90       * and returns void. The phase that this event is fired in can be controlled
91       * via the immediate attribute.
92       *  
93       * @JSFProperty
94       *   returnSignature="void"
95       *   methodSignature="javax.faces.event.ActionEvent"
96       */
97      public MethodBinding getActionListener()
98      {
99          return _actionListener;
100     }
101 
102     public void addActionListener(ActionListener listener)
103     {
104         addFacesListener(listener);
105     }
106 
107     public ActionListener[] getActionListeners()
108     {
109         return (ActionListener[])getFacesListeners(ActionListener.class);
110     }
111 
112     public void removeActionListener(ActionListener listener)
113     {
114         removeFacesListener(listener);
115     }
116 
117     public void broadcast(FacesEvent event)
118             throws AbortProcessingException
119     {
120         super.broadcast(event);
121 
122         if (event instanceof ActionEvent)
123         {
124             FacesContext context = getFacesContext();
125 
126             MethodBinding actionListenerBinding = getActionListener();
127             if (actionListenerBinding != null)
128             {
129                 try
130                 {
131                     actionListenerBinding.invoke(context, new Object[] {event});
132                 }
133                 catch (EvaluationException e)
134                 {
135                     Throwable cause = e.getCause();
136                     if (cause != null && cause instanceof AbortProcessingException)
137                     {
138                         throw (AbortProcessingException)cause;
139                     }
140                     else
141                     {
142                         throw e;
143                     }
144                 }
145             }
146 
147             ActionListener defaultActionListener
148                     = context.getApplication().getActionListener();
149             if (defaultActionListener != null)
150             {
151                 defaultActionListener.processAction((ActionEvent)event);
152             }
153         }
154     }
155 
156     public void queueEvent(FacesEvent event)
157     {
158         if (event != null && this == event.getSource() && event instanceof ActionEvent)
159         {
160             if (isImmediate())
161             {
162                 event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
163             }
164             else
165             {
166                 event.setPhaseId(PhaseId.INVOKE_APPLICATION);
167             }
168         }
169         super.queueEvent(event);
170     }
171 
172 
173     public UICommand()
174     {
175         setRendererType(DEFAULT_RENDERER_TYPE);
176     }
177 
178     public String getFamily()
179     {
180         return COMPONENT_FAMILY;
181     }
182 
183     public void setImmediate(boolean immediate)
184     {
185         _immediate = Boolean.valueOf(immediate);
186     }
187 
188     
189 
190     /**
191      * A boolean value that identifies the phase during which action events
192      * should fire. During normal event processing, action methods and
193      * action listener methods are fired during the "invoke application"
194      * phase of request processing. If this attribute is set to "true",
195      * these methods are fired instead at the end of the "apply request
196      * values" phase.
197      * 
198      * @JSFProperty
199      *   defaultValue="false"
200      */
201     public boolean isImmediate()
202     {
203         if (_immediate != null) return _immediate.booleanValue();
204         ValueBinding vb = getValueBinding("immediate");
205         Boolean v = vb != null ? (Boolean)vb.getValue(getFacesContext()) : null;
206         return v != null ? v.booleanValue() : DEFAULT_IMMEDIATE;
207     }
208 
209     public void setValue(Object value)
210     {
211         _value = value;
212     }
213 
214     /**
215      * The initial value of this component.
216      * 
217      * @JSFProperty
218      */
219     public Object getValue()
220     {
221         if (_value != null) return _value;
222         ValueBinding vb = getValueBinding("value");
223         return vb != null ? vb.getValue(getFacesContext()) : null;
224     }
225 
226 
227 
228     public Object saveState(FacesContext context)
229     {
230         Object values[] = new Object[5];
231         values[0] = super.saveState(context);
232         values[1] = saveAttachedState(context, _action);
233         values[2] = saveAttachedState(context, _actionListener);
234         values[3] = _immediate;
235         values[4] = _value;
236         return values;
237     }
238 
239     public void restoreState(FacesContext context, Object state)
240     {
241         Object values[] = (Object[])state;
242         super.restoreState(context, values[0]);
243         _action = (MethodBinding)restoreAttachedState(context, values[1]);
244         _actionListener = (MethodBinding)restoreAttachedState(context, values[2]);
245         _immediate = (Boolean)values[3];
246         _value = values[4];
247     }
248 }