/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.renderkit.html;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIParameter;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.ActionEvent;
import org.ajax4jsf.Messages;
import org.ajax4jsf.javascript.AjaxScript;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.renderkit.HeaderResourcesRendererBase;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
import org.ajax4jsf.resource.InternetResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* "Wrapped" standard {@link javax.faces.component.html.HtmlCommandLink} renderer,
* to avoid common problem - If no commandLink's exist in initial rendered page, {@link javax.faces.component.html.HtmlForm} renderer
* don't encode nessesary hidden fields for link and it's param. Our form-link renderer can avoid this problem.
* @author shura
*
*/
public class HtmlCommandLinkRenderer extends HeaderResourcesRendererBase {
private static final Log _log = LogFactory.getLog(HtmlCommandLinkRenderer.class);
private static final String[] LINK_EXCLUSIONS = {"onclick","target","href"};
private InternetResource[] scripts = null;
private static final String FORM_SCRIPT = "/org/ajax4jsf/javascript/scripts/form.js";
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.renderkit.RendererBase#doDecode(javax.faces.context.FacesContext,
* javax.faces.component.UIComponent)
*/
protected void doDecode(FacesContext context, UIComponent component) {
UIForm form = getUtils().getNestingForm(context,component);
if(null != form){
String hiddenFieldId = getHiddenFieldId(context, form, component);
Object hiddenFieldValue;
if(null != (hiddenFieldValue=context.getExternalContext().getRequestParameterMap().get(hiddenFieldId))){
if(component.getClientId(context).equals(hiddenFieldValue)){
// Link submitted !
if(_log.isDebugEnabled()){
_log.debug(Messages.getMessage(Messages.COMMAND_LINK_SUBMIT_INFO, component.getClientId(context)));
}
ActionEvent actionEvent = new ActionEvent(component);
component.queueEvent(actionEvent);
}
}
}
}
/* (non-Javadoc)
* @see org.ajax4jsf.renderkit.RendererBase#doEncodeBegin(javax.faces.context.ResponseWriter, javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
protected void doEncodeBegin(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
if(isDisabled(context,component)){
doEncodePassiveBegin(writer, context, component);
} else {
doEncodeActiveBegin(writer, context, component);
}
}
private String getHiddenFieldId(FacesContext context, UIForm form, UIComponent component) {
return form.getClientId(context)+AjaxFormRenderer.HIDDEN_FIELD_SUFFIX;
}
protected void doEncodeActiveBegin(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException{
writer.startElement(HTML.a_ELEMENT,component);
getUtils().encodeId(context,component);
getUtils().encodeAttributesFromArray(context,component,HTML.PASS_THRU_STYLES);
getUtils().encodePassThruWithExclusionsArray(context,component,LINK_EXCLUSIONS);
writer.writeAttribute("href","#",null);
UIForm form = getUtils().getNestingForm(context,component);
String clientId = component.getClientId(context);
if(null == form){
if(_log.isWarnEnabled()){
_log.warn(Messages.getMessage(Messages.COMMAND_LINK_NOT_IN_FORM_WARNING, clientId));
}
return;
}
// Encode onclick attribute.
Object click = component.getAttributes().get("onclick");
StringBuffer onclick = new StringBuffer(256);
if(null != click){
onclick.append(click).append(';');
}
JSFunction submit = new JSFunction(AjaxFormRenderer.FORM_SUBMIT_FUNCTION_NAME);
submit.addParameter(clientId);
submit.addParameter(form.getClientId(context));
submit.addParameter(component.getAttributes().get("target"));
Map parameters = new HashMap();
for (Iterator iter = component.getChildren().iterator(); iter.hasNext();) {
Object child = iter.next();
if (child instanceof UIParameter) {
UIParameter param = (UIParameter) child;
String name = ((UIParameter) child).getName();
Object value = ((UIParameter) child).getValue();
if (name == null) {
throw new IllegalArgumentException(Messages.getMessage(
Messages.UNNAMED_PARAMETER_ERROR, component.getClientId(context)));
}
if (value == null) {
value = "";
}
parameters.put(name,value);
}
}
parameters.put(getHiddenFieldId(context, form, component), component.getClientId(context));
submit.addParameter(parameters);
onclick.append("return ");
submit.appendScript(onclick);
writer.writeAttribute(HTML.onclick_ATTRIBUTE,onclick,"onclick");
//
encodeValue(writer,context,component);
}
protected void doEncodePassiveBegin(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException{
writer.startElement(HTML.SPAN_ELEM,component);
getUtils().encodeId(context,component);
getUtils().encodeAttributesFromArray(context,component,HTML.PASS_THRU_STYLES);
getUtils().encodePassThru(context,component);
encodeValue(writer,context,component);
}
/* (non-Javadoc)
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
// TODO Auto-generated method stub
renderChildren(context,component);
}
/* (non-Javadoc)
* @see org.ajax4jsf.renderkit.RendererBase#doEncodeEnd(javax.faces.context.ResponseWriter, javax.faces.context.FacesContext, javax.faces.component.UIComponent)
*/
protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
if(isDisabled(context,component)){
doEncodePassiveEnd(writer, context, component);
} else {
doEncodeActiveEnd(writer, context, component);
}
}
protected void doEncodeActiveEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException{
writer.endElement(HTML.a_ELEMENT);
}
protected void doEncodePassiveEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException{
writer.endElement(HTML.SPAN_ELEM);
}
/**
* Check for disabled component
* @param context
* @param command
* @return true if link is disabled.
*/
private boolean isDisabled(FacesContext context, UIComponent command){
if (command.getAttributes().get("disabled") != null) {
if ((command.getAttributes().get("disabled")).equals(Boolean.TRUE)) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.ajax4jsf.renderkit.RendererBase#getComponentClass()
*/
protected Class getComponentClass() {
// TODO Auto-generated method stub
return UICommand.class;
}
/* (non-Javadoc)
* @see javax.faces.render.Renderer#getRendersChildren()
*/
public boolean getRendersChildren() {
return true;
}
protected void encodeValue(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException{
String valueString = null;
if (component instanceof UICommand) {
Object value = ((UICommand) component).getValue();
if (value != null) {
valueString = value.toString();
}
} else if (component instanceof ValueHolder) {
Object value = ((ValueHolder) component).getValue();
if (value != null) {
valueString = getUtils().formatValue(context,component,value);
}
}
if (null != valueString && valueString.length()>0) {
writer.writeText(valueString,null);
}
}
/* (non-Javadoc)
* @see org.ajax4jsf.renderkit.HeaderResourcesRendererBase#getScripts()
*/
protected InternetResource[] getScripts() {
synchronized (this) {
if (scripts == null) {
scripts = new InternetResource[1];
scripts[0] = getResource(FORM_SCRIPT);
}
}
return scripts;
}
}