1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.ppr;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.myfaces.custom.dojo.DojoConfig;
25 import org.apache.myfaces.custom.dojo.DojoUtils;
26 import org.apache.myfaces.custom.subform.SubForm;
27 import org.apache.myfaces.renderkit.html.util.AddResource;
28 import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
29 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
30 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
31 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
32 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
33
34 import javax.faces.FacesException;
35 import javax.faces.component.UIComponent;
36 import javax.faces.context.ExternalContext;
37 import javax.faces.context.FacesContext;
38 import javax.faces.context.ResponseWriter;
39 import java.io.IOException;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.ArrayList;
43
44
45
46
47
48 public class PPRSupport
49 {
50 private static Log log = LogFactory.getLog(PPRSupport.class);
51
52 private static final String PPR_INITIALIZED = "org.apache.myfaces.ppr.INITIALIZED";
53
54 private static final String PPR_JS_FILE = "ppr.js";
55
56 private static final String ADD_PARTIAL_TRIGGER_FUNCTION = "addPartialTrigger";
57
58 private static final String ADD_PERIODICAL_TRIGGER_FUNCTION = "addPeriodicalTrigger";
59
60 private static final String ADD_PARTIAL_TRIGGER_PATTERN_FUNCTION = "addPartialTriggerPattern";
61
62 private static final String SET_SUBFORM_ID_FUNCTION = "setSubFormId";
63
64 private static final String SET_COMPONENT_UPDATE_FUNCTION = "setComponentUpdateFunction";
65
66 private static final String ADD_INLINE_LOADING_MESSAGE_FUNCTION = "addInlineLoadingMessage";
67
68 private static final String MY_FACES_PPR_INIT_CODE = "new org.apache.myfaces.PPRCtrl";
69
70
71 public final static String COMMAND_CONFIGURED_MARK = PPRSupport.class.getName() + "_CONFIGURED";
72
73 public final static String PROCESS_COMPONENTS = PPRSupport.class.getName() + "PROCESS_COMPONENTS";
74
75
76 public static boolean isPartialRequest(FacesContext facesContext)
77 {
78 return PPRPhaseListener.isPartialRequest(facesContext);
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public static void initPPR(FacesContext facesContext, PPRPanelGroup uiComponent) throws IOException
94 {
95
96
97
98 final ExternalContext externalContext = facesContext.getExternalContext();
99 final Map requestMap = externalContext.getRequestMap();
100
101
102
103
104 if (!requestMap.containsKey(PPR_INITIALIZED)) {
105 requestMap.put(PPR_INITIALIZED, Boolean.TRUE);
106
107 String encoding = "UTF-8";
108 if (facesContext.getResponseWriter().getCharacterEncoding() != null) {
109 encoding = facesContext.getResponseWriter().getCharacterEncoding();
110 }
111
112 DojoConfig currentConfig = DojoUtils.getDjConfigInstance(facesContext);
113 currentConfig.setBindEncoding(encoding);
114
115 String javascriptLocation = (String) uiComponent.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
116 AddResource addResource = AddResourceFactory.getInstance(facesContext);
117 DojoUtils.addMainInclude(facesContext, uiComponent, javascriptLocation, currentConfig);
118 DojoUtils.addRequire(facesContext, uiComponent, "dojo.io.*");
119 DojoUtils.addRequire(facesContext, uiComponent, "dojo.event.*");
120 DojoUtils.addRequire(facesContext, uiComponent, "dojo.xml.*");
121 addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, PPRPanelGroup.class, PPR_JS_FILE);
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public static void encodeJavaScript(FacesContext facesContext, PPRPanelGroup pprGroup) throws IOException
141 {
142 StringBuffer script = new StringBuffer();
143
144
145
146
147
148 script.append("dojo.addOnLoad( function(){ ");
149
150 String pprCtrlReference = initPPRFormControl(facesContext, pprGroup, script);
151
152 encodePeriodicalUpdates(facesContext, pprGroup, script, pprCtrlReference);
153
154 encodePartialTriggerPattern(facesContext, pprGroup, script, pprCtrlReference);
155
156 encodeSubFormFunction(facesContext, pprGroup, script, pprCtrlReference);
157
158 encodeDomUpdateConfig(facesContext, pprGroup, script, pprCtrlReference);
159
160 encodeInlineLoadMsg(facesContext, pprGroup, script, pprCtrlReference);
161
162 encodePartialTriggers(facesContext, pprGroup, script, pprCtrlReference);
163
164
165 script.append("});");
166
167
168 renderInlineScript(facesContext, pprGroup, script.toString());
169 }
170
171 public static void encodeJavaScriptTriggerOnly(FacesContext context, UIComponent uiComponent, PPRPanelGroup pprGroup,
172 PartialTriggerParser.PartialTrigger trigger) throws IOException
173 {
174 StringBuffer script = new StringBuffer();
175 script.append("dojo.addOnLoad( function(){ ");
176 String pprCtrlReference = initPPRFormControl(context, pprGroup, script);
177 String clientId = pprGroup.getClientId(context);
178 encodePartialTrigger(context, script, pprCtrlReference, clientId, uiComponent, trigger);
179
180 script.append("});");
181
182
183 renderInlineScript(context, pprGroup, script.toString());
184 }
185
186 private static void encodePartialTrigger(FacesContext facesContext,
187 StringBuffer script,
188 String pprCtrlReference,
189 String clientId,
190 UIComponent partialTriggerComponent,
191 PartialTriggerParser.PartialTrigger trigger)
192 {
193 String partialTriggerClientId;
194 String partialTriggerId = trigger.getPartialTriggerId();
195 if (partialTriggerComponent == null) {
196 partialTriggerComponent = facesContext.getViewRoot().findComponent(partialTriggerId);
197 }
198 if (partialTriggerComponent != null) {
199 partialTriggerClientId = partialTriggerComponent.getClientId(facesContext);
200 script.append(pprCtrlReference + "." + ADD_PARTIAL_TRIGGER_FUNCTION + "('" + partialTriggerClientId + "'," + encodeArray(trigger.getEventHooks()) + ",'" + clientId + "');");
201 }
202 else {
203 if (log.isDebugEnabled()) {
204 log.debug("PPRPanelGroupRenderer Component with id " + partialTriggerId + " not found!");
205 }
206 }
207 }
208
209 private static void encodePartialTriggers(FacesContext context, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
210 {
211 String clientId = pprGroup.getClientId(context);
212 UIComponent partialTriggerComponent;
213
214 List partialTriggerIds = pprGroup.parsePartialTriggers();
215 for (int i = 0; i < partialTriggerIds.size(); i++) {
216 PartialTriggerParser.PartialTrigger trigger = (PartialTriggerParser.PartialTrigger) partialTriggerIds
217 .get(i);
218 partialTriggerComponent = pprGroup.findComponent(trigger.getPartialTriggerId());
219 encodePartialTrigger(context, script, pprCtrlReference, clientId, partialTriggerComponent, trigger);
220 }
221 }
222
223 private static void encodePartialTriggerPattern(FacesContext context, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
224 {
225 String clientId = pprGroup.getClientId(context);
226
227 String partialTriggerPattern = pprGroup.getPartialTriggerPattern();
228
229
230 if (partialTriggerPattern != null && partialTriggerPattern.trim().length() > 0) {
231 script.append(pprCtrlReference + "." + ADD_PARTIAL_TRIGGER_PATTERN_FUNCTION + "('" + partialTriggerPattern + "','" + clientId + "');");
232 }
233
234 }
235
236 private static void encodeInlineLoadMsg(FacesContext context, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
237 {
238 String clientId = pprGroup.getClientId(context);
239 String inlineLoadingMessage = pprGroup.getInlineLoadingMessage();
240
241
242 if (inlineLoadingMessage != null && inlineLoadingMessage.trim().length() > 0) {
243 script.append(pprCtrlReference + "." + ADD_INLINE_LOADING_MESSAGE_FUNCTION + "('" + inlineLoadingMessage + "','" + clientId + "');");
244 }
245 }
246
247 private static void encodeSubFormFunction(FacesContext context, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
248 {
249 String clientId = pprGroup.getClientId(context);
250 SubForm subFormParent = findParentSubForm(pprGroup);
251 if (subFormParent != null) {
252 script.append(pprCtrlReference + "." + SET_SUBFORM_ID_FUNCTION + "('" + subFormParent.getId() + "','" + clientId + "');");
253 }
254 }
255
256 private static void encodeDomUpdateConfig(FacesContext context, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
257 {
258 String componentUpdateFunction = pprGroup.getComponentUpdateFunction();
259 if (!StringUtils.isEmpty(componentUpdateFunction)) {
260 script.append(pprCtrlReference + "." + SET_COMPONENT_UPDATE_FUNCTION+ "('" + componentUpdateFunction + "');");
261 }
262 }
263
264 private static void encodePeriodicalUpdates(FacesContext facesContext, PPRPanelGroup pprGroup, StringBuffer script, String pprCtrlReference)
265 {
266 String clientId = pprGroup.getClientId(facesContext);
267
268
269 if (pprGroup.getPeriodicalUpdate() != null) {
270 List partialTriggers = pprGroup.parsePeriodicalTriggers();
271 if (partialTriggers.size() == 0) {
272 Integer wait = null;
273 if (pprGroup.getExcludeFromStoppingPeriodicalUpdate() != null) {
274 wait = pprGroup.getWaitBeforePeriodicalUpdate();
275 }
276 script.append(pprCtrlReference + ".startPeriodicalUpdate(" + pprGroup.getPeriodicalUpdate() + ",'" + clientId + "', " + wait + ");");
277 }
278 else {
279 String periodicalTriggerId;
280 String periodicalTriggerClientId;
281 UIComponent periodicalTriggerComponent;
282 for (int i = 0; i < partialTriggers.size(); i++) {
283 PartialTriggerParser.PartialTrigger trigger = (PartialTriggerParser.PartialTrigger) partialTriggers
284 .get(i);
285 periodicalTriggerId = trigger.getPartialTriggerId();
286 periodicalTriggerComponent = pprGroup.findComponent(periodicalTriggerId);
287 if (periodicalTriggerComponent == null) {
288 periodicalTriggerComponent = facesContext.getViewRoot().findComponent(periodicalTriggerId);
289 }
290
291
292 if (periodicalTriggerComponent != null) {
293 periodicalTriggerClientId = periodicalTriggerComponent.getClientId(facesContext);
294 script.append(pprCtrlReference + "." + ADD_PERIODICAL_TRIGGER_FUNCTION +
295 "('" + periodicalTriggerClientId + "'," +
296 encodeArray(trigger.getEventHooks()) + ",'" + clientId + "', " +
297 pprGroup.getPeriodicalUpdate() + ");");
298
299
300 }
301 else {
302 if (log.isDebugEnabled()) {
303 log.debug("PPRPanelGroupRenderer Component with id " + periodicalTriggerId + " not found!");
304 }
305 }
306 }
307 }
308
309 String idRegex = pprGroup.getExcludeFromStoppingPeriodicalUpdate();
310
311 if (idRegex != null) {
312 script.append(pprCtrlReference + ".excludeFromStoppingPeriodicalUpdate('" + idRegex + "');");
313 }
314 }
315 }
316
317 private static String initPPRFormControl(FacesContext facesContext, PPRPanelGroup pprGroup, StringBuffer script)
318 {
319 FormInfo fi = RendererUtils.findNestingForm(pprGroup, facesContext);
320 if (fi == null) {
321 throw new FacesException("PPRPanelGroup must be embedded in a form.");
322 }
323 final String formName = fi.getFormName();
324 Map requestMap = facesContext.getExternalContext().getRequestMap();
325
326 String pprCtrlReference = "dojo.byId('" + formName + "').myFacesPPRCtrl";
327
328
329
330
331
332
333
334
335
336 boolean pprInited = pprGroup.getInitializationSent();
337 if (!PPRSupport.isPartialRequest(facesContext))
338 {
339
340
341 pprInited = Boolean.TRUE.equals(requestMap.get(PPR_INITIALIZED + "." + formName));
342 }
343
344 if (!pprInited) {
345 pprGroup.setInitializationSent(true);
346 requestMap.put(PPR_INITIALIZED + "." + formName, Boolean.TRUE);
347
348 script.append(pprCtrlReference + "=" + MY_FACES_PPR_INIT_CODE + "('" + formName + "'," + pprGroup.getShowDebugMessages().booleanValue() + "," + pprGroup.getStateUpdate().booleanValue() + ");\n");
349
350 if (pprGroup.getPeriodicalUpdate() != null) {
351 script.append(pprCtrlReference + ".registerOnSubmitInterceptor();");
352 }
353 }
354 return pprCtrlReference;
355 }
356
357 public static SubForm findParentSubForm(UIComponent base)
358 {
359 if (base == null) {
360 return null;
361 }
362 if (base instanceof SubForm) {
363 return (SubForm) base;
364 }
365 return findParentSubForm(base.getParent());
366 }
367
368 private static String encodeArray(List eventHooks)
369 {
370 if (eventHooks == null || eventHooks.size() == 0) {
371 return "null";
372 }
373 else {
374 StringBuffer buf = new StringBuffer();
375 buf.append("[");
376
377 for (int i = 0; i < eventHooks.size(); i++) {
378 if (i > 0) {
379 buf.append(",");
380 }
381 String eventHook = (String) eventHooks.get(i);
382 buf.append("'");
383 buf.append(eventHook);
384 buf.append("'");
385 }
386 buf.append("]");
387
388 return buf.toString();
389 }
390 }
391
392
393
394
395
396
397
398
399
400
401 private static void renderInlineScript(FacesContext facesContext, UIComponent component, String script) throws IOException
402 {
403 ResponseWriter writer = facesContext.getResponseWriter();
404 writer.startElement(HTML.SCRIPT_ELEM, component);
405 writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
406 writer.write(script);
407 writer.endElement(HTML.SCRIPT_ELEM);
408 }
409
410
411
412
413
414
415
416
417
418
419 public static List getComponentsByCommaSeparatedIdList(FacesContext context, UIComponent comp, String idList, Class desiredType)
420 {
421 List retval = new ArrayList();
422 UIComponent currentComponent = null;
423 String[] ids = StringUtils.split(idList, ',');
424 for (int i = 0; i < ids.length; i++) {
425 String id = StringUtils.trim(ids[i]);
426 currentComponent = comp.findComponent(id);
427 if (nullSafeCheckComponentType(desiredType, currentComponent)) {
428 retval.add(currentComponent);
429 }
430 else {
431 currentComponent = context.getViewRoot().findComponent(id);
432 if (nullSafeCheckComponentType(desiredType, currentComponent)) {
433 retval.add(currentComponent);
434 }
435 }
436 }
437 return retval;
438 }
439
440 private static boolean nullSafeCheckComponentType(Class desiredType, UIComponent currentComponent)
441 {
442 return currentComponent != null && (desiredType == null || desiredType.isAssignableFrom(currentComponent.getClass()));
443 }
444 }