You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/02/17 16:42:48 UTC
svn commit: r745124 - in /myfaces/tomahawk/trunk/core/src:
main/java/org/apache/myfaces/custom/date/
test/java/org/apache/myfaces/custom/date/
Author: lu4242
Date: Tue Feb 17 15:42:47 2009
New Revision: 745124
URL: http://svn.apache.org/viewvc?rev=745124&view=rev
Log:
TOMAHAWK-1014 HTMLInputDate ignores custom converters (changed decode and encodeEnd so converters can be set).
Modified:
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/AbstractHtmlInputDate.java
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/HtmlDateRenderer.java
myfaces/tomahawk/trunk/core/src/test/java/org/apache/myfaces/custom/date/HtmlDateRendererTest.java
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/AbstractHtmlInputDate.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/AbstractHtmlInputDate.java?rev=745124&r1=745123&r2=745124&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/AbstractHtmlInputDate.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/AbstractHtmlInputDate.java Tue Feb 17 15:42:47 2009
@@ -342,39 +342,36 @@
public abstract boolean isDisabled();
/**
- * This component converts submitted values to its inner class
- * UserData, so this method does not allow custom
- * converters to be defined.
+ * Retrieve the converter used by this component.
+ * <p>
+ * If no converter is selected, submitted values are converted to
+ * its inner class UserData on decode method.
+ * </p>
+ * <p>
+ * If some converter is used, submitted values are decoded as
+ * a String with the following format:
+ * </p>
+ * <p></p>
+ * <p>year=yyyy</p>
+ * <p>month=mm</p>
+ * <p>day=dd</p>
+ * <p>hours=hh</p>
+ * <p>minutes=mm</p>
+ * <p>seconds=ss</p>
+ * <p>ampm=ampm</p>
+ * <p></p>
+ * <p>
+ * Note that submitted values could be wrong and it is necessary to
+ * restore values on render response phase. The converter receive
+ * a string with this format on getAsObject method and it is expected
+ * the converter encode it on getAsString method, so the renderer can
+ * restore the submitted values correctly.
+ * </p>
*
* @JSFProperty
- * tagExcluded = "true"
*/
public Converter getConverter()
{
- return null;
- }
-
- public void setConverter(Converter converter)
- {
- throw new UnsupportedOperationException();
- }
-
- /**
- * This property comes from 1.2 UIInput, but since this
- * component does not allow a custom converter, this
- * should return null.
- *
- * @JSFProperty
- * tagExcluded = "true"
- * @return
- */
- public String getConverterMessage()
- {
- return null;
- }
-
- public void setConverterMessage(String converterMessage)
- {
- throw new UnsupportedOperationException();
+ return super.getConverter();
}
}
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/HtmlDateRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/HtmlDateRenderer.java?rev=745124&r1=745123&r2=745124&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/HtmlDateRenderer.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/date/HtmlDateRenderer.java Tue Feb 17 15:42:47 2009
@@ -19,11 +19,14 @@
package org.apache.myfaces.custom.date;
import java.io.IOException;
+import java.io.StringReader;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Locale;
import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
@@ -85,12 +88,63 @@
HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
Locale currentLocale = facesContext.getViewRoot().getLocale();
- UserData userData = (UserData) inputDate.getSubmittedValue();
- if( userData == null )
- userData = inputDate.getUserData(currentLocale);
+ UserData userData = null;
String type = inputDate.getType();
boolean ampm = inputDate.isAmpm();
String clientId = uiComponent.getClientId(facesContext);
+
+ if (null == inputDate.getConverter())
+ {
+ userData = (UserData) inputDate.getSubmittedValue();
+ if( userData == null )
+ userData = inputDate.getUserData(currentLocale);
+ }
+ else
+ {
+ //Use converter to get the value as string and
+ //create a UserData decoding it.
+ String value = org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.getStringValue(facesContext, inputDate);
+
+ //Create a UserData bean
+ userData = inputDate.getUserData(currentLocale);
+
+ if (null != value)
+ {
+ StringTokenizer st = new StringTokenizer(value,"\n");
+ while(st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (token.startsWith("year="))
+ {
+ userData.setYear(token.substring(5));
+ }
+ if (token.startsWith("month="))
+ {
+ userData.setYear(token.substring(6));
+ }
+ if (token.startsWith("day="))
+ {
+ userData.setYear(token.substring(4));
+ }
+ if (token.startsWith("hours="))
+ {
+ userData.setYear(token.substring(6));
+ }
+ if (token.startsWith("minutes="))
+ {
+ userData.setYear(token.substring(8));
+ }
+ if (token.startsWith("seconds="))
+ {
+ userData.setYear(token.substring(8));
+ }
+ if (token.startsWith("ampm="))
+ {
+ userData.setYear(token.substring(5));
+ }
+ }
+ }
+ }
boolean disabled = isDisabled(facesContext, inputDate);
boolean readonly = inputDate.isReadonly();
@@ -334,42 +388,122 @@
if( isDisabled(facesContext, inputDate) ) // For safety, do not set the submited value if the component is disabled.
return;
+
+ if (null == inputDate.getConverter())
+ {
+ //Instead of use a custom object to encode data,
+ //we have to encode all info in a String, so the converter
+ //can convert it to a String if the value
+ //is invalid.
+ String clientId = inputDate.getClientId(facesContext);
+ String type = inputDate.getType();
+ Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
+ StringBuffer submittedValue = new StringBuffer();
+ if( ! (type.equals( "time" ) || type.equals( "short_time" )) )
+ {
+ submittedValue.append("year=");
+ submittedValue.append((String) requestMap.get(clientId + ID_YEAR_POSTFIX) );
+ submittedValue.append("\n");
+
+ submittedValue.append("month=");
+ submittedValue.append((String) requestMap.get(clientId + ID_MONTH_POSTFIX));
+ submittedValue.append("\n");
+
+ submittedValue.append("day=");
+ submittedValue.append((String) requestMap.get(getClientIdForDaySubcomponent(clientId)) );
+ submittedValue.append("\n");
+ }
+
+ if( ! type.equals( "date" ) )
+ {
+ submittedValue.append("hours=");
+ submittedValue.append((String) requestMap.get(clientId + ID_HOURS_POSTFIX) );
+ submittedValue.append("\n");
+
+ submittedValue.append("minutes=");
+ submittedValue.append((String) requestMap.get(clientId + ID_MINUTES_POSTFIX) );
+ submittedValue.append("\n");
+
+ if (type.equals("full") || type.equals("time"))
+ {
+ submittedValue.append("seconds=");
+ submittedValue.append((String) requestMap.get(clientId + ID_SECONDS_POSTFIX) );
+ submittedValue.append("\n");
+ }
+
+ if (inputDate.isAmpm())
+ {
+ submittedValue.append("ampm=");
+ submittedValue.append((String) requestMap.get(clientId + ID_AMPM_POSTFIX) );
+ submittedValue.append("\n");
+ }
+ }
+ if (submittedValue.charAt(submittedValue.length()-1) == '\n' )
+ {
+ submittedValue.deleteCharAt(submittedValue.length()-1);
+ }
+
+ inputDate.setSubmittedValue( submittedValue.toString() );
+ }
+ else
+ {
+ //Use AbstractHtmlInputDate.UserData to save submitted value
+ Locale currentLocale = facesContext.getViewRoot().getLocale();
+ UserData userData = (UserData) inputDate.getSubmittedValue();
+ if( userData == null )
+ userData = inputDate.getUserData(currentLocale);
+
+ String clientId = inputDate.getClientId(facesContext);
+ String type = inputDate.getType();
+ Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
+
+ if( ! (type.equals( "time" ) || type.equals( "short_time" )) ){
+ userData.setDay( (String) requestMap.get(getClientIdForDaySubcomponent(clientId)) );
+ userData.setMonth( (String) requestMap.get(clientId + ID_MONTH_POSTFIX) );
+ userData.setYear( (String) requestMap.get(clientId + ID_YEAR_POSTFIX) );
+ }
- Locale currentLocale = facesContext.getViewRoot().getLocale();
- UserData userData = (UserData) inputDate.getSubmittedValue();
- if( userData == null )
- userData = inputDate.getUserData(currentLocale);
-
- String clientId = inputDate.getClientId(facesContext);
- String type = inputDate.getType();
- Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
-
- if( ! (type.equals( "time" ) || type.equals( "short_time" )) ){
- userData.setDay( (String) requestMap.get(getClientIdForDaySubcomponent(clientId)) );
- userData.setMonth( (String) requestMap.get(clientId + ID_MONTH_POSTFIX) );
- userData.setYear( (String) requestMap.get(clientId + ID_YEAR_POSTFIX) );
- }
-
- if( ! type.equals( "date" ) ){
- userData.setHours( (String) requestMap.get(clientId + ID_HOURS_POSTFIX) );
- userData.setMinutes( (String) requestMap.get(clientId + ID_MINUTES_POSTFIX) );
- if (type.equals("full") || type.equals("time"))
- userData.setSeconds( (String) requestMap.get(clientId + ID_SECONDS_POSTFIX) );
-
- if (inputDate.isAmpm()) {
- userData.setAmpm( (String) requestMap.get(clientId + ID_AMPM_POSTFIX) );
+ if( ! type.equals( "date" ) ){
+ userData.setHours( (String) requestMap.get(clientId + ID_HOURS_POSTFIX) );
+ userData.setMinutes( (String) requestMap.get(clientId + ID_MINUTES_POSTFIX) );
+ if (type.equals("full") || type.equals("time"))
+ userData.setSeconds( (String) requestMap.get(clientId + ID_SECONDS_POSTFIX) );
+
+ if (inputDate.isAmpm()) {
+ userData.setAmpm( (String) requestMap.get(clientId + ID_AMPM_POSTFIX) );
+ }
}
+ inputDate.setSubmittedValue( userData );
}
- inputDate.setSubmittedValue( userData );
}
-
+
public Object getConvertedValue(FacesContext context, UIComponent uiComponent, Object submittedValue) throws ConverterException {
- UserData userData = (UserData) submittedValue;
- try {
- return userData.parse();
- } catch (ParseException e) {
- Object[] args = {uiComponent.getId()};
- throw new ConverterException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, DATE_MESSAGE_ID, args));
+
+ HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
+
+ if (inputDate.getConverter() == null)
+ {
+ UserData userData = (UserData) submittedValue;
+ try {
+ return userData.parse();
+ } catch (ParseException e) {
+ Object[] args = {uiComponent.getId()};
+ throw new ConverterException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, DATE_MESSAGE_ID, args));
+ }
+ }
+ else
+ {
+ if (submittedValue != null && !(submittedValue instanceof String))
+ {
+ if (RendererUtils.NOTHING.equals(submittedValue))
+ {
+ return null;
+ }
+ throw new IllegalArgumentException("Submitted value of type String for component : "
+ + RendererUtils.getPathToComponent(inputDate) + "expected");
+ }
+
+ return inputDate.getConverter().getAsObject(context, inputDate, (String) submittedValue);
}
}
}
Modified: myfaces/tomahawk/trunk/core/src/test/java/org/apache/myfaces/custom/date/HtmlDateRendererTest.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/test/java/org/apache/myfaces/custom/date/HtmlDateRendererTest.java?rev=745124&r1=745123&r2=745124&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/test/java/org/apache/myfaces/custom/date/HtmlDateRendererTest.java (original)
+++ myfaces/tomahawk/trunk/core/src/test/java/org/apache/myfaces/custom/date/HtmlDateRendererTest.java Tue Feb 17 15:42:47 2009
@@ -19,17 +19,25 @@
package org.apache.myfaces.custom.date;
+import java.io.IOException;
+import java.io.StringReader;
+import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Properties;
import javax.faces.FactoryFinder;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
import javax.faces.render.RenderKitFactory;
import junit.framework.Test;
@@ -37,6 +45,7 @@
import org.apache.myfaces.application.ApplicationFactoryImpl;
import org.apache.myfaces.custom.date.AbstractHtmlInputDate.UserData;
+import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
import org.apache.myfaces.test.AbstractTomahawkViewControllerTestCase;
import org.apache.myfaces.test.utils.HtmlCheckAttributesUtil;
import org.apache.myfaces.test.utils.HtmlRenderedAttr;
@@ -207,6 +216,240 @@
assertEquals(cal.get(Calendar.YEAR) + "", data.getYear());
}
+ public static class DateTestConverter implements Converter
+ {
+
+ public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String submittedValue)
+ throws ConverterException
+ {
+ HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
+ String type = inputDate.getType();
+ Properties props = new Properties();
+ try
+ {
+ props.load(new StringReader(submittedValue));
+ }catch(IOException e)
+ {
+ }
+ UserData userData = inputDate.getUserData(facesContext.getViewRoot().getLocale());
+ if( ! (type.equals( "time" ) || type.equals( "short_time" )) )
+ {
+ userData.setYear(props.getProperty("year"));
+ userData.setMonth(props.getProperty("month"));
+ userData.setDay(props.getProperty("day"));
+ }
+
+ if( ! type.equals( "date" ) ){
+ userData.setHours(props.getProperty("hours"));
+ userData.setMinutes(props.getProperty("minutes"));
+ if (type.equals("full") || type.equals("time"))
+ {
+ userData.setSeconds(props.getProperty("seconds"));
+ }
+ if (inputDate.isAmpm()) {
+ userData.setAmpm(props.getProperty("ampm"));
+ }
+ }
+ try {
+ return userData.parse();
+ } catch (ParseException e) {
+ Object[] args = {uiComponent.getId()};
+ throw new ConverterException("Error Parsing");
+ }
+ }
+
+ public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object submitValue)
+ throws ConverterException
+ {
+ HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
+ String type = inputDate.getType();
+ UserData value = new UserData((Date) submitValue,
+ facesContext.getViewRoot().getLocale(),
+ inputDate.getTimeZone(), inputDate.isAmpm(), inputDate.getType());
+
+ StringBuffer submittedValue = new StringBuffer();
+ if( ! (type.equals( "time" ) || type.equals( "short_time" )) )
+ {
+ submittedValue.append("year=");
+ submittedValue.append((String) value.getYear() );
+ submittedValue.append("\n");
+
+ submittedValue.append("month=");
+ submittedValue.append((String) value.getMonth());
+ submittedValue.append("\n");
+
+ submittedValue.append("day=");
+ submittedValue.append((String) value.getDay() );
+ submittedValue.append("\n");
+ }
+
+ if( ! type.equals( "date" ) )
+ {
+ submittedValue.append("hours=");
+ submittedValue.append((String) value.getHours() );
+ submittedValue.append("\n");
+
+ submittedValue.append("minutes=");
+ submittedValue.append((String) value.getMinutes() );
+ submittedValue.append("\n");
+
+ if (type.equals("full") || type.equals("time"))
+ {
+ submittedValue.append("seconds=");
+ submittedValue.append((String) value.getSeconds() );
+ submittedValue.append("\n");
+ }
+
+ if (inputDate.isAmpm())
+ {
+ submittedValue.append("ampm=");
+ submittedValue.append((String) value.getAmpm() );
+ submittedValue.append("\n");
+ }
+ }
+ if (submittedValue.charAt(submittedValue.length()-1) == '\n' )
+ {
+ submittedValue.deleteCharAt(submittedValue.length()-1);
+ }
+
+ return submittedValue.toString();
+ }
+
+ }
+
+ public void testDecodeConverterDate() throws Exception {
+ HtmlInputDate inputDate = new HtmlInputDate();
+ inputDate.setId("test");
+ inputDate.setType("date");
+ inputDate.setConverter(new DateTestConverter());
+ HtmlDateRenderer subject = new HtmlDateRenderer();
+ // setup the request map
+ Map map = new HashMap();
+ map.put("test.day", "14");
+ map.put("test.month", "1");
+ map.put("test.year", "2005");
+ FacesContext facesContext = mockupForDecodeCall(map);
+ // decode
+ subject.decode(facesContext, inputDate);
+ //With converter, the submitted value is a String
+ assertTrue(inputDate.getSubmittedValue() instanceof String);
+ // converter
+ inputDate.validate(facesContext);
+
+ UserData data = inputDate.getUserData(Locale.ENGLISH);
+ assertEquals("14", data.getDay());
+ assertEquals("1", data.getMonth());
+ assertEquals("2005", data.getYear());
+ }
+
+ public void testDecodeConverterWithSubmittedValue() throws Exception {
+ HtmlInputDate inputDate = new HtmlInputDate();
+ inputDate.setId("test");
+ inputDate.setType("date");
+ inputDate.setConverter(new DateTestConverter());
+ Date today = new Date();
+ inputDate.setSubmittedValue(new UserData(today, Locale.ENGLISH, null, true, "date"));
+ HtmlDateRenderer subject = new HtmlDateRenderer();
+ // setup the request map
+ Map map = new HashMap();
+ map.put("test.day", "14");
+ map.put("test.month", "1");
+ map.put("test.year", "2005");
+ FacesContext facesContext = mockupForDecodeCall(map);
+ // decode
+ subject.decode(facesContext, inputDate);
+ //With converter, the submitted value is a String
+ assertTrue(inputDate.getSubmittedValue() instanceof String);
+ // converter
+ inputDate.validate(facesContext);
+
+ UserData data = inputDate.getUserData(Locale.ENGLISH);
+ assertEquals("14", data.getDay());
+ assertEquals("1", data.getMonth());
+ assertEquals("2005", data.getYear());
+ }
+
+ public void testDecodeConverterTime() throws Exception {
+ HtmlInputDate inputDate = new HtmlInputDate();
+ inputDate.setId("test");
+ inputDate.setType("time");
+ HtmlDateRenderer subject = new HtmlDateRenderer();
+ // setup the request map
+ Map map = new HashMap();
+ map.put("test.hours", "12");
+ map.put("test.minutes", "15");
+ map.put("test.seconds", "35");
+ FacesContext facesContext = mockupForDecodeCall(map);
+ // decode
+ subject.decode(facesContext, inputDate);
+ //With converter, the submitted value is a String
+ assertTrue(inputDate.getSubmittedValue() instanceof String);
+ // converter
+ inputDate.validate(facesContext);
+
+ UserData data = inputDate.getUserData(Locale.ENGLISH);
+ assertEquals("12", data.getHours());
+ assertEquals("15", data.getMinutes());
+ assertEquals("35", data.getSeconds());
+ }
+
+ public void testDecodeConverterFull() throws Exception {
+ HtmlInputDate inputDate = new HtmlInputDate();
+ inputDate.setId("test");
+ inputDate.setType("full");
+ HtmlDateRenderer subject = new HtmlDateRenderer();
+ // setup the request map
+ Map map = new HashMap();
+ map.put("test.day", "14");
+ map.put("test.month", "1");
+ map.put("test.year", "2005");
+ map.put("test.hours", "12");
+ map.put("test.minutes", "15");
+ map.put("test.seconds", "3");
+ FacesContext facesContext = mockupForDecodeCall(map);
+ // decode
+ subject.decode(facesContext, inputDate);
+ //With converter, the submitted value is a String
+ assertTrue(inputDate.getSubmittedValue() instanceof String);
+ // converter
+ inputDate.validate(facesContext);
+ UserData data = inputDate.getUserData(Locale.ENGLISH);
+ assertEquals("14", data.getDay());
+ assertEquals("1", data.getMonth());
+ assertEquals("2005", data.getYear());
+ assertEquals("12", data.getHours());
+ assertEquals("15", data.getMinutes());
+ assertEquals("03", data.getSeconds());
+ }
+
+ public void testDecodeConverterFlorp() throws Exception {
+ HtmlInputDate inputDate = new HtmlInputDate();
+ inputDate.setId("test");
+ // is this correct? Should it parse correctly if the type is not valid?
+ inputDate.setType("florp");
+ HtmlDateRenderer subject = new HtmlDateRenderer();
+ // setup the request map
+ Map map = new HashMap();
+ map.put("test.day", "14");
+ map.put("test.month", "1");
+ map.put("test.year", "2005");
+ map.put("test.hours", "12");
+ map.put("test.minutes", "15");
+ FacesContext facesContext = mockupForDecodeCall(map);
+ // decode
+ subject.decode(facesContext, inputDate);
+ //With converter, the submitted value is a String
+ assertTrue(inputDate.getSubmittedValue() instanceof String);
+ // converter
+ inputDate.validate(facesContext);
+ UserData data = inputDate.getUserData(Locale.ENGLISH);
+ assertEquals("14", data.getDay());
+ assertEquals("1", data.getMonth());
+ assertEquals("2005", data.getYear());
+ assertEquals("12", data.getHours());
+ assertEquals("15", data.getMinutes());
+ }
+
/*
* Test method for
* 'org.apache.myfaces.custom.date.HtmlDateRenderer.encodeEnd(FacesContext,