View Javadoc
1   package org.andromda.cartridges.jsf.renderkit.html;
2   
3   import java.io.IOException;
4   import java.util.Iterator;
5   import java.util.Map;
6   import javax.faces.component.NamingContainer;
7   import javax.faces.component.UICommand;
8   import javax.faces.component.UIComponent;
9   import javax.faces.component.UIForm;
10  import javax.faces.component.UIViewRoot;
11  import javax.faces.context.FacesContext;
12  import javax.faces.context.ResponseWriter;
13  import javax.faces.el.MethodBinding;
14  import javax.faces.event.ActionEvent;
15  import javax.faces.render.Renderer;
16  import org.andromda.cartridges.jsf.Constants;
17  import org.andromda.cartridges.jsf.component.html.HtmlPopupFrame;
18  import org.andromda.cartridges.jsf.utils.ComponentUtils;
19  
20  /**
21   * A custom renderer for rendering a popup frame.
22   */
23  public class PopupRenderer
24      extends Renderer
25  {
26      /**
27       * hiddenPopupFrame
28       */
29      public static final String POPUP_FRAME_HIDDEN = "hiddenPopupFrame";
30  
31      /**
32       * Retrieve the popup resource path (the path within the
33       * deployed web application) given the relative <code>path</code>
34       *
35       * @param path the relative path.
36       * @return the complete path including the context path of the application.
37       */
38      private String getPopupResourcePath(final String path)
39      {
40          return ComponentUtils.getContextPath(FacesContext.getCurrentInstance().getExternalContext().getRequest()) + Constants.RESOURCE_CONTEXT + path;
41      }
42  
43      private Object getRequestAttribute(final String attributeName)
44      {
45          return ComponentUtils.getAttribute(FacesContext.getCurrentInstance().getExternalContext().getRequest(), attributeName);
46      }
47  
48      private void setRequestAttribute(final String attributeName, final String attributeValue)
49      {
50          ComponentUtils.setAttribute(FacesContext.getCurrentInstance().getExternalContext().getRequest(), attributeName, attributeValue);
51      }
52  
53      /**
54       * keeps track of whether or not the javascript has been rendered.
55       */
56      private static final String JS_ATTRIBUTE = "andromda.jsf.js";
57  
58      /**
59       * @param context
60       * @param component
61       * @throws IOException
62       */
63      protected void commonJavascript(
64          final FacesContext context,
65          final UIComponent component)
66          throws IOException
67      {
68          final ResponseWriter writer = context.getResponseWriter();
69          if (this.getRequestAttribute(JS_ATTRIBUTE) == null)
70          {
71              this.setRequestAttribute(
72                  JS_ATTRIBUTE,
73                  JS_ATTRIBUTE);
74              writer.startElement(
75                  "script",
76                  component);
77              writer.writeAttribute(
78                  "language",
79                  "JavaScript",
80                  null);
81              writer.writeAttribute(
82                  "src",
83                  getPopupResourcePath("/popup/js/popup.js"),
84                  null);
85              writer.endElement("script");
86          }
87          writer.startElement(
88              "input",
89              null);
90          writer.writeAttribute(
91              "type",
92              "hidden",
93              null);
94          writer.writeAttribute(
95              "name",
96              POPUP_FRAME_HIDDEN,
97              null);
98          writer.writeAttribute(
99              "value",
100             "",
101             null);
102         writer.endElement("input");
103     }
104 
105     private static final String DEFAULT_STYLE =
106         "position:absolute; left:0; top:0; visibility:hidden; border:1px solid black; background-color:#FFFFFF; ";
107 
108     /**
109      * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
110      */
111     public void decode(
112         final FacesContext context,
113         final UIComponent component)
114     {
115         final HtmlPopupFrame command = (HtmlPopupFrame)component;
116         final Map parameters = context.getExternalContext().getRequestParameterMap();
117         final String popupAction = (String)parameters.get(PopupRenderer.POPUP_FRAME_HIDDEN);
118         if (popupAction != null && popupAction.equals(getHiddenFieldOpen(
119                     command,
120                     context)))
121         {
122             final MethodBinding binding = command.getActionOpen();
123             command.setAction(binding);
124             final ActionEvent actionEvent = new ActionEvent(command);
125             if (command.isImmediate())
126             {
127                 command.queueEventImmediate(actionEvent);
128             }
129             else
130             {
131                 command.queueEventNormal(actionEvent);
132             }
133         }
134         else if (popupAction != null && popupAction.equals(getHiddenFieldClose(
135                     command,
136                     context)))
137         {
138             final MethodBinding binding = command.getActionClose();
139             if (binding != null)
140             {
141                 command.setAction(binding);
142                 ActionEvent actionEvent = new ActionEvent(command);
143                 command.queueEventImmediate(actionEvent);
144             }
145         }
146     }
147 
148     /**
149      * @see javax.faces.render.Renderer#getRendersChildren()
150      */
151     public boolean getRendersChildren()
152     {
153         return true;
154     }
155 
156     private String getHiddenFieldOpen(
157         HtmlPopupFrame command,
158         FacesContext context)
159     {
160         return command.getClientId(context) + NamingContainer.SEPARATOR_CHAR + UIViewRoot.UNIQUE_ID_PREFIX + "op";
161     }
162 
163     private String getHiddenFieldClose(
164         HtmlPopupFrame command,
165         FacesContext context)
166     {
167         return command.getClientId(context) + NamingContainer.SEPARATOR_CHAR + UIViewRoot.UNIQUE_ID_PREFIX + "cl";
168     }
169 
170     /**
171      * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
172      */
173     public void encodeBegin(
174         FacesContext context,
175         UIComponent component)
176         throws IOException
177     {
178         final HtmlPopupFrame command = (HtmlPopupFrame)component;
179         if (command.isRendered())
180         {
181             final UIForm uiform = this.getForm(
182                     context,
183                     command);
184             if (uiform == null)
185             {
186                 throw new RuntimeException("JSF h:form needed to use this component");
187             }
188 
189             final String formClientId = uiform.getClientId(context);
190 
191             // start differences from command link
192             final ResponseWriter writer = context.getResponseWriter();
193             commonJavascript(
194                 context,
195                 command);
196 
197             writer.startElement(
198                 "a",
199                 command);
200             writer.writeAttribute(
201                 "href",
202                 "#",
203                 null);
204 
205             String form = "document.forms['" + formClientId + "']";
206 
207             StringBuilder buffer = new StringBuilder();
208             buffer.append("showPopupFrame(");
209             buffer.append(form);
210             buffer.append(",this,event");
211             buffer.append(",'");
212             buffer.append(getHiddenFieldClose(
213                     command,
214                     context));
215             buffer.append("','");
216             buffer.append(command.getStyleClassFrame() == null ? "" : command.getStyleClassFrame());
217             buffer.append("','");
218             buffer.append(DEFAULT_STYLE);
219             buffer.append(command.getStyleFrame() == null ? "" : command.getStyleFrame());
220             buffer.append("',");
221             buffer.append(command.getMouseHorizPos() == null ? "0" : command.getMouseHorizPos());
222             buffer.append(',');
223             buffer.append(command.getMouseVertPos() == null ? "0" : command.getMouseVertPos());
224             buffer.append(',');
225             buffer.append(command.getAbsolute() == null ? "false" : command.getAbsolute());
226             buffer.append(',');
227             buffer.append(command.getCenter() == null ? "false" : command.getCenter());
228             buffer.append(",'");
229             buffer.append(command.getHeight() == null ? "" : command.getHeight());
230             buffer.append("','");
231             buffer.append(command.getWidth() == null ? "" : command.getWidth());
232             buffer.append("','");
233             buffer.append(command.getScrolling() == null ? "auto" : command.getScrolling().toLowerCase());
234             buffer.append("');");
235 
236             buffer.append(form);
237             buffer.append(".target='");
238             buffer.append("hiddenPopupFrameTarget");
239             buffer.append("';");
240 
241             buffer.append(form);
242             buffer.append(".elements['");
243             buffer.append(POPUP_FRAME_HIDDEN);
244             buffer.append("'].value='");
245             buffer.append(getHiddenFieldOpen(
246                     command,
247                     context));
248             buffer.append("';");
249 
250             buffer.append(form);
251             buffer.append(".submit();");
252             buffer.append(form);
253             buffer.append(".elements['");
254             buffer.append(POPUP_FRAME_HIDDEN);
255             buffer.append("'].value='';");
256 
257             buffer.append(form);
258             buffer.append(".target='';");
259 
260             buffer.append("return false;");
261 
262             writer.writeAttribute(
263                 "onclick",
264                 buffer.toString(),
265                 null);
266 
267             writer.writeAttribute(
268                 "id",
269                 command.getClientId(context),
270                 null);
271 
272             final String accesskey = command.getAccesskey();
273             if (accesskey != null)
274             {
275                 writer.writeAttribute(
276                     "accesskey",
277                     accesskey,
278                     "accesskey");
279             }
280 
281             final String directory = command.getDir();
282             if (directory != null)
283             {
284                 writer.writeAttribute(
285                     "dir",
286                     directory,
287                     "dir");
288             }
289 
290             final String lang = command.getLang();
291             if (lang != null)
292             {
293                 writer.writeAttribute(
294                     "lang",
295                     lang,
296                     "lang");
297             }
298 
299             final String tabindex = command.getTabindex();
300             if (tabindex != null)
301             {
302                 writer.writeAttribute(
303                     "tabindex",
304                     tabindex,
305                     "tabindex");
306             }
307 
308             final String title = command.getTitle();
309             if (title != null)
310             {
311                 writer.writeAttribute(
312                     "title",
313                     title,
314                     "title");
315             }
316 
317             final String styleClass = command.getStyleClass();
318             if (styleClass != null)
319             {
320                 writer.writeAttribute(
321                     "class",
322                     styleClass,
323                     "styleClass");
324             }
325 
326             final String style = command.getStyle();
327             if (style != null)
328             {
329                 writer.writeAttribute(
330                     "style",
331                     style,
332                     "style");
333             }
334 
335             String label = null;
336             final Object value = ((UICommand)component).getValue();
337             if (value != null)
338             {
339                 label = value.toString();
340             }
341             if (label != null && label.length() != 0)
342             {
343                 writer.write(label);
344             }
345             writer.flush();
346         }
347     }
348 
349     /**
350      * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
351      */
352     public void encodeChildren(
353         final FacesContext context,
354         final UIComponent component)
355         throws IOException
356     {
357         // - only render if rendered is true
358         if (component.isRendered())
359         {
360             for (Iterator iterator = component.getChildren().iterator(); iterator.hasNext();)
361             {
362                 final UIComponent child = (UIComponent)iterator.next();
363                 child.encodeBegin(context);
364                 if (child.getRendersChildren())
365                 {
366                     child.encodeChildren(context);
367                 }
368                 child.encodeEnd(context);
369             }
370         }
371     }
372 
373     /**
374      * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
375      */
376     public void encodeEnd(
377         final FacesContext context,
378         final UIComponent component)
379         throws IOException
380     {
381         final UICommand command = (UICommand)component;
382 
383         // - only render if rendered is true
384         if (command.isRendered())
385         {
386             final ResponseWriter writer = context.getResponseWriter();
387 
388             // - complete writing Anchor element
389             writer.endElement("a");
390             writer.flush();
391         }
392     }
393 
394     /**
395      * @see javax.faces.render.Renderer#convertClientId(javax.faces.context.FacesContext, String)
396      */
397     public String convertClientId(
398         final FacesContext context,
399         final String clientId)
400     {
401         return clientId;
402     }
403 
404     /**
405      * Gets the form to which the <code>component</code> belongs
406      * or null if the form can not be found.
407      *
408      * @param context the faces context.
409      * @param component the component.
410      * @return the form.
411      */
412     protected UIForm getForm(
413         final FacesContext context,
414         final UIComponent component)
415     {
416         UIComponent parent = component.getParent();
417         while (parent != null)
418         {
419             if (parent instanceof UIForm)
420             {
421                 break;
422             }
423             parent = parent.getParent();
424         }
425         return (UIForm)parent;
426     }
427 }