(first a small disclaimer: I only read the first two points in your question
)
The text file format you describe is
java.util.Properties
serialization. Below is a “PropertiesItem” class that makes it easy to bind java.util.Properties objects directly into a Vaadin Form like this:
Properties props = new Properties();
props.setProperty("Name", "John Doe");
props.setProperty("Age(int)", "39");
props.setProperty("DOA(boolean)", "false");
props.setProperty("Arrived(date)", "");
props.setProperty("Notes", "");
item = new PropertiesItem(props);
f = new Form();
f.setItemDataSource(item);
mainWindow.addComponent(f);
Attached also a screenshot of the Form generated based on this.
package com.example.tester;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Properties;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
/**
* This class implements Vaadin Item interface using java.util.Properties as
* backend /storage.
*
* @see java.util.Properties
* @author Sami Ekblad
*/
public class PropertiesItem implements Item {
private static final long serialVersionUID = 1L;
public static final String TYPE_SUFFIX_DEFAULT = "";
public static final String TYPE_SUFFIX_STRING = "(string)";
public static final String TYPE_SUFFIX_INT = "(int)";
public static final String TYPE_SUFFIX_BOOLEAN = "(boolean)";
public static final String TYPE_SUFFIX_DATE = "(date)";
/**
* Parse the type suffix from property name.
*
* @param type
* @return Object
*/
public static String parseToTypeSuffix(String suffix) {
if (suffix == null) {
return TYPE_SUFFIX_DEFAULT;
}
if (suffix.endsWith(TYPE_SUFFIX_STRING)) {
return TYPE_SUFFIX_STRING;
}
if (suffix.endsWith(TYPE_SUFFIX_DATE)) {
return TYPE_SUFFIX_DATE;
}
if (suffix.endsWith(TYPE_SUFFIX_INT)) {
return TYPE_SUFFIX_INT;
}
if (suffix.endsWith(TYPE_SUFFIX_BOOLEAN)) {
return TYPE_SUFFIX_BOOLEAN;
}
return TYPE_SUFFIX_DEFAULT;
}
/**
* Convert string suffix to Java class type. Method suffixToType.
*
* @param type
* @return Class
*/
public static Class suffixToType(String suffix) {
suffix = parseToTypeSuffix(suffix);
if (suffix.endsWith(TYPE_SUFFIX_STRING)) {
return String.class;
}
if (suffix.endsWith(TYPE_SUFFIX_DATE)) {
return Date.class;
}
if (suffix.endsWith(TYPE_SUFFIX_INT)) {
return Integer.class;
}
if (suffix.endsWith(TYPE_SUFFIX_BOOLEAN)) {
return Boolean.class;
}
// Default to string type
return String.class;
}
/**
* Convert the Java type string suffix. Method suffixToType.
*
* @param type
* @return Class
*/
public static String typeToSuffix(Class type) {
if (type.equals(Date.class)) {
return TYPE_SUFFIX_DATE;
}
if (type.equals(Integer.class)) {
return TYPE_SUFFIX_INT;
}
if (type.equals(Boolean.class)) {
return TYPE_SUFFIX_BOOLEAN;
}
return TYPE_SUFFIX_DEFAULT;
}
private File file;
private Properties values = new Properties();
private HashMap typedProperties = new LinkedHashMap();
private Method getStringMethod = null;
private Method setStringMethod = null;
private Comparator propertyOrder;
public PropertiesItem() {
this(new Properties());
}
public PropertiesItem(File propertiesFile) {
this();
setFile(propertiesFile);
}
public PropertiesItem(Properties defaults, Comparator propertyOrder) {
this(defaults);
this.propertyOrder = propertyOrder;
}
public PropertiesItem(Properties defaults) {
// Initlize methods
Class c = Properties.class;
try {
getStringMethod = c.getDeclaredMethod("getProperty",
new Class[] { String.class });
setStringMethod = c.getDeclaredMethod("setProperty", new Class[] {
String.class, String.class });
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
setProperties(defaults);
}
/** Set the properties storage */
protected void setProperties(Properties defaults) {
// Remove all
removeAllProperties();
// Create default properties as specified types
if (defaults != null) {
List propIds = new ArrayList(defaults.keySet());
for (Iterator i = propIds.iterator(); i.hasNext();) {
String id = (String) i.next();
addItemPropertyByName(id).setValue(defaults.get(id));
}
}
}
/**
* Remove all properties.
*/
public void removeAllProperties() {
values.clear();
typedProperties.clear();
}
/**
* @see com.vaadin.data.Item#getItemProperty(java.lang.Object)
*/
public Property getItemProperty(Object id) {
return (Property) typedProperties.get(id);
}
/**
* @see com.vaadin.data.Item#getItemPropertyIds()
*/
public Collection getItemPropertyIds() {
List l = new ArrayList(typedProperties.keySet());
if (propertyOrder != null) {
// Use specified order
Collections.sort(l, this.propertyOrder);
} else {
// Alphabetical order
Collections.sort(l);
}
return l;
}
/**
* @see com.vaadin.data.Item#addItemProperty(java.lang.Object,
* com.vaadin.data.Property)
*/
public boolean addItemProperty(Object id, Property property)
throws UnsupportedOperationException {
Class clazz = property.getType();
String type = typeToSuffix(clazz);
// Create and add the new property
Property p = new PropertiesProperty(clazz, id.toString() + type, values);
typedProperties.put(id, p);
// Copy the value
p.setValue(property.getValue());
return true;
}
/**
* @see com.vaadin.data.Item#removeItemProperty(java.lang.Object)
*/
public boolean removeItemProperty(Object arg0)
throws UnsupportedOperationException {
return typedProperties.remove(arg0) != null;
}
/** Add item property of given id. Parses the type from id. */
protected Property addItemPropertyByName(String id) {
String type = parseToTypeSuffix(id);
String name = id.substring(0, id.length() - type.length());
Class clazz = suffixToType(type);
Property p = new PropertiesProperty(clazz, id, values);
typedProperties.put(name, p);
return p;
}
public void setType(Object id, Class newType) {
PropertiesProperty p = (PropertiesProperty) getItemProperty(id);
if (p != null) {
p.setType(newType);
}
}
public class PropertiesProperty implements Property {
private Class type = String.class;
private Properties store;
private boolean readOnly = false;
private String key;
private Constructor constructor = null;
private SimpleDateFormat df;
private PropertiesProperty(Class type, String key, Properties store) {
this.key = key;
this.store = store;
setType(type);
if (type.equals(Date.class)) {
df = new SimpleDateFormat();
}
}
/**
* @see com.vaadin.data.Property#getValue()
*/
public Object getValue() {
try {
if (type.equals(Date.class)) {
String val = store.getProperty(key);
if (val != null)
return df.parse(val);
} else {
return constructor.newInstance(new Object[] { store
.getProperty(key) });
}
} catch (Exception e) {
try {
return type.newInstance();
} catch (Exception ex) {
// Ignore
}
}
return null;
}
/**
* @see com.vaadin.data.Property#setValue(java.lang.Object)
*/
public void setValue(Object newValue) throws ReadOnlyException,
ConversionException {
if (newValue == null)
store.setProperty(key, "");
else {
if (newValue instanceof Date && type.equals(Date.class)) {
store.setProperty(key, df.format(newValue));
} else {
store.setProperty(key, newValue.toString());
}
}
}
/**
* @see com.vaadin.data.Property#getType()
*/
public Class getType() {
return type;
}
public void setType(Class newType) {
this.type = newType;
try {
constructor = type.getConstructor(new Class[] { String.class });
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
"Unsupported type in PropertiesItem property '"
+ this.key + "':" + newType);
}
}
/**
* @see com.vaadin.data.Property#isReadOnly()
*/
public boolean isReadOnly() {
return this.readOnly;
}
/**
* @see com.vaadin.data.Property#setReadOnly(boolean)
*/
public void setReadOnly(boolean newStatus) {
this.readOnly = newStatus;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
return "" + getValue();
}
}
/**
* Returns the file.
*
* @return File
*/
public File getFile() {
return file;
}
/**
* Sets the storage file.
*
* @param file
* The file to set
*/
public void setFile(File file) {
this.file = file;
if (file != null) {
Properties defaults = new Properties();
try {
defaults.load(new FileInputStream(file));
setProperties(defaults);
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
}
public void save() {
if (file == null)
return;
try {
if (!this.file.exists())
this.file.createNewFile();
values.store(new FileOutputStream(this.file), "PropertiesItem");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Get the properties values.
*
* @return Properies.
*/
public Properties getProperties() {
return values;
}
}
(For easier copy pasting the above code use:
http://uilder.virtuallypreinstalled.com/run/codecopy/
)
As you can see there is built-in typing for the properties using the type suffix in parentheses. Use it if you like - the default is String. Also for convenience there is setFile together with save function to persist the data.
