View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.remotecommand;
23  
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.Map;
27  
28  import javax.el.MethodExpression;
29  import javax.faces.application.ResourceDependency;
30  import javax.faces.component.UICommand;
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  import javax.faces.convert.Converter;
34  import javax.faces.event.ActionEvent;
35  import javax.faces.event.ActionListener;
36  import javax.faces.event.FacesEvent;
37  import javax.faces.event.FacesListener;
38  
39  import org.primefaces.component.api.AjaxSource;
40  import org.primefaces.extensions.component.base.AbstractParameter;
41  import org.primefaces.extensions.component.parameters.AssignableParameter;
42  import org.primefaces.extensions.component.parameters.MethodParameter;
43  
44  /**
45   * Component class for the <code>RemoteCommand</code> component.
46   *
47   * @author Thomas Andraschko / last modified by $Author$
48   * @version $Revision$
49   * @since 0.2
50   */
51  @ResourceDependency(library = "primefaces", name = "jquery/jquery.js")
52  @ResourceDependency(library = "primefaces", name = "jquery/jquery-plugins.js")
53  @ResourceDependency(library = "primefaces", name = "core.js")
54  @ResourceDependency(library = "primefaces-extensions", name = "primefaces-extensions.js")
55  public class RemoteCommand extends UICommand implements AjaxSource {
56  
57      public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.RemoteCommand";
58      public static final String COMPONENT_FAMILY = "org.primefaces.extensions.component";
59      private static final String DEFAULT_RENDERER = "org.primefaces.extensions.component.RemoteCommandRenderer";
60  
61      private List<AbstractParameter> allParameters = null;
62      private List<AssignableParameter> assignableParameters = null;
63      private List<MethodParameter> methodParameters = null;
64      private Object[] convertedMethodParams = null;
65  
66      /**
67       * Properties that are tracked by state saving.
68       *
69       * @author Thomas Andraschko / last modified by $Author$
70       * @version $Revision$
71       */
72      @SuppressWarnings("java:S115")
73      protected enum PropertyKeys {
74  
75          //@formatter:off
76          name,
77          update,
78          process,
79          onstart,
80          oncomplete,
81          onerror,
82          onsuccess,
83          global,
84          async,
85          partialSubmit,
86          action,
87          autoRun,
88          actionListener,
89          resetValues,
90          ignoreAutoUpdate,
91          delay,
92          timeout,
93          partialSubmitFilter,
94          form,
95          ignoreComponentNotFound
96          //@formatter:on
97      }
98  
99      public RemoteCommand() {
100         setRendererType(DEFAULT_RENDERER);
101     }
102 
103     @Override
104     public String getFamily() {
105         return COMPONENT_FAMILY;
106     }
107 
108     public String getName() {
109         return (String) getStateHelper().eval(PropertyKeys.name, null);
110     }
111 
112     public void setName(final String name) {
113         getStateHelper().put(PropertyKeys.name, name);
114     }
115 
116     @Override
117     public String getUpdate() {
118         return (String) getStateHelper().eval(PropertyKeys.update, null);
119     }
120 
121     public void setUpdate(final String update) {
122         getStateHelper().put(PropertyKeys.update, update);
123     }
124 
125     @Override
126     public String getProcess() {
127         return (String) getStateHelper().eval(PropertyKeys.process, null);
128     }
129 
130     public void setProcess(final String process) {
131         getStateHelper().put(PropertyKeys.process, process);
132     }
133 
134     @Override
135     public String getOnstart() {
136         return (String) getStateHelper().eval(PropertyKeys.onstart, null);
137     }
138 
139     public void setOnstart(final String onstart) {
140         getStateHelper().put(PropertyKeys.onstart, onstart);
141     }
142 
143     @Override
144     public String getOncomplete() {
145         return (String) getStateHelper().eval(PropertyKeys.oncomplete, null);
146     }
147 
148     public void setOncomplete(final String oncomplete) {
149         getStateHelper().put(PropertyKeys.oncomplete, oncomplete);
150     }
151 
152     @Override
153     public String getOnerror() {
154         return (String) getStateHelper().eval(PropertyKeys.onerror, null);
155     }
156 
157     public void setOnerror(final String onerror) {
158         getStateHelper().put(PropertyKeys.onerror, onerror);
159     }
160 
161     @Override
162     public String getOnsuccess() {
163         return (String) getStateHelper().eval(PropertyKeys.onsuccess, null);
164     }
165 
166     public void setOnsuccess(final String onsuccess) {
167         getStateHelper().put(PropertyKeys.onsuccess, onsuccess);
168     }
169 
170     @Override
171     public boolean isGlobal() {
172         return (Boolean) getStateHelper().eval(PropertyKeys.global, true);
173     }
174 
175     public void setGlobal(final boolean global) {
176         getStateHelper().put(PropertyKeys.global, global);
177     }
178 
179     @Override
180     public boolean isAsync() {
181         return (Boolean) getStateHelper().eval(PropertyKeys.async, false);
182     }
183 
184     public void setAsync(final boolean async) {
185         getStateHelper().put(PropertyKeys.async, async);
186     }
187 
188     @Override
189     public boolean isPartialSubmit() {
190         return (Boolean) getStateHelper().eval(PropertyKeys.partialSubmit, false);
191     }
192 
193     public void setPartialSubmit(final boolean partialSubmit) {
194         getStateHelper().put(PropertyKeys.partialSubmit, partialSubmit);
195     }
196 
197     public boolean isAutoRun() {
198         return (Boolean) getStateHelper().eval(PropertyKeys.autoRun, false);
199     }
200 
201     public void setAutoRun(final boolean autoRun) {
202         getStateHelper().put(PropertyKeys.autoRun, autoRun);
203     }
204 
205     public MethodExpression getActionListenerMethodExpression() {
206         return (MethodExpression) getStateHelper().get(PropertyKeys.actionListener);
207     }
208 
209     public void setActionListenerMethodExpression(final MethodExpression actionListener) {
210         getStateHelper().put(PropertyKeys.actionListener, actionListener);
211     }
212 
213     @Override
214     public boolean isPartialSubmitSet() {
215         return getStateHelper().get(PropertyKeys.partialSubmit) != null || getValueExpression("partialSubmit") != null;
216     }
217 
218     @Override
219     public boolean isResetValues() {
220         return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.resetValues, false);
221     }
222 
223     public void setResetValues(final boolean resetValues) {
224         getStateHelper().put(PropertyKeys.resetValues, resetValues);
225     }
226 
227     @Override
228     public boolean isIgnoreAutoUpdate() {
229         return (java.lang.Boolean) getStateHelper().eval(PropertyKeys.ignoreAutoUpdate, false);
230     }
231 
232     public void setIgnoreAutoUpdate(final boolean ignoreAutoUpdate) {
233         getStateHelper().put(PropertyKeys.ignoreAutoUpdate, ignoreAutoUpdate);
234     }
235 
236     @Override
237     public boolean isResetValuesSet() {
238         return getStateHelper().get(PropertyKeys.resetValues) != null || getValueExpression("resetValues") != null;
239     }
240 
241     @Override
242     public java.lang.String getDelay() {
243         return (java.lang.String) getStateHelper().eval(PropertyKeys.delay, null);
244     }
245 
246     public void setDelay(final java.lang.String delay) {
247         getStateHelper().put(PropertyKeys.delay, delay);
248     }
249 
250     @Override
251     public int getTimeout() {
252         return (java.lang.Integer) getStateHelper().eval(PropertyKeys.timeout, 0);
253     }
254 
255     public void setTimeout(final int timeout) {
256         getStateHelper().put(PropertyKeys.timeout, timeout);
257     }
258 
259     @Override
260     public java.lang.String getPartialSubmitFilter() {
261         return (java.lang.String) getStateHelper().eval(PropertyKeys.partialSubmitFilter, null);
262     }
263 
264     public void setPartialSubmitFilter(final java.lang.String _partialSubmitFilter) {
265         getStateHelper().put(PropertyKeys.partialSubmitFilter, _partialSubmitFilter);
266     }
267 
268     @Override
269     public java.lang.String getForm() {
270         return (java.lang.String) getStateHelper().eval(PropertyKeys.form, null);
271     }
272 
273     public void setForm(final java.lang.String _form) {
274         getStateHelper().put(PropertyKeys.form, _form);
275     }
276 
277     @Override
278     public void broadcast(final FacesEvent event) {
279         for (final FacesListener listener : getFacesListeners(FacesListener.class)) {
280             if (event.isAppropriateListener(listener)) {
281                 event.processListener(listener);
282             }
283         }
284 
285         if (event instanceof ActionEvent) {
286             final FacesContext context = getFacesContext();
287 
288             // invoke actionListener
289             final MethodExpression listener = getActionListenerMethodExpression();
290             if (listener != null) {
291                 listener.invoke(context.getELContext(), getConvertedMethodParameters(context));
292             }
293 
294             // invoke action
295             final ActionListener actionListener = context.getApplication().getActionListener();
296             if (actionListener != null) {
297                 actionListener.processAction((ActionEvent) event);
298             }
299         }
300     }
301 
302     protected void findChildParameters() {
303         if (allParameters == null || assignableParameters == null || methodParameters == null) {
304             allParameters = new ArrayList<>();
305             assignableParameters = new ArrayList<>();
306             methodParameters = new ArrayList<>();
307 
308             for (final UIComponent child : super.getChildren()) {
309                 if (child instanceof AbstractParameter) {
310                     allParameters.add((AbstractParameter) child);
311 
312                     if (child instanceof AssignableParameter) {
313                         assignableParameters.add((AssignableParameter) child);
314                     }
315                     else {
316                         if (child instanceof MethodParameter) {
317                             methodParameters.add((MethodParameter) child);
318                         }
319                     }
320                 }
321             }
322         }
323     }
324 
325     protected List<AbstractParameter> getAllParameters() {
326         findChildParameters();
327 
328         return allParameters;
329     }
330 
331     protected List<AssignableParameter> getAssignableParameters() {
332         findChildParameters();
333 
334         return assignableParameters;
335     }
336 
337     protected List<MethodParameter> getMethodParameters() {
338         findChildParameters();
339 
340         return methodParameters;
341     }
342 
343     protected Object[] getConvertedMethodParameters(final FacesContext context) {
344         if (convertedMethodParams == null) {
345             convertedMethodParams = new Object[getMethodParameters().size()];
346 
347             for (int i = 0; i < getMethodParameters().size(); i++) {
348                 final MethodParameter methodParameter = getMethodParameters().get(i);
349 
350                 final Converter converter = methodParameter.getConverter();
351                 final String parameterValue = getParameterValue(context, methodParameter.getName());
352 
353                 if (converter == null) {
354                     convertedMethodParams[i] = parameterValue;
355                 }
356                 else {
357                     final Object convertedValue = converter.getAsObject(context, methodParameter, parameterValue);
358                     convertedMethodParams[i] = convertedValue;
359                 }
360             }
361         }
362 
363         return convertedMethodParams;
364     }
365 
366     public String getParameterValue(final FacesContext context, final String name) {
367         final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
368         final String clientId = getClientId(context);
369 
370         return params.get(clientId + "_" + name);
371     }
372 
373     @Override
374     public boolean isAjaxified() {
375         return true;
376     }
377 
378     @Override
379     public boolean isIgnoreComponentNotFound() {
380         return (Boolean) getStateHelper().eval(PropertyKeys.ignoreComponentNotFound, false);
381     }
382 
383     public void setIgnoreComponentNotFound(final boolean ignoreComponentNotFound) {
384         getStateHelper().put(PropertyKeys.ignoreComponentNotFound, ignoreComponentNotFound);
385     }
386 
387     @Override
388     public Object saveState(FacesContext context) {
389         // reset component for MyFaces view pooling
390         allParameters = null;
391         assignableParameters = null;
392         methodParameters = null;
393         convertedMethodParams = null;
394 
395         return super.saveState(context);
396     }
397 }