diff options
16 files changed, 781 insertions, 117 deletions
diff --git a/client-compiler/ivy.xml b/client-compiler/ivy.xml index ee36e4e261..04b5feb45e 100644 --- a/client-compiler/ivy.xml +++ b/client-compiler/ivy.xml @@ -1,57 +1,62 @@ <?xml version="1.0" encoding="UTF-8"?> <ivy-module version="2.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd" - xmlns:m="http://ant.apache.org/ivy/maven"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd" + xmlns:m="http://ant.apache.org/ivy/maven"> - <info organisation="com.vaadin" module="vaadin-client-compiler" - revision="${vaadin.version}" /> + <info organisation="com.vaadin" module="vaadin-client-compiler" + revision="${vaadin.version}" /> - <configurations> - <conf name="build" /> - <conf name="build-provided" /> - <conf name="ide" visibility="private" /> - </configurations> - <publications> - <artifact type="jar" ext="jar" /> - <artifact type="source" ext="jar" m:classifier="sources" /> - <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> - <artifact type="pom" ext="pom" /> - </publications> - <dependencies> - <dependency org="com.vaadin" name="vaadin-shared" - rev="${vaadin.version}" conf="build" /> - <dependency org="com.vaadin" name="vaadin-server" - rev="${vaadin.version}" conf="build" /> - <dependency org="com.vaadin" name="vaadin-client" - rev="${vaadin.version}" conf="build" /> + <configurations> + <conf name="build" /> + <conf name="build-provided" /> + <conf name="ide" visibility="private" /> + </configurations> + <publications> + <artifact type="jar" ext="jar" /> + <artifact type="source" ext="jar" m:classifier="sources" /> + <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> + <artifact type="pom" ext="pom" /> + </publications> + <dependencies> + <dependency org="com.vaadin" name="vaadin-shared" rev="${vaadin.version}" + conf="build" /> + <dependency org="com.vaadin" name="vaadin-server" rev="${vaadin.version}" + conf="build" /> + <dependency org="com.vaadin" name="vaadin-client" rev="${vaadin.version}" + conf="build" /> <dependency org="com.vaadin" name="vaadin-theme-compiler" rev="${vaadin.version}" conf="build" /> - - <dependency org="commons-collections" name="commons-collections" - rev="3.1" conf="build,ide -> default" /> - <dependency org="ant" name="ant" rev="1.6.5" - conf="build,ide -> default" /> - <dependency org="net.sourceforge.cssparser" name="cssparser" - rev="0.9.5" conf="build,ide -> default" /> - <dependency org="ant" name="ant" rev="1.6.5" - conf="build,ide -> default" /> - <dependency org="ant" name="ant-launcher" rev="1.6.5" - conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty" rev="6.1.11" - conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty-util" - rev="6.1.11" conf="build,ide -> default" /> - <dependency org="org.jdesktop" name="swing-worker" - rev="1.1" conf="build,ide -> default" /> - <dependency org="commons-codec" name="commons-codec" - rev="1.3" conf="build,ide -> default" /> - <dependency org="commons-io" name="commons-io" rev="1.4" - conf="build,ide -> default" /> - <dependency org="commons-lang" name="commons-lang" - rev="2.6" conf="build,ide -> default" /> - <dependency org="org.apache.james" name="apache-mime4j" - rev="0.6" conf="build,ide -> default" /> - </dependencies> + + <dependency org="commons-collections" name="commons-collections" + rev="3.1" conf="build,ide -> default" /> + <dependency org="commons-logging" name="commons-logging" + rev="1.1.1" conf="build,ide -> default" /> + + <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> + <dependency org="net.sourceforge.cssparser" name="cssparser" + rev="0.9.5" conf="build,ide -> default" /> + <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> + <dependency org="ant" name="ant-launcher" rev="1.6.5" + conf="build,ide -> default" /> + <dependency org="org.mortbay.jetty" name="jetty" rev="6.1.11" + conf="build,ide -> default" /> + <dependency org="org.mortbay.jetty" name="jetty-util" rev="6.1.11" + conf="build,ide -> default" /> + <dependency org="org.jdesktop" name="swing-worker" rev="1.1" + conf="build,ide -> default" /> + <dependency org="commons-codec" name="commons-codec" rev="1.3" + conf="build,ide -> default" /> + <dependency org="commons-io" name="commons-io" rev="1.4" + conf="build,ide -> default" /> + <dependency org="commons-lang" name="commons-lang" rev="2.6" + conf="build,ide -> default" /> + <dependency org="org.apache.james" name="apache-mime4j" + rev="0.6" conf="build,ide -> default" /> + + <dependency org="com.vaadin" name="vaadin-client-compiler-deps" + rev="0.9.0" conf="build,ide -> default" /> + + </dependencies> </ivy-module> diff --git a/client/src/com/vaadin/client/ui/VLabel.java b/client/src/com/vaadin/client/ui/VLabel.java index 83fc8e207e..8acd653778 100644 --- a/client/src/com/vaadin/client/ui/VLabel.java +++ b/client/src/com/vaadin/client/ui/VLabel.java @@ -16,7 +16,6 @@ package com.vaadin.client.ui; -import com.google.gwt.dom.client.Style.Display; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.ApplicationConnection; @@ -57,10 +56,8 @@ public class VLabel extends HTML { super.setWidth(width); if (width == null || width.equals("")) { setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, true); - getElement().getStyle().setDisplay(Display.INLINE_BLOCK); } else { setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, false); - getElement().getStyle().clearDisplay(); } } diff --git a/gwt-files.xml b/gwt-files.xml index 69e6c04e70..33aba795ef 100644 --- a/gwt-files.xml +++ b/gwt-files.xml @@ -57,17 +57,62 @@ <!-- cssparser --> <exclude name="com/steadystate/css/**" /> <!-- Ant & AntLauncher --> - <exclude name="org/apache/tools/**"/> + <exclude name="org/apache/tools/**" /> <!-- Jetty & jetty-util --> - <exclude name="org/mortbay/**"/> + <exclude name="org/mortbay/**" /> <!-- Swing Worker--> - <exclude name="org/jdesktop/swingworker/**"/> - <!-- Apache commons codec & io & lang --> - <exclude name="org/apache/commons/codec/**"/> - <exclude name="org/apache/commons/io/**"/> - <exclude name="org/apache/commons/lang/**"/> + <exclude name="org/jdesktop/swingworker/**" /> + <!-- Apache commons codec & io & lang & collections & logging --> + <exclude name="org/apache/commons/codec/**" /> + <exclude name="org/apache/commons/io/**" /> + <exclude name="org/apache/commons/lang/**" /> + <exclude name="org/apache/commons/collections/**" /> + <exclude name="org/apache/commons/logging/**" /> <!-- apache mime4j --> - <exclude name="org/apache/james/mime4j/**"/> + <exclude name="org/apache/james/mime4j/**" /> + + <!-- client-compiler-deps --> + <exclude name="com/gargoylesoftware/" /> + <exclude name="com/google/common/" /> + <exclude name="com/google/debugging/" /> + <exclude name="com/google/gwt/dev/protobuf/" /> + <exclude name="com/google/gwt/thirdparty/debugging/" /> + <exclude name="com/google/gwt/thirdparty/javascript/" /> + <exclude name="com/google/gwt/thirdparty/mozilla/" /> + <exclude name="com/ibm/" /> + <exclude name="externs.zip" /> + <exclude name="java_cup/" /> + <exclude name="javax/annotation/" /> + <exclude name="net/sourceforge/htmlunit/" /> + <exclude name="org/apache/bcel/" /> + <exclude name="org/apache/html/" /> + <exclude name="org/apache/http/" /> + <exclude name="org/apache/NOTICE" /> + <exclude name="org/apache/regexp/" /> + <exclude name="org/apache/tapestry/" /> + <exclude name="org/apache/wml/" /> + <exclude name="org/apache/xalan/" /> + <exclude name="org/apache/xerces/" /> + <exclude name="org/apache/xml/" /> + <exclude name="org/apache/xmlcommons/" /> + <exclude name="org/apache/xpath/" /> + <exclude name="org/cyberneko/" /> + <exclude name="org/eclipse/" /> + <exclude name="org/kohsuke/" /> + <exclude name="org/w3c/" /> + <exclude name="org/xml/" /> + <exclude name="rhino_ast/" /> + <exclude name="rhinoDiff.txt" /> + <exclude name="trax/" /> + <exclude name="unicode-license.txt" /> + <exclude name="org/json" /> + + <exclude name="license/NOTICE" /> + <exclude name="license/LICENSE.dom-documentation.txt" /> + <exclude name="license/LICENSE.dom-software.txt" /> + <exclude name="license/LICENSE" /> + <exclude name="license/README.dom.txt" /> + <exclude name="license/README.sax.txt" /> <!-- Overridden in Vaadin --> <exclude name="com/google/gwt/dev/About.properties" /> @@ -105,7 +150,7 @@ <exclude name="com/google/gwt/*/shared/**" /> <exclude name="com/google/gwt/*/*/shared/**" /> <exclude name="com/google/web/bindery/*/shared/**" /> - + <!-- Used by the server, in wrong package in GWT --> <exclude name="com/google/gwt/user/client/rpc/IsSerializable.*" /> diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java index 7e44c26c9e..55bd3a4641 100644 --- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -58,6 +58,23 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + @Override + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + Item dataSource = getItemDataSource(); + if (dataSource != null && dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + try { + return getFieldName(beanType, minifiedFieldName); + } catch (SecurityException e) { + } catch (NoSuchFieldException e) { + } + } + return null; + } + private static java.lang.reflect.Field getField(Class<?> cls, String propertyId) throws SecurityException, NoSuchFieldException { if (propertyId.contains(".")) { @@ -75,7 +92,7 @@ public class BeanFieldGroup<T> extends FieldGroup { } catch (NoSuchFieldError e) { // Try super classes until we reach Object Class<?> superClass = cls.getSuperclass(); - if (superClass != Object.class) { + if (superClass != null && superClass != Object.class) { return getField(superClass, propertyId); } else { throw e; @@ -84,6 +101,22 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + private static String getFieldName(Class<?> cls, String propertyId) + throws SecurityException, NoSuchFieldException { + for (java.lang.reflect.Field field1 : cls.getDeclaredFields()) { + if (propertyId.equals(minifyFieldName(field1.getName()))) { + return field1.getName(); + } + } + // Try super classes until we reach Object + Class<?> superClass = cls.getSuperclass(); + if (superClass != null && superClass != Object.class) { + return getFieldName(superClass, propertyId); + } else { + throw new NoSuchFieldException(); + } + } + /** * Helper method for setting the data source directly using a bean. This * method wraps the bean in a {@link BeanItem} and calls @@ -166,4 +199,4 @@ public class BeanFieldGroup<T> extends FieldGroup { } return beanValidationImplementationAvailable; } -}
\ No newline at end of file +} diff --git a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java index 9ced6588f5..ff6b1d3aee 100644 --- a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java +++ b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java @@ -15,18 +15,23 @@ */ package com.vaadin.data.fieldgroup; +import java.util.Date; import java.util.EnumSet; import com.vaadin.data.Item; import com.vaadin.data.fieldgroup.FieldGroup.BindException; +import com.vaadin.ui.AbstractField; import com.vaadin.ui.AbstractSelect; import com.vaadin.ui.AbstractTextField; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; +import com.vaadin.ui.DateField; import com.vaadin.ui.Field; +import com.vaadin.ui.InlineDateField; import com.vaadin.ui.ListSelect; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.OptionGroup; +import com.vaadin.ui.PopupDateField; import com.vaadin.ui.RichTextArea; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; @@ -39,6 +44,8 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { public <T extends Field> T createField(Class<?> type, Class<T> fieldType) { if (Enum.class.isAssignableFrom(type)) { return createEnumField(type, fieldType); + } else if (Date.class.isAssignableFrom(type)) { + return createDateField(type, fieldType); } else if (Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) { return createBooleanField(fieldType); @@ -70,6 +77,24 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { return null; } + private <T extends Field> T createDateField(Class<?> type, + Class<T> fieldType) { + AbstractField field; + + if (InlineDateField.class.isAssignableFrom(fieldType)) { + field = new InlineDateField(); + } else if (DateField.class.isAssignableFrom(fieldType)) { + field = new PopupDateField(); + } else if (AbstractTextField.class.isAssignableFrom(fieldType)) { + field = createAbstractTextField((Class<? extends AbstractTextField>) fieldType); + } else { + return null; + } + + field.setImmediate(true); + return (T) field; + } + protected AbstractSelect createCompatibleSelect( Class<? extends AbstractSelect> fieldType) { AbstractSelect select; diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index dc1fdbb78d..6c515dbdee 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -733,11 +733,12 @@ public class FieldGroup implements Serializable { * that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory. All non-null fields for which a property id can - * be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory. All non-null fields for which a property id can be + * determined are bound to the property id. * </p> * <p> * For example: @@ -777,11 +778,12 @@ public class FieldGroup implements Serializable { * member fields that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory is buildFields is true. All non-null fields for - * which a property id can be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory is buildFields is true. All non-null fields for which a + * property id can be determined are bound to the property id. * </p> * * @param objectWithMemberFields @@ -812,7 +814,16 @@ public class FieldGroup implements Serializable { // @PropertyId(propertyId) always overrides property id propertyId = propertyIdAnnotation.value(); } else { - propertyId = memberField.getName(); + try { + propertyId = findPropertyId(memberField); + } catch (SearchException e) { + // Property id was not found, skip this field + continue; + } + if (propertyId == null) { + // Property id was not found, skip this field + continue; + } } // Ensure that the property id exists @@ -873,6 +884,54 @@ public class FieldGroup implements Serializable { } } + /** + * Searches for a property id from the current itemDataSource that matches + * the given memberField. + * <p> + * If perfect match is not found, uses a case insensitive search that also + * ignores underscores. Returns null if no match is found. Throws a + * SearchException if no item data source has been set. + * </p> + * <p> + * The propertyId search logic used by + * {@link #buildAndBindMemberFields(Object, boolean) + * buildAndBindMemberFields} can easily be customized by overriding this + * method. No other changes are needed. + * </p> + * + * @param memberField + * The field an object id is searched for + * @return + */ + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + if (getItemDataSource() == null) { + throw new SearchException( + "Property id type for field '" + + fieldName + + "' could not be determined. No item data source has been set."); + } + Item dataSource = getItemDataSource(); + if (dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + for (Object itemPropertyId : dataSource.getItemPropertyIds()) { + if (itemPropertyId instanceof String) { + String itemPropertyName = (String) itemPropertyId; + if (minifiedFieldName.equals(minifyFieldName(itemPropertyName))) { + return itemPropertyName; + } + } + } + } + return null; + } + + protected static String minifyFieldName(String fieldName) { + return fieldName.toLowerCase().replace("_", ""); + } + public static class CommitException extends Exception { public CommitException() { @@ -909,6 +968,18 @@ public class FieldGroup implements Serializable { } + public static class SearchException extends RuntimeException { + + public SearchException(String message) { + super(message); + } + + public SearchException(String message, Throwable t) { + super(message, t); + } + + } + /** * Builds a field and binds it to the given property id using the field * binder. diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java index e59ea7fd5e..8c1e7af0fa 100644 --- a/server/src/com/vaadin/server/VaadinPortletService.java +++ b/server/src/com/vaadin/server/VaadinPortletService.java @@ -46,7 +46,12 @@ public class VaadinPortletService extends VaadinService { } } - protected VaadinPortlet getPortlet() { + /** + * Retrieves a reference to the portlet associated with this service. + * + * @return A reference to the VaadinPortlet this service is using + */ + public VaadinPortlet getPortlet() { return portlet; } diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java index 71f47ea217..7120e3a5c5 100644 --- a/server/src/com/vaadin/server/VaadinServletService.java +++ b/server/src/com/vaadin/server/VaadinServletService.java @@ -44,7 +44,12 @@ public class VaadinServletService extends VaadinService { } } - protected VaadinServlet getServlet() { + /** + * Retrieves a reference to the servlet associated with this service. + * + * @return A reference to the VaadinServlet this service is using + */ + public VaadinServlet getServlet() { return servlet; } diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 422e0a1796..619d717d97 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -373,30 +373,6 @@ public abstract class AbstractField<T> extends AbstractComponent implements /* Property interface implementation */ /** - * Returns the (field) value converted to a String using toString(). - * - * @see java.lang.Object#toString() - * @deprecated As of 7.0, use {@link #getValue()} to get the value of the - * field, {@link #getConvertedValue()} to get the field value - * converted to the data model type or - * {@link #getPropertyDataSource()} .getValue() to get the value - * of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using AbstractField.toString() to get the value for a " - + getClass().getSimpleName() - + ". This will not be supported starting from Vaadin 7.1 " - + "(your debugger might call toString() and cause this message to appear)."); - final Object value = getFieldValue(); - if (value == null) { - return null; - } - return value.toString(); - } - - /** * Gets the current value of the field. * * <p> diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java index f49a1403cf..f413ea47f2 100644 --- a/server/src/com/vaadin/ui/Label.java +++ b/server/src/com/vaadin/ui/Label.java @@ -203,23 +203,6 @@ public class Label extends AbstractComponent implements Property<String>, } /** - * Returns the value displayed by this label. - * - * @see java.lang.Object#toString() - * @deprecated As of 7.0, use {@link #getValue()} to get the value of the - * label or {@link #getPropertyDataSource()} .getValue() to get - * the value of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using Label.toString() to get the value for a " - + getClass().getSimpleName() - + ". This will not be supported starting from Vaadin 7.1 (your debugger might call toString() and cause this message to appear)."); - return getValue(); - } - - /** * Gets the type of the Property. * * @see com.vaadin.data.Property#getType() diff --git a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java new file mode 100644 index 0000000000..3f4368c295 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBinding.java @@ -0,0 +1,84 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextField; + +public class CaseInsensitiveBinding { + + @Test + public void caseInsensitivityAndUnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("LastName", new ObjectProperty<String>("Sparrow")); + + class MyForm extends FormLayout { + TextField lastName = new TextField("Last name"); + + public MyForm() { + + // Should bind to the LastName property + addComponent(lastName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Sparrow".equals(form.lastName.getValue())); + } + + @Test + public void UnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", new ObjectProperty<String>("Jack")); + + class MyForm extends FormLayout { + TextField firstName = new TextField("First name"); + + public MyForm() { + // Should bind to the first_name property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Jack".equals(form.firstName.getValue())); + } + + @Test + public void perfectMatchPriority() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", new ObjectProperty<String>( + "Not this")); + item.addItemProperty("firstName", new ObjectProperty<String>("This")); + + class MyForm extends FormLayout { + TextField firstName = new TextField("First name"); + + public MyForm() { + // should bind to the firstName property, not first_name property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("This".equals(form.firstName.getValue())); + } + +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/fieldgroup/DateForm.html b/uitest/src/com/vaadin/tests/fieldgroup/DateForm.html new file mode 100644 index 0000000000..f141091805 --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/DateForm.html @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.fieldgroup.DateForm?restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestsfieldgroupDateForm::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VPopupCalendar[0]#field</td> + <td>1/20/84</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestsfieldgroupDateForm::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VPopupCalendar[0]#field</td> + <td>1/20/84</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestsfieldgroupDateForm::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VDateFieldCalendar[0]/VCalendarPanel[0]#day20</td> + <td>v-inline-datefield-calendarpanel-day-selected</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestsfieldgroupDateForm::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VTextField[0]</td> + <td>Jan 20, 1984 4:34:49 PM</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/fieldgroup/DateForm.java b/uitest/src/com/vaadin/tests/fieldgroup/DateForm.java new file mode 100644 index 0000000000..0d906a086b --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/DateForm.java @@ -0,0 +1,150 @@ +package com.vaadin.tests.fieldgroup; + +import java.util.Date; + +import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.data.util.BeanItem; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.DateField; +import com.vaadin.ui.InlineDateField; +import com.vaadin.ui.Notification; +import com.vaadin.ui.PopupDateField; +import com.vaadin.ui.TextField; + +public class DateForm extends TestBase { + + private Log log = new Log(5); + @PropertyId("date1") + private DateField dateField; + @PropertyId("date2") + private PopupDateField popupDateField; + @PropertyId("date3") + private InlineDateField inlineDateField; + @PropertyId("date4") + private TextField textField; + + public static class DateObject { + private Date date1, date2, date3, date4; + + public DateObject(Date date1, Date date2, Date date3, Date date4) { + super(); + this.date1 = date1; + this.date2 = date2; + this.date3 = date3; + this.date4 = date4; + } + + public Date getDate1() { + return date1; + } + + public void setDate1(Date date1) { + this.date1 = date1; + } + + public Date getDate2() { + return date2; + } + + public void setDate2(Date date2) { + this.date2 = date2; + } + + public Date getDate3() { + return date3; + } + + public void setDate3(Date date3) { + this.date3 = date3; + } + + public Date getDate4() { + return date4; + } + + public void setDate4(Date date4) { + this.date4 = date4; + } + + } + + @Override + protected void setup() { + addComponent(log); + final FieldGroup fieldGroup = new BeanFieldGroup<DateObject>( + DateObject.class); + fieldGroup.setBuffered(true); + + fieldGroup.buildAndBindMemberFields(this); + textField.setWidth("20em"); + addComponent(dateField); + addComponent(popupDateField); + addComponent(inlineDateField); + addComponent(textField); + + Button commitButton = new Button("Commit", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + String msg = "Commit succesful"; + try { + fieldGroup.commit(); + } catch (CommitException e) { + msg = "Commit failed: " + e.getMessage(); + } + Notification.show(msg); + log.log(msg); + + } + }); + Button discardButton = new Button("Discard", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + fieldGroup.discard(); + log.log("Discarded changes"); + + } + }); + Button showBean = new Button("Show bean values", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + log.log(getPerson(fieldGroup).toString()); + + } + }); + addComponent(commitButton); + addComponent(discardButton); + addComponent(showBean); + + DateObject d = new DateObject(new Date(443457289789L), new Date( + 443457289789L), new Date(443457289789L), + new Date(443457289789L)); + fieldGroup.setItemDataSource(new BeanItem<DateObject>(d)); + } + + public static Person getPerson(FieldGroup binder) { + return ((BeanItem<Person>) binder.getItemDataSource()).getBean(); + } + + @Override + protected String getDescription() { + return "Ensure FieldGroupFieldFactory supports Dates"; + } + + @Override + protected Integer getTicketNumber() { + return 8539; + } + +} diff --git a/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginMainView.java b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginMainView.java new file mode 100644 index 0000000000..cb59aa1608 --- /dev/null +++ b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginMainView.java @@ -0,0 +1,42 @@ +package com.vaadin.tests.minitutorials.v70; + +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Label; + +public class SimpleLoginMainView extends CustomComponent implements View { + + public static final String NAME = ""; + + Label text = new Label(); + + Button logout = new Button("Logout", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + + // "Logout" the user + getSession().setAttribute("user", null); + + // Refresh this view, should redirect to login view + getUI().getNavigator().navigateTo(NAME); + } + }); + + public SimpleLoginMainView() { + setCompositionRoot(new CssLayout(text, logout)); + } + + @Override + public void enter(ViewChangeEvent event) { + // Get the user name from the session + String username = String.valueOf(getSession().getAttribute("user")); + + // And show the username + text.setValue("Hello " + username); + } +} diff --git a/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginUI.java b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginUI.java new file mode 100644 index 0000000000..2fbbff10a8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginUI.java @@ -0,0 +1,64 @@ +package com.vaadin.tests.minitutorials.v70; + +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.UI; + +public class SimpleLoginUI extends UI { + + @Override + protected void init(VaadinRequest request) { + + /* + * Create a new instance of the navigator. The navigator will attach + * itself automatically to this view. + */ + new Navigator(this, this); + + /* + * The initial log view where the user can login to the application + */ + getNavigator().addView(SimpleLoginView.NAME, SimpleLoginView.class); + + /* + * Add the main view of the application + */ + getNavigator().addView(SimpleLoginMainView.NAME, + SimpleLoginMainView.class); + + /* + * We use a view change handler to ensure the user is always redirected + * to the login view if the user is not logged in. + */ + getNavigator().addViewChangeListener(new ViewChangeListener() { + + @Override + public boolean beforeViewChange(ViewChangeEvent event) { + + // Check if a user has logged in + boolean isLoggedIn = getSession().getAttribute("user") != null; + boolean isLoginView = event.getNewView() instanceof SimpleLoginView; + + if (!isLoggedIn && !isLoginView) { + // Redirect to login view always if a user has not yet + // logged in + getNavigator().navigateTo(SimpleLoginView.NAME); + return false; + + } else if (isLoggedIn && isLoginView) { + // If someone tries to access to login view while logged in, + // then cancel + return false; + } + + return true; + } + + @Override + public void afterViewChange(ViewChangeEvent event) { + + } + }); + } +} diff --git a/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginView.java b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginView.java new file mode 100644 index 0000000000..88a2a8f678 --- /dev/null +++ b/uitest/src/com/vaadin/tests/minitutorials/v70/SimpleLoginView.java @@ -0,0 +1,137 @@ +package com.vaadin.tests.minitutorials.v70; + +import com.vaadin.data.validator.AbstractValidator; +import com.vaadin.data.validator.EmailValidator; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.shared.ui.MarginInfo; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.PasswordField; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.Reindeer; + +public class SimpleLoginView extends CustomComponent implements View, + Button.ClickListener { + + public static final String NAME = "login"; + + private final TextField user; + + private final PasswordField password; + + private final Button loginButton; + + public SimpleLoginView() { + setSizeFull(); + + // Create the user input field + user = new TextField("User:"); + user.setWidth("300px"); + user.setRequired(true); + user.setInputPrompt("Your username (eg. joe@email.com)"); + user.addValidator(new EmailValidator("Username must be an email address")); + user.setInvalidAllowed(false); + + // Create the password input field + password = new PasswordField("Password:"); + password.setWidth("300px"); + password.addValidator(new PasswordValidator()); + password.setRequired(true); + password.setValue(""); + password.setNullRepresentation(""); + + // Create login button + loginButton = new Button("Login", this); + + // Add both to a panel + VerticalLayout fields = new VerticalLayout(user, password, loginButton); + fields.setCaption("Please login to access the application. (test@test.com/passw0rd)"); + fields.setSpacing(true); + fields.setMargin(new MarginInfo(true, true, true, false)); + fields.setSizeUndefined(); + + // The view root layout + VerticalLayout viewLayout = new VerticalLayout(fields); + viewLayout.setSizeFull(); + viewLayout.setComponentAlignment(fields, Alignment.MIDDLE_CENTER); + viewLayout.setStyleName(Reindeer.LAYOUT_BLUE); + setCompositionRoot(viewLayout); + } + + @Override + public void enter(ViewChangeEvent event) { + // focus the username field when user arrives to the login view + user.focus(); + } + + /* + * Validator for validating the passwords + */ + private static final class PasswordValidator extends + AbstractValidator<String> { + + public PasswordValidator() { + super("The password provided is not valid"); + } + + @Override + protected boolean isValidValue(String value) { + /* + * Password must be at least 8 characters long and contain at least + * one number + */ + if (value != null + && (value.length() < 8 || !value.matches(".*\\d.*"))) { + return false; + } + return true; + } + + @Override + public Class<String> getType() { + return String.class; + } + } + + @Override + public void buttonClick(ClickEvent event) { + + /* + * Validate the fields using the navigator. By using validors for the + * fields we reduce the amount of queries we have to use to the database + * for wrongly entered passwords + */ + if (!user.isValid() || !password.isValid()) { + return; + } + + String username = user.getValue(); + String password = this.password.getValue(); + + /* + * Validate username and password with database here. For examples sake + * I use a dummy username and password. + */ + boolean isValid = username.equals("test@test.com") + && password.equals("passw0rd"); + + if(isValid){ + // Store the current user in the service session + getSession().setAttribute("user", username); + + // Navigate to main view + getUI().getNavigator().navigateTo(SimpleLoginMainView.NAME); + + } else { + + // Wrong password clear the password field and refocuses it + this.password.setValue(null); + this.password.focus(); + } + } +} + |