PopupRenderer.java
package org.andromda.cartridges.jsf.renderkit.html;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.faces.component.NamingContainer;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.MethodBinding;
import javax.faces.event.ActionEvent;
import javax.faces.render.Renderer;
import org.andromda.cartridges.jsf.Constants;
import org.andromda.cartridges.jsf.component.html.HtmlPopupFrame;
import org.andromda.cartridges.jsf.utils.ComponentUtils;
/**
* A custom renderer for rendering a popup frame.
*/
public class PopupRenderer
extends Renderer
{
/**
* hiddenPopupFrame
*/
public static final String POPUP_FRAME_HIDDEN = "hiddenPopupFrame";
/**
* Retrieve the popup resource path (the path within the
* deployed web application) given the relative <code>path</code>
*
* @param path the relative path.
* @return the complete path including the context path of the application.
*/
private String getPopupResourcePath(final String path)
{
return ComponentUtils.getContextPath(FacesContext.getCurrentInstance().getExternalContext().getRequest()) + Constants.RESOURCE_CONTEXT + path;
}
private Object getRequestAttribute(final String attributeName)
{
return ComponentUtils.getAttribute(FacesContext.getCurrentInstance().getExternalContext().getRequest(), attributeName);
}
private void setRequestAttribute(final String attributeName, final String attributeValue)
{
ComponentUtils.setAttribute(FacesContext.getCurrentInstance().getExternalContext().getRequest(), attributeName, attributeValue);
}
/**
* keeps track of whether or not the javascript has been rendered.
*/
private static final String JS_ATTRIBUTE = "andromda.jsf.js";
/**
* @param context
* @param component
* @throws IOException
*/
protected void commonJavascript(
final FacesContext context,
final UIComponent component)
throws IOException
{
final ResponseWriter writer = context.getResponseWriter();
if (this.getRequestAttribute(JS_ATTRIBUTE) == null)
{
this.setRequestAttribute(
JS_ATTRIBUTE,
JS_ATTRIBUTE);
writer.startElement(
"script",
component);
writer.writeAttribute(
"language",
"JavaScript",
null);
writer.writeAttribute(
"src",
getPopupResourcePath("/popup/js/popup.js"),
null);
writer.endElement("script");
}
writer.startElement(
"input",
null);
writer.writeAttribute(
"type",
"hidden",
null);
writer.writeAttribute(
"name",
POPUP_FRAME_HIDDEN,
null);
writer.writeAttribute(
"value",
"",
null);
writer.endElement("input");
}
private static final String DEFAULT_STYLE =
"position:absolute; left:0; top:0; visibility:hidden; border:1px solid black; background-color:#FFFFFF; ";
/**
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
public void decode(
final FacesContext context,
final UIComponent component)
{
final HtmlPopupFrame command = (HtmlPopupFrame)component;
final Map parameters = context.getExternalContext().getRequestParameterMap();
final String popupAction = (String)parameters.get(PopupRenderer.POPUP_FRAME_HIDDEN);
if (popupAction != null && popupAction.equals(getHiddenFieldOpen(
command,
context)))
{
final MethodBinding binding = command.getActionOpen();
command.setAction(binding);
final ActionEvent actionEvent = new ActionEvent(command);
if (command.isImmediate())
{
command.queueEventImmediate(actionEvent);
}
else
{
command.queueEventNormal(actionEvent);
}
}
else if (popupAction != null && popupAction.equals(getHiddenFieldClose(
command,
context)))
{
final MethodBinding binding = command.getActionClose();
if (binding != null)
{
command.setAction(binding);
ActionEvent actionEvent = new ActionEvent(command);
command.queueEventImmediate(actionEvent);
}
}
}
/**
* @see javax.faces.render.Renderer#getRendersChildren()
*/
public boolean getRendersChildren()
{
return true;
}
private String getHiddenFieldOpen(
HtmlPopupFrame command,
FacesContext context)
{
return command.getClientId(context) + NamingContainer.SEPARATOR_CHAR + UIViewRoot.UNIQUE_ID_PREFIX + "op";
}
private String getHiddenFieldClose(
HtmlPopupFrame command,
FacesContext context)
{
return command.getClientId(context) + NamingContainer.SEPARATOR_CHAR + UIViewRoot.UNIQUE_ID_PREFIX + "cl";
}
/**
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
public void encodeBegin(
FacesContext context,
UIComponent component)
throws IOException
{
final HtmlPopupFrame command = (HtmlPopupFrame)component;
if (command.isRendered())
{
final UIForm uiform = this.getForm(
context,
command);
if (uiform == null)
{
throw new RuntimeException("JSF h:form needed to use this component");
}
final String formClientId = uiform.getClientId(context);
// start differences from command link
final ResponseWriter writer = context.getResponseWriter();
commonJavascript(
context,
command);
writer.startElement(
"a",
command);
writer.writeAttribute(
"href",
"#",
null);
String form = "document.forms['" + formClientId + "']";
StringBuilder buffer = new StringBuilder();
buffer.append("showPopupFrame(");
buffer.append(form);
buffer.append(",this,event");
buffer.append(",'");
buffer.append(getHiddenFieldClose(
command,
context));
buffer.append("','");
buffer.append(command.getStyleClassFrame() == null ? "" : command.getStyleClassFrame());
buffer.append("','");
buffer.append(DEFAULT_STYLE);
buffer.append(command.getStyleFrame() == null ? "" : command.getStyleFrame());
buffer.append("',");
buffer.append(command.getMouseHorizPos() == null ? "0" : command.getMouseHorizPos());
buffer.append(',');
buffer.append(command.getMouseVertPos() == null ? "0" : command.getMouseVertPos());
buffer.append(',');
buffer.append(command.getAbsolute() == null ? "false" : command.getAbsolute());
buffer.append(',');
buffer.append(command.getCenter() == null ? "false" : command.getCenter());
buffer.append(",'");
buffer.append(command.getHeight() == null ? "" : command.getHeight());
buffer.append("','");
buffer.append(command.getWidth() == null ? "" : command.getWidth());
buffer.append("','");
buffer.append(command.getScrolling() == null ? "auto" : command.getScrolling().toLowerCase());
buffer.append("');");
buffer.append(form);
buffer.append(".target='");
buffer.append("hiddenPopupFrameTarget");
buffer.append("';");
buffer.append(form);
buffer.append(".elements['");
buffer.append(POPUP_FRAME_HIDDEN);
buffer.append("'].value='");
buffer.append(getHiddenFieldOpen(
command,
context));
buffer.append("';");
buffer.append(form);
buffer.append(".submit();");
buffer.append(form);
buffer.append(".elements['");
buffer.append(POPUP_FRAME_HIDDEN);
buffer.append("'].value='';");
buffer.append(form);
buffer.append(".target='';");
buffer.append("return false;");
writer.writeAttribute(
"onclick",
buffer.toString(),
null);
writer.writeAttribute(
"id",
command.getClientId(context),
null);
final String accesskey = command.getAccesskey();
if (accesskey != null)
{
writer.writeAttribute(
"accesskey",
accesskey,
"accesskey");
}
final String directory = command.getDir();
if (directory != null)
{
writer.writeAttribute(
"dir",
directory,
"dir");
}
final String lang = command.getLang();
if (lang != null)
{
writer.writeAttribute(
"lang",
lang,
"lang");
}
final String tabindex = command.getTabindex();
if (tabindex != null)
{
writer.writeAttribute(
"tabindex",
tabindex,
"tabindex");
}
final String title = command.getTitle();
if (title != null)
{
writer.writeAttribute(
"title",
title,
"title");
}
final String styleClass = command.getStyleClass();
if (styleClass != null)
{
writer.writeAttribute(
"class",
styleClass,
"styleClass");
}
final String style = command.getStyle();
if (style != null)
{
writer.writeAttribute(
"style",
style,
"style");
}
String label = null;
final Object value = ((UICommand)component).getValue();
if (value != null)
{
label = value.toString();
}
if (label != null && label.length() != 0)
{
writer.write(label);
}
writer.flush();
}
}
/**
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
public void encodeChildren(
final FacesContext context,
final UIComponent component)
throws IOException
{
// - only render if rendered is true
if (component.isRendered())
{
for (Iterator iterator = component.getChildren().iterator(); iterator.hasNext();)
{
final UIComponent child = (UIComponent)iterator.next();
child.encodeBegin(context);
if (child.getRendersChildren())
{
child.encodeChildren(context);
}
child.encodeEnd(context);
}
}
}
/**
* @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
public void encodeEnd(
final FacesContext context,
final UIComponent component)
throws IOException
{
final UICommand command = (UICommand)component;
// - only render if rendered is true
if (command.isRendered())
{
final ResponseWriter writer = context.getResponseWriter();
// - complete writing Anchor element
writer.endElement("a");
writer.flush();
}
}
/**
* @see javax.faces.render.Renderer#convertClientId(javax.faces.context.FacesContext, String)
*/
public String convertClientId(
final FacesContext context,
final String clientId)
{
return clientId;
}
/**
* Gets the form to which the <code>component</code> belongs
* or null if the form can not be found.
*
* @param context the faces context.
* @param component the component.
* @return the form.
*/
protected UIForm getForm(
final FacesContext context,
final UIComponent component)
{
UIComponent parent = component.getParent();
while (parent != null)
{
if (parent instanceof UIForm)
{
break;
}
parent = parent.getParent();
}
return (UIForm)parent;
}
}