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