/*
* xulfaces : bring XUL power to Java
*
* Copyright (C) 2005 Olivier SCHMITT
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.xulfaces.renderer.input;
import java.io.IOException;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.ValueBinding;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xulfaces.bridge.Bridge;
import org.xulfaces.bridge.Zone;
import org.xulfaces.bridge.command.NotValidCommand;
import org.xulfaces.renderer.XULRenderer;
import org.xulfaces.utils.XulUtils;
public class InputRenderer extends XULRenderer {
private static final Log log = LogFactory.getLog(InputRenderer.class);
protected void decodeUIInput(FacesContext facesContext,
UIComponent component) {
if (!(component instanceof EditableValueHolder)) {
throw new IllegalArgumentException("Component "
+ component.getClientId(facesContext)
+ " is not an EditableValueHolder");
}
String clientId = component.getClientId(facesContext);
if (isSubmitted(facesContext, component)) {
Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
// request parameter found, set submittedValue
((EditableValueHolder) component).setSubmittedValue(paramMap
.get(clientId));
if(log.isDebugEnabled()){
log.debug(component.getClass().getName() + " " + component.getId() + " value=" + paramMap.get(clientId));
}
} else {
((EditableValueHolder) component).setSubmittedValue(null);
}
}
@Override
public void encodeBegin(FacesContext facesContext, UIComponent component)
throws IOException {
super.encodeBegin(facesContext, component);
if (component instanceof EditableValueHolder) {
EditableValueHolder editableValueHolder = (EditableValueHolder) component;
if (!editableValueHolder.isValid()) {
Bridge bridge = XulUtils.getBridge();
Zone zone = new Zone(component.getClientId(facesContext));
bridge.addCommand(new NotValidCommand(zone));
}
}
}
public Object getConvertedValue(FacesContext context,
UIComponent component, Object submittedValue)
throws ConverterException {
// if we have no local value, try to get the valueBinding.
ValueBinding valueBinding = component.getValueBinding("value");
Converter converter = null;
Object result = null;
// If there is a converter attribute, use it to to ask application
// instance for a converter with this identifer.
if (component instanceof ValueHolder) {
converter = ((ValueHolder) component).getConverter();
}
if (null == converter && null != valueBinding) {
Class converterType = valueBinding.getType(context);
// if converterType is null, assume the modelType is "String".
if (converterType == null || converterType == String.class
|| converterType == Object.class) {
if (log.isDebugEnabled()) {
log.debug("No conversion necessary for " + submittedValue
+ "and converterType " + converterType
+ " while decoding component " + component.getId());
}
return submittedValue;
}
// if getType returns a type for which we support a default
// conversion, acquire an appropriate converter instance.
try {
Application application = context.getApplication();
converter = application.createConverter(converterType);
if (log.isDebugEnabled()) {
log.debug("Created converter " + converter + "of type "
+ converterType + " while decoding component "
+ component.getId());
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Converter could not be instantiated for "
+ converterType + " while " + "decoding component "
+ component.getId());
}
if(submittedValue instanceof Object[]){
if (log.isDebugEnabled()) {
log.debug("Assume we have a String array here.");
}
return submittedValue;
}
else {
return (null);
}
}
} else if (converter == null && valueBinding == null) {
// if there is no valueBinding and converter attribute set,
// assume the modelType as "String" since we have no way of
// figuring out the type. So for the selectOne and
// selectMany, converter has to be set if there is no
// valueBinding attribute set on the component.
if (log.isDebugEnabled()) {
log
.debug("No conversion necessary for "
+ submittedValue
+ " while decoding component "
+ component.getId()
+ "since there is no explicitly registered converter and "
+ "component value is not bound to a model property ");
}
return submittedValue;
}
if (converter != null) {
if(submittedValue instanceof Object[]){
String[] submittedValues = (String[]) submittedValue;
Object[] results = new Object[submittedValues.length];
for(int i=0; i < submittedValues.length;i++){
results[i] = converter.getAsObject(context, component, submittedValues[i]);
}
return results;
}
else {
result = converter.getAsObject(context, component, (String)submittedValue);
}
return result;
} else {
if (log.isDebugEnabled()) {
log.debug("Unexpected Converter exception "
+ " while decoding component " + component.getId() + " for value " + submittedValue);
}
throw new ConverterException("Converter error : "+ submittedValue);
}
}
protected void decodeUISelectMany(FacesContext facesContext,
UIComponent component) {
if (!(component instanceof EditableValueHolder)) {
throw new IllegalArgumentException("Component "
+ component.getClientId(facesContext)
+ " is not an EditableValueHolder");
}
Map paramMap = facesContext.getExternalContext()
.getRequestParameterMap();
String clientId = component.getClientId(facesContext);
if (paramMap.containsKey(clientId)) {
Object[] submittedValue = null;
// request parameter found, set submittedValue
String string = (String) paramMap.get(clientId);
if (string != null) {
submittedValue = string.split(" ");
}
((EditableValueHolder) component).setSubmittedValue(submittedValue);
} else {
((EditableValueHolder) component).setSubmittedValue(null);
}
}
protected String getAsString(FacesContext facesContext,
UIComponent component, Object value) {
Converter converter = ((ValueHolder) component).getConverter();
if (converter == null && value != null) {
if (value instanceof String) {
return (String) value;
}
try {
converter = facesContext.getApplication().createConverter(
value.getClass());
} catch (FacesException e) {
log.error("No converter for class "
+ value.getClass().getName() + " found (component id="
+ component.getId() + ").");
// converter stays null
}
}
if (converter == null) {
if (value == null) {
return null;
} else {
return value.toString();
}
} else {
return converter.getAsString(facesContext, component, value);
}
}
protected String getStringValue(FacesContext facesContext,
UIComponent component) {
try {
if (!(component instanceof ValueHolder)) {
throw new IllegalArgumentException("Component : "
+ "is not a ValueHolder");
}
if (component instanceof EditableValueHolder) {
EditableValueHolder editableValueHolder = (EditableValueHolder) component;
Object submittedValue = ((EditableValueHolder) component)
.getSubmittedValue();
if (!editableValueHolder.isValid()) {
editableValueHolder.setSubmittedValue(null);
}
if (submittedValue != null) {
if (submittedValue instanceof String) {
return (String) submittedValue;
} else {
throw new IllegalArgumentException(
"Expected submitted value of type String for component : ");
}
}
}
Object value = ((ValueHolder) component).getValue();
Converter converter = ((ValueHolder) component).getConverter();
if (converter == null && value != null) {
if (value instanceof String) {
return (String) value;
}
try {
converter = facesContext.getApplication().createConverter(
value.getClass());
} catch (FacesException e) {
log.error("No converter for class "
+ value.getClass().getName()
+ " found (component id=" + component.getId()
+ ").");
// converter stays null
}
}
if (converter == null) {
if (value == null) {
return "";
} else {
return value.toString();
}
} else {
return converter.getAsString(facesContext, component, value);
}
} catch (PropertyNotFoundException ex) {
log.error("Property not found - called by component : ");
throw ex;
}
}
}