How do I use a DateField with a Joda DateTime property?
The domain model of the project I’m planning to implement uses Joda DateTime classes instead of java.util.Date, so I’d like to bind the Vaadin DateField class to these Joda DateTime classes.
I can create a supplementary property on the model objects that does the conversion but I’m looking for a more elegant and scalable solution so that I don’t need to modify all of the model objects.
[code]
public DateTime getBirthDate() {
return birthDate;
}
public void setBirthDate(DateTime birthDate) {
this.birthDate = birthDate;
}
public Date getBirthDateAsDate() {
return this.birthDate.toDate();
}
public void setBirthDateAsDate(Date date) {
this.birthDate = new DateTime(date);
}
I have a better solution now. In this approach I’ve created a Property object to convert between the DateTime data type and the Date data type.
Which works, but you also need to subclass the DateField class and override the setPropertyDataSource() method because in DateField this method does a check to see if the property has the right type or not. So in my subclass ZDateField I wrap the original Date property with the new ZDateTimeProperty that performs the conversion.
Richard.
package my.example.ui.framework;
import com.vaadin.data.Property;
import org.joda.time.DateTime;
import java.util.Date;
/**
*/
public class ZDateTimeProperty implements Property {
private Property sourceProperty;
public ZDateTimeProperty(Property sourceProperty) {
this.sourceProperty = sourceProperty;
if(!sourceProperty.getType().equals(DateTime.class)) {
throw new RuntimeException("Source property a not a DateTime, but is a " + sourceProperty.getType().getName());
}
}
@Override
public Object getValue() {
DateTime sourceDate = (DateTime)sourceProperty.getValue();
Object result = null;
if(sourceDate != null) {
result = sourceDate.toDate();
}
return result;
}
@Override
public void setValue(Object o) throws ReadOnlyException, ConversionException {
DateTime value = null;
if(o != null) {
if(o instanceof Date) {
Date date = (Date)o;
value = new DateTime(date);
}
else {
throw new RuntimeException("Value supplied was not a Date.class");
}
}
sourceProperty.setValue(value);
}
@Override
public Class<?> getType() {
return Date.class;
}
@Override
public boolean isReadOnly() {
return sourceProperty.isReadOnly();
}
@Override
public void setReadOnly(boolean b) {
sourceProperty.setReadOnly(b);
}
}
package my.example.ui.framework;
import com.vaadin.data.Property;
import com.vaadin.ui.DateField;
import org.joda.time.DateTime;
import java.util.Date;
/**
*/
public class ZDateField extends DateField {
public ZDateField() {
}
public ZDateField(String caption) {
super(caption);
}
public ZDateField(String caption, Property dataSource) {
super(caption, dataSource);
}
public ZDateField(Property dataSource) throws IllegalArgumentException {
super(dataSource);
}
public ZDateField(String caption, Date value) {
super(caption, value);
}
@Override
public void setPropertyDataSource(Property newDataSource) {
if(newDataSource.getType().equals(DateTime.class)) {
[b]
super.setPropertyDataSource(new ZDateTimeProperty(newDataSource));
[/b]
}
else {
super.setPropertyDataSource(newDataSource);
}
}
}
Thank you for the idea on how to use Joda-time with Vaadin.
Remember that you have to implement Property.ValueChangeNotifier in your ZDateField to get the correct communication with the DateField, otherwise updates on the property-wrapper will not be reflected back to the DateField.
in ZDateField:
@Override
public void addListener(ValueChangeListener listener) {
if (sourceProperty instanceof Property.ValueChangeNotifier) {
((Property.ValueChangeNotifier) sourceProperty).addListener(listener);
}
}
@Override
public void removeListener(ValueChangeListener listener) {
if (sourceProperty instanceof Property.ValueChangeNotifier) {
((Property.ValueChangeNotifier) sourceProperty).removeListener(listener);
}
}
Hello, I would like to use the ZDateField component, but can you explain how we can add this modification as, I don’t know how to retreive the reference to sourceProperty in the ZDateField class.