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.el.MethodExpression;
22  import javax.el.ValueExpression;
23  import javax.faces.context.FacesContext;
24  import javax.faces.el.MethodBinding;
25  import javax.faces.event.AbortProcessingException;
26  import javax.faces.event.ActionEvent;
27  import javax.faces.event.ActionListener;
28  import javax.faces.event.FacesEvent;
29  import javax.faces.event.PhaseId;
30  
31  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
32  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFListener;
33  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
34  
35  /**
36   * 
37   * UICommand is a base abstraction for components that implement ActionSource.
38   * 
39   */
40  @JSFComponent(defaultRendererType = "javax.faces.Button")
41  public class UICommand extends UIComponentBase implements ActionSource2
42  {
43      public static final String COMPONENT_TYPE = "javax.faces.Command";
44      public static final String COMPONENT_FAMILY = "javax.faces.Command";
45  
46      private boolean _immediate;
47      private boolean _immediateSet;
48      private Object _value;
49      private MethodExpression _actionExpression;
50      private MethodBinding _actionListener;
51  
52      /**
53       * Construct an instance of the UICommand.
54       */
55      public UICommand()
56      {
57          setRendererType("javax.faces.Button");
58      }
59  
60      /**
61       * Specifies the action to take when this command is invoked.
62       * <p>
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       * </p>
69       * <p>
70       * If the value is a string literal, it is treated as a navigation outcome
71       * for the current view.  This is functionally equivalent to a reference to
72       * an action method that returns the string literal.
73       * </p>
74       * 
75       * @deprecated Use getActionExpression() instead.
76       */
77      public MethodBinding getAction()
78      {
79          MethodExpression actionExpression = getActionExpression();
80          if (actionExpression instanceof _MethodBindingToMethodExpression)
81          {
82              return ((_MethodBindingToMethodExpression) actionExpression)
83                      .getMethodBinding();
84          }
85          if (actionExpression != null)
86          {
87              return new _MethodExpressionToMethodBinding(actionExpression);
88          }
89          return null;
90      }
91  
92      /**
93       * @deprecated Use setActionExpression instead.
94       */
95      public void setAction(MethodBinding action)
96      {
97          if (action != null)
98          {
99              setActionExpression(new _MethodBindingToMethodExpression(action));
100         }
101         else
102         {
103             setActionExpression(null);
104         }
105     }
106 
107     @Override
108     public void broadcast(FacesEvent event) throws AbortProcessingException
109     {
110         super.broadcast(event);
111 
112         if (event instanceof ActionEvent)
113         {
114             FacesContext context = getFacesContext();
115 
116             MethodBinding mb = getActionListener();
117             if (mb != null)
118             {
119                 mb.invoke(context, new Object[]
120                 { event });
121             }
122 
123             ActionListener defaultActionListener = context.getApplication()
124                     .getActionListener();
125             if (defaultActionListener != null)
126             {
127                 defaultActionListener.processAction((ActionEvent) event);
128             }
129         }
130     }
131 
132     @Override
133     public void queueEvent(FacesEvent event)
134     {
135         if (event != null && event instanceof ActionEvent)
136         {
137             UIComponent component = event.getComponent();
138             if (component instanceof ActionSource)
139             {
140                 if (((ActionSource)component).isImmediate())
141                 {
142                     event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
143                 }
144                 else
145                 {
146                     event.setPhaseId(PhaseId.INVOKE_APPLICATION);
147                 }
148             }
149         }
150         super.queueEvent(event);
151     }
152 
153     /**
154      * A boolean value that identifies the phase during which action events
155      * should fire.
156      * <p>
157      * During normal event processing, action methods and action listener methods are fired during the
158      * "invoke application" phase of request processing. If this attribute is set to "true", these methods
159      * are fired instead at the end of the "apply request values" phase.
160      * </p>
161      */
162     @JSFProperty
163     public boolean isImmediate()
164     {
165         if (_immediateSet)
166         {
167             return _immediate;
168         }
169         ValueExpression expression = getValueExpression("immediate");
170         if (expression != null)
171         {
172             return (Boolean) expression.getValue(getFacesContext()
173                     .getELContext());
174         }
175         return false;
176     }
177 
178     public void setImmediate(boolean immediate)
179     {
180         this._immediate = immediate;
181         this._immediateSet = true;
182     }
183 
184     /**
185      * The text to display to the user for this command component.
186      */
187     @JSFProperty
188     public Object getValue()
189     {
190         if (_value != null)
191         {
192             return _value;
193         }
194         ValueExpression expression = getValueExpression("value");
195         if (expression != null)
196         {
197             return expression.getValue(getFacesContext().getELContext());
198         }
199         return null;
200     }
201 
202     public void setValue(Object value)
203     {
204         this._value = value;
205     }
206 
207     /**
208      * The action to take when this command is invoked.
209      * <p>
210      * If the value is an expression, it is expected to be a method binding EL expression that identifies
211      * an action method. An action method accepts no parameters and has a String return value, called the
212      * action outcome, that identifies the next view displayed. The phase that this event is fired in
213      * can be controlled via the immediate attribute.
214      * </p>
215      * <p> 
216      * If the value is a string literal, it is treated as a navigation outcome for the current view. This
217      * is functionally equivalent to a reference to an action method that returns the string literal.
218      * </p>
219      */
220     @JSFProperty(stateHolder = true, returnSignature = "java.lang.Object", jspName = "action")
221     public MethodExpression getActionExpression()
222     {
223         if (_actionExpression != null)
224         {
225             return _actionExpression;
226         }
227         ValueExpression expression = getValueExpression("actionExpression");
228         if (expression != null)
229         {
230             return (MethodExpression) expression.getValue(getFacesContext()
231                     .getELContext());
232         }
233         return null;
234     }
235 
236     public void setActionExpression(MethodExpression actionExpression)
237     {
238         this._actionExpression = actionExpression;
239     }
240 
241     /**
242      * A method binding EL expression that identifies an action listener method to be invoked if
243      * this component is activated by the user.
244      * <p>
245      * An action listener method accepts a parameter of type javax.faces.event.ActionEvent and returns void.
246      * The phase that this event is fired in can be controlled via the immediate attribute.
247      * 
248      * @deprecated
249      */
250     @JSFProperty(stateHolder = true, returnSignature = "void", methodSignature = "javax.faces.event.ActionEvent")
251     public MethodBinding getActionListener()
252     {
253         if (_actionListener != null)
254         {
255             return _actionListener;
256         }
257         ValueExpression expression = getValueExpression("actionListener");
258         if (expression != null)
259         {
260             return (MethodBinding) expression.getValue(getFacesContext()
261                     .getELContext());
262         }
263         return null;
264     }
265 
266     /**
267      * @deprecated
268      */
269     @JSFProperty(returnSignature="void",methodSignature="javax.faces.event.ActionEvent")
270     public void setActionListener(MethodBinding actionListener)
271     {
272         this._actionListener = actionListener;
273     }
274 
275     public void addActionListener(ActionListener listener)
276     {
277         addFacesListener(listener);
278     }
279 
280     public void removeActionListener(ActionListener listener)
281     {
282         removeFacesListener(listener);
283     }
284 
285     /**
286      * Event delivered when the "action" of the component has been
287      * invoked; for example, by clicking on a button. The action may result 
288      * in page navigation.
289      */
290     @JSFListener(event="javax.faces.event.ActionEvent",
291             phases="Invoke Application, Apply Request Values")
292     public ActionListener[] getActionListeners()
293     {
294         return (ActionListener[]) getFacesListeners(ActionListener.class);
295     }
296 
297     @Override
298     public Object saveState(FacesContext facesContext)
299     {
300         Object[] values = new Object[6];
301         values[0] = super.saveState(facesContext);
302         values[1] = _immediate;
303         values[2] = _immediateSet;
304         values[3] = _value;
305         values[4] = saveAttachedState(facesContext, _actionExpression);
306         values[5] = saveAttachedState(facesContext, _actionListener);
307 
308         return values;
309     }
310 
311     @Override
312     public void restoreState(FacesContext facesContext, Object state)
313     {
314         Object[] values = (Object[]) state;
315         super.restoreState(facesContext, values[0]);
316         _immediate = (Boolean) values[1];
317         _immediateSet = (Boolean) values[2];
318         _value = values[3];
319         _actionExpression = (MethodExpression) restoreAttachedState(
320                 facesContext, values[4]);
321         _actionListener = (MethodBinding) restoreAttachedState(facesContext,
322                 values[5]);
323     }
324 
325     @Override
326     public String getFamily()
327     {
328         return COMPONENT_FAMILY;
329     }
330 }