001: package org.andromda.cartridges.jsf.converters;
002:
003: import java.text.DateFormat;
004: import java.text.SimpleDateFormat;
005: import java.util.Calendar;
006: import java.util.Date;
007: import java.util.TimeZone;
008:
009: import javax.faces.component.UIComponent;
010: import javax.faces.context.FacesContext;
011: import javax.faces.convert.ConverterException;
012: import javax.faces.el.ValueBinding;
013:
014: import org.apache.myfaces.custom.calendar.HtmlCalendarRenderer.DateConverter;
015:
016: /**
017: * Overrides the default DateTimeConverter to include conversion of Calendar
018: * instances as well as Date instances.
019: *
020: * <p>
021: * Unfortunately because of poor design in myfaces's calendar component, we have to implement
022: * DateConverter so that we can correctly convert to a date in the inputCalendar implementation.
023: * </p>
024: *
025: * @author Chad Brandon
026: */
027: public class DateTimeConverter extends
028: javax.faces.convert.DateTimeConverter implements DateConverter {
029: /**
030: * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
031: */
032: public String getAsString(FacesContext context,
033: UIComponent component, Object value)
034: throws ConverterException {
035: if (value instanceof Calendar) {
036: value = ((Calendar) value).getTime();
037: }
038: final String pattern = this .getPattern();
039: String result = null;
040: if (value != null && pattern != null
041: && pattern.trim().length() > 0) {
042: DateFormat format = new SimpleDateFormat(pattern);
043: format.setTimeZone(this .getTimeZone());
044: result = format.format((Date) value);
045: }
046: return result;
047: }
048:
049: /**
050: * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
051: */
052: public Object getAsObject(FacesContext context,
053: UIComponent component, String value)
054: throws ConverterException {
055: Object asObject = null;
056: final Class componentType = this .getComponentType(context,
057: component);
058: if (componentType != null) {
059: asObject = super .getAsObject(context, component, value);
060: if (Calendar.class.isAssignableFrom(componentType)
061: && asObject instanceof Date) {
062: final Calendar calendar = Calendar.getInstance();
063: calendar.setTimeZone(this .getTimeZone());
064: calendar.setTime((Date) asObject);
065: asObject = calendar;
066: }
067: }
068: return asObject;
069: }
070:
071: /**
072: * Gets the component type for the given <code>component</code>.
073: * @param context the current faces context.
074: * @param component the component from which to retrieve the type.
075: * @return true/false
076: */
077: private Class getComponentType(final FacesContext context,
078: final UIComponent component) {
079: Class type = null;
080: final ValueBinding binding = component.getValueBinding("value");
081: if (binding != null) {
082: type = binding.getType(context);
083: }
084: return type;
085: }
086:
087: /**
088: * Gets the component Value for the given <code>component</code>.
089: * @param context the current faces context.
090: * @param component the component from which to retrieve the value.
091: * @return true/false
092: */
093: private Object getComponentValue(final FacesContext context,
094: final UIComponent component) {
095: Object value = null;
096: final ValueBinding binding = component.getValueBinding("value");
097: if (binding != null) {
098: value = binding.getValue(context);
099: }
100: return value;
101: }
102:
103: private TimeZone timeZone;
104:
105: /**
106: * @see #getTimeZone()
107: * @see javax.faces.convert.DateTimeConverter#restoreState(javax.faces.context.FacesContext, java.lang.Object)
108: */
109: public void restoreState(FacesContext facesContext, Object state) {
110: super .restoreState(facesContext, state);
111: Object values[] = (Object[]) state;
112: this .timeZone = (TimeZone) values[4];
113: }
114:
115: /**
116: * @see #getTimeZone()
117: * @see javax.faces.convert.DateTimeConverter#saveState(javax.faces.context.FacesContext)
118: */
119: public Object saveState(FacesContext facesContext) {
120: Object values[] = (Object[]) super .saveState(facesContext);
121: values[4] = this .timeZone;
122: return values;
123: }
124:
125: /**
126: * @see #getTimeZone()
127: * @see javax.faces.convert.DateTimeConverter#setTimeZone(java.util.TimeZone)
128: */
129: public void setTimeZone(TimeZone timeZone) {
130: this .timeZone = timeZone;
131: }
132:
133: /**
134: * Overridden because the default timeZone is set as GMT, whereas it should be the default
135: * for the operating system (at least in my opinion).
136: *
137: * @see javax.faces.convert.DateTimeConverter#getTimeZone()
138: */
139: public TimeZone getTimeZone() {
140: return this .timeZone == null ? TimeZone.getDefault()
141: : this .timeZone;
142: }
143:
144: public static final String CONVERTER_ID = "andromda.faces.DateTime";
145:
146: /**
147: * @see org.apache.myfaces.custom.calendar.HtmlCalendarRenderer.DateConverter#getAsDate(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
148: */
149: public Date getAsDate(FacesContext context, UIComponent component) {
150: Object value = this .getComponentValue(context, component);
151: if (value instanceof Calendar) {
152: value = ((Calendar) value).getTime();
153: }
154: return (Date) value;
155: }
156: }
|