diff options
Diffstat (limited to 'server')
341 files changed, 25015 insertions, 2071 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java index bdad94355d..164f04bb79 100644 --- a/server/src/com/vaadin/Application.java +++ b/server/src/com/vaadin/Application.java @@ -30,7 +30,6 @@ import java.util.EventListener; import java.util.EventObject; import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -51,27 +50,27 @@ import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.ConverterFactory; import com.vaadin.data.util.converter.DefaultConverterFactory; import com.vaadin.event.EventRouter; +import com.vaadin.server.AbstractApplicationServlet; +import com.vaadin.server.AbstractErrorMessage; +import com.vaadin.server.BootstrapFragmentResponse; +import com.vaadin.server.BootstrapListener; +import com.vaadin.server.BootstrapPageResponse; +import com.vaadin.server.BootstrapResponse; +import com.vaadin.server.ChangeVariablesErrorEvent; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.CombinedRequest; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.GlobalResourceHandler; +import com.vaadin.server.RequestHandler; +import com.vaadin.server.Terminal; +import com.vaadin.server.UIProvider; +import com.vaadin.server.VariableOwner; +import com.vaadin.server.WebApplicationContext; +import com.vaadin.server.WrappedRequest; +import com.vaadin.server.WrappedRequest.BrowserDetails; +import com.vaadin.server.WrappedResponse; import com.vaadin.service.ApplicationContext; import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.AbstractErrorMessage; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.CombinedRequest; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.Terminal; -import com.vaadin.terminal.UIProvider; -import com.vaadin.terminal.VariableOwner; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedRequest.BrowserDetails; -import com.vaadin.terminal.WrappedResponse; -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; -import com.vaadin.terminal.gwt.server.BootstrapFragmentResponse; -import com.vaadin.terminal.gwt.server.BootstrapListener; -import com.vaadin.terminal.gwt.server.BootstrapPageResponse; -import com.vaadin.terminal.gwt.server.BootstrapResponse; -import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent; -import com.vaadin.terminal.gwt.server.ClientConnector; -import com.vaadin.terminal.gwt.server.WebApplicationContext; import com.vaadin.tools.ReflectTools; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractField; @@ -123,8 +122,8 @@ import com.vaadin.ui.Window; * found out, the window itself is queried for a preferred theme. If the window * does not prefer a specific theme, the application containing the window is * queried. If neither the application prefers a theme, the default theme for - * the {@link com.vaadin.terminal.Terminal terminal} is used. The terminal - * always defines a default theme. + * the {@link com.vaadin.server.Terminal terminal} is used. The terminal always + * defines a default theme. * </p> * * @author Vaadin Ltd. @@ -458,10 +457,6 @@ public class Application implements Terminal.ErrorListener, Serializable { /** * Application resource mapping: key <-> resource. */ - private final Hashtable<ApplicationResource, String> resourceKeyMap = new Hashtable<ApplicationResource, String>(); - - private final Hashtable<String, ApplicationResource> keyResourceMap = new Hashtable<String, ApplicationResource>(); - private long lastResourceKeyNumber = 0; /** @@ -508,6 +503,8 @@ public class Application implements Terminal.ErrorListener, Serializable { private List<UIProvider> uiProviders = new LinkedList<UIProvider>(); + private GlobalResourceHandler globalResourceHandler; + /** * Gets the user of the application. * @@ -694,71 +691,6 @@ public class Application implements Terminal.ErrorListener, Serializable { } /** - * Adds new resource to the application. The resource can be accessed by the - * user of the application. - * - * @param resource - * the resource to add. - */ - public void addResource(ApplicationResource resource) { - - // Check if the resource is already mapped - if (resourceKeyMap.containsKey(resource)) { - return; - } - - // Generate key - final String key = String.valueOf(++lastResourceKeyNumber); - - // Add the resource to mappings - resourceKeyMap.put(resource, key); - keyResourceMap.put(key, resource); - } - - /** - * Removes the resource from the application. - * - * @param resource - * the resource to remove. - */ - public void removeResource(ApplicationResource resource) { - final Object key = resourceKeyMap.get(resource); - if (key != null) { - resourceKeyMap.remove(resource); - keyResourceMap.remove(key); - } - } - - /** - * Gets the relative uri of the resource. This method is intended to be - * called only be the terminal implementation. - * - * This method can only be called from within the processing of a UIDL - * request, not from a background thread. - * - * @param resource - * the resource to get relative location. - * @return the relative uri of the resource or null if called in a - * background thread - * - * @deprecated this method is intended to be used by the terminal only. It - * may be removed or moved in the future. - */ - @Deprecated - public String getRelativeLocation(ApplicationResource resource) { - - // Gets the key - final String key = resourceKeyMap.get(resource); - - // If the resource is not registered, return null - if (key == null) { - return null; - } - - return context.generateApplicationResourceURL(resource, key); - } - - /** * Gets the default locale for this application. * * By default this is the preferred locale of the user using the @@ -881,7 +813,7 @@ public class Application implements Terminal.ErrorListener, Serializable { * @param listener * the user change listener to add. */ - public void addListener(UserChangeListener listener) { + public void addUserChangeListener(UserChangeListener listener) { if (userChangeListeners == null) { userChangeListeners = new LinkedList<UserChangeListener>(); } @@ -889,12 +821,22 @@ public class Application implements Terminal.ErrorListener, Serializable { } /** + * @deprecated Since 7.0, replaced by + * {@link #addUserChangeListener(UserChangeListener)} + **/ + @Deprecated + public void addListener(UserChangeListener listener) { + addUserChangeListener(listener); + } + + /** * Removes the user change listener. * * @param listener * the user change listener to remove. */ - public void removeListener(UserChangeListener listener) { + + public void removeUserChangeListener(UserChangeListener listener) { if (userChangeListeners == null) { return; } @@ -905,6 +847,15 @@ public class Application implements Terminal.ErrorListener, Serializable { } /** + * @deprecated Since 7.0, replaced by + * {@link #removeUserChangeListener(UserChangeListener)} + **/ + @Deprecated + public void removeListener(UserChangeListener listener) { + removeUserChangeListener(listener); + } + + /** * Window detach event. * * This event is sent each time a window is removed from the application @@ -1075,7 +1026,7 @@ public class Application implements Terminal.ErrorListener, Serializable { * * @param event * the change event. - * @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent) + * @see com.vaadin.server.Terminal.ErrorListener#terminalError(com.vaadin.server.Terminal.ErrorEvent) */ @Override @@ -2066,20 +2017,6 @@ public class Application implements Terminal.ErrorListener, Serializable { } /** - * Find an application resource with a given key. - * - * @param key - * The key of the resource - * @return The application resource corresponding to the provided key, or - * <code>null</code> if no resource is registered for the key - * - * @since 7.0 - */ - public ApplicationResource getResource(String key) { - return keyResourceMap.get(key); - } - - /** * Thread local for keeping track of currently used application instance * * @since 7.0 @@ -2510,4 +2447,30 @@ public class Application implements Terminal.ErrorListener, Serializable { } return true; } + + /** + * Gets this application's global resource handler that takes care of + * serving connector resources that are not served by any single connector + * because e.g. because they are served with strong caching or because of + * legacy reasons. + * + * @param createOnDemand + * <code>true</code> if a resource handler should be initialized + * if there is no handler associated with this application. + * </code>false</code> if </code>null</code> should be returned + * if there is no registered handler. + * @return this application's global resource handler, or <code>null</code> + * if there is no handler and the createOnDemand parameter is + * <code>false</code>. + * + * @since 7.0.0 + */ + public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) { + if (globalResourceHandler == null && createOnDemand) { + globalResourceHandler = new GlobalResourceHandler(); + addRequestHandler(globalResourceHandler); + } + + return globalResourceHandler; + } } diff --git a/server/src/com/vaadin/UIRequiresMoreInformationException.java b/server/src/com/vaadin/UIRequiresMoreInformationException.java index 493c31acb6..76a31d88ef 100644 --- a/server/src/com/vaadin/UIRequiresMoreInformationException.java +++ b/server/src/com/vaadin/UIRequiresMoreInformationException.java @@ -16,8 +16,8 @@ package com.vaadin; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedRequest.BrowserDetails; +import com.vaadin.server.WrappedRequest; +import com.vaadin.server.WrappedRequest.BrowserDetails; /** * Exception that is thrown to indicate that creating or initializing the UI diff --git a/server/src/com/vaadin/annotations/EagerInit.java b/server/src/com/vaadin/annotations/EagerInit.java index 462c6bb5ac..f08d46b551 100644 --- a/server/src/com/vaadin/annotations/EagerInit.java +++ b/server/src/com/vaadin/annotations/EagerInit.java @@ -20,7 +20,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.vaadin.terminal.WrappedRequest; +import com.vaadin.server.WrappedRequest; import com.vaadin.ui.UI; /** @@ -29,7 +29,7 @@ import com.vaadin.ui.UI; * This will make the UI appear more quickly, as ensuring the availability of * this information typically requires an additional round trip to the client. * - * @see UI#init(com.vaadin.terminal.WrappedRequest) + * @see UI#init(com.vaadin.server.WrappedRequest) * @see WrappedRequest#getBrowserDetails() * * @since 7.0 diff --git a/server/src/com/vaadin/annotations/JavaScript.java b/server/src/com/vaadin/annotations/JavaScript.java index 7943fe1055..1a2fdf7583 100644 --- a/server/src/com/vaadin/annotations/JavaScript.java +++ b/server/src/com/vaadin/annotations/JavaScript.java @@ -21,7 +21,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.server.ClientConnector; /** * If this annotation is present on a {@link ClientConnector} class, the diff --git a/server/src/com/vaadin/annotations/StyleSheet.java b/server/src/com/vaadin/annotations/StyleSheet.java index 7833544ab5..e1a9efd696 100644 --- a/server/src/com/vaadin/annotations/StyleSheet.java +++ b/server/src/com/vaadin/annotations/StyleSheet.java @@ -21,7 +21,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.server.ClientConnector; /** * If this annotation is present on a {@link ClientConnector} class, the diff --git a/server/src/com/vaadin/data/Container.java b/server/src/com/vaadin/data/Container.java index de53b88018..155dde87ef 100644 --- a/server/src/com/vaadin/data/Container.java +++ b/server/src/com/vaadin/data/Container.java @@ -1016,6 +1016,14 @@ public interface Container extends Serializable { * @param listener * listener to be added */ + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(ItemSetChangeListener)} + **/ + @Deprecated public void addListener(Container.ItemSetChangeListener listener); /** @@ -1024,6 +1032,14 @@ public interface Container extends Serializable { * @param listener * listener to be removed */ + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(ItemSetChangeListener)} + **/ + @Deprecated public void removeListener(Container.ItemSetChangeListener listener); } @@ -1102,6 +1118,14 @@ public interface Container extends Serializable { * @param listener * The new Listener to be registered */ + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(PropertySetChangeListener)} + **/ + @Deprecated public void addListener(Container.PropertySetChangeListener listener); /** @@ -1110,6 +1134,14 @@ public interface Container extends Serializable { * @param listener * Listener to be removed */ + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(PropertySetChangeListener)} + **/ + @Deprecated public void removeListener(Container.PropertySetChangeListener listener); } } diff --git a/server/src/com/vaadin/data/Item.java b/server/src/com/vaadin/data/Item.java index 684027e608..8bdf963835 100644 --- a/server/src/com/vaadin/data/Item.java +++ b/server/src/com/vaadin/data/Item.java @@ -177,6 +177,14 @@ public interface Item extends Serializable { * @param listener * The new Listener to be registered. */ + public void addPropertySetChangeListener( + Item.PropertySetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(PropertySetChangeListener)} + **/ + @Deprecated public void addListener(Item.PropertySetChangeListener listener); /** @@ -185,6 +193,14 @@ public interface Item extends Serializable { * @param listener * Listener to be removed. */ + public void removePropertySetChangeListener( + Item.PropertySetChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(PropertySetChangeListener)} + **/ + @Deprecated public void removeListener(Item.PropertySetChangeListener listener); } } diff --git a/server/src/com/vaadin/data/Property.java b/server/src/com/vaadin/data/Property.java index 3e5c6826bb..7e46af09b7 100644 --- a/server/src/com/vaadin/data/Property.java +++ b/server/src/com/vaadin/data/Property.java @@ -304,6 +304,13 @@ public interface Property<T> extends Serializable { * @param listener * the new Listener to be registered */ + public void addValueChangeListener(Property.ValueChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(ValueChangeListener)} + **/ + @Deprecated public void addListener(Property.ValueChangeListener listener); /** @@ -312,6 +319,14 @@ public interface Property<T> extends Serializable { * @param listener * listener to be removed */ + public void removeValueChangeListener( + Property.ValueChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(ValueChangeListener)} + **/ + @Deprecated public void removeListener(Property.ValueChangeListener listener); } @@ -379,6 +394,14 @@ public interface Property<T> extends Serializable { * @param listener * the new Listener to be registered */ + public void addReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addReadOnlyStatusChangeListener(ReadOnlyStatusChangeListener)} + **/ + @Deprecated public void addListener(Property.ReadOnlyStatusChangeListener listener); /** @@ -387,6 +410,14 @@ public interface Property<T> extends Serializable { * @param listener * listener to be removed */ + public void removeReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeReadOnlyStatusChangeListener(ReadOnlyStatusChangeListener)} + **/ + @Deprecated public void removeListener( Property.ReadOnlyStatusChangeListener listener); } diff --git a/server/src/com/vaadin/data/Validator.java b/server/src/com/vaadin/data/Validator.java index ef07d3eadc..1755a44920 100644 --- a/server/src/com/vaadin/data/Validator.java +++ b/server/src/com/vaadin/data/Validator.java @@ -18,7 +18,7 @@ package com.vaadin.data; import java.io.Serializable; -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; +import com.vaadin.server.AbstractApplicationServlet; /** * Interface that implements a method for validating if an {@link Object} is diff --git a/server/src/com/vaadin/data/util/AbstractBeanContainer.java b/server/src/com/vaadin/data/util/AbstractBeanContainer.java index 9cd4afa3c2..cb09cdad46 100644 --- a/server/src/com/vaadin/data/util/AbstractBeanContainer.java +++ b/server/src/com/vaadin/data/util/AbstractBeanContainer.java @@ -741,14 +741,35 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends return new PropertyBasedBeanIdResolver(propertyId); } + /** + * @deprecated Since 7.0, replaced by {@link #addPropertySetChangeListener} + **/ + @Deprecated @Override public void addListener(Container.PropertySetChangeListener listener) { - super.addListener(listener); + addPropertySetChangeListener(listener); + } + + @Override + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { + super.addPropertySetChangeListener(listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated @Override public void removeListener(Container.PropertySetChangeListener listener) { - super.removeListener(listener); + removePropertySetChangeListener(listener); + } + + @Override + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { + super.removePropertySetChangeListener(listener); } @Override diff --git a/server/src/com/vaadin/data/util/AbstractContainer.java b/server/src/com/vaadin/data/util/AbstractContainer.java index fbce468bce..ff8fc90651 100644 --- a/server/src/com/vaadin/data/util/AbstractContainer.java +++ b/server/src/com/vaadin/data/util/AbstractContainer.java @@ -100,7 +100,8 @@ public abstract class AbstractContainer implements Container { * * @see PropertySetChangeNotifier#addListener(com.vaadin.data.Container.PropertySetChangeListener) */ - protected void addListener(Container.PropertySetChangeListener listener) { + protected void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (getPropertySetChangeListeners() == null) { setPropertySetChangeListeners(new LinkedList<Container.PropertySetChangeListener>()); } @@ -108,6 +109,15 @@ public abstract class AbstractContainer implements Container { } /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + protected void addListener(Container.PropertySetChangeListener listener) { + addPropertySetChangeListener(listener); + } + + /** * Implementation of the corresponding method in * {@link PropertySetChangeNotifier}, override with the corresponding public * method and implement the interface to use this. @@ -115,12 +125,22 @@ public abstract class AbstractContainer implements Container { * @see PropertySetChangeNotifier#removeListener(com.vaadin.data.Container. * PropertySetChangeListener) */ - protected void removeListener(Container.PropertySetChangeListener listener) { + protected void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (getPropertySetChangeListeners() != null) { getPropertySetChangeListeners().remove(listener); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + protected void removeListener(Container.PropertySetChangeListener listener) { + removePropertySetChangeListener(listener); + } + // ItemSetChangeNotifier /** @@ -130,7 +150,8 @@ public abstract class AbstractContainer implements Container { * * @see ItemSetChangeNotifier#addListener(com.vaadin.data.Container.ItemSetChangeListener) */ - protected void addListener(Container.ItemSetChangeListener listener) { + protected void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (getItemSetChangeListeners() == null) { setItemSetChangeListeners(new LinkedList<Container.ItemSetChangeListener>()); } @@ -138,19 +159,38 @@ public abstract class AbstractContainer implements Container { } /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + protected void addListener(Container.ItemSetChangeListener listener) { + addItemSetChangeListener(listener); + } + + /** * Implementation of the corresponding method in * {@link ItemSetChangeNotifier}, override with the corresponding public * method and implement the interface to use this. * * @see ItemSetChangeNotifier#removeListener(com.vaadin.data.Container.ItemSetChangeListener) */ - protected void removeListener(Container.ItemSetChangeListener listener) { + protected void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (getItemSetChangeListeners() != null) { getItemSetChangeListeners().remove(listener); } } /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + protected void removeListener(Container.ItemSetChangeListener listener) { + removeItemSetChangeListener(listener); + } + + /** * Sends a simple Property set change event to all interested listeners. */ protected void fireContainerPropertySetChange() { diff --git a/server/src/com/vaadin/data/util/AbstractInMemoryContainer.java b/server/src/com/vaadin/data/util/AbstractInMemoryContainer.java index fd2ced2d4a..6eea9cb421 100644 --- a/server/src/com/vaadin/data/util/AbstractInMemoryContainer.java +++ b/server/src/com/vaadin/data/util/AbstractInMemoryContainer.java @@ -324,15 +324,36 @@ public abstract class AbstractInMemoryContainer<ITEMIDTYPE, PROPERTYIDCLASS, ITE } // ItemSetChangeNotifier - + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated @Override public void addListener(Container.ItemSetChangeListener listener) { - super.addListener(listener); + addItemSetChangeListener(listener); + } + + @Override + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { + super.addItemSetChangeListener(listener); } @Override + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { + super.removeItemSetChangeListener(listener); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + @Override public void removeListener(Container.ItemSetChangeListener listener) { - super.removeListener(listener); + removeItemSetChangeListener(listener); } // internal methods diff --git a/server/src/com/vaadin/data/util/AbstractProperty.java b/server/src/com/vaadin/data/util/AbstractProperty.java index f508156d05..6636996cd5 100644 --- a/server/src/com/vaadin/data/util/AbstractProperty.java +++ b/server/src/com/vaadin/data/util/AbstractProperty.java @@ -121,7 +121,8 @@ public abstract class AbstractProperty<T> implements Property<T>, * the new Listener to be registered. */ @Override - public void addListener(Property.ReadOnlyStatusChangeListener listener) { + public void addReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { if (readOnlyStatusChangeListeners == null) { readOnlyStatusChangeListeners = new LinkedList<ReadOnlyStatusChangeListener>(); } @@ -129,19 +130,38 @@ public abstract class AbstractProperty<T> implements Property<T>, } /** + * @deprecated Since 7.0, replaced by + * {@link #addReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Deprecated + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + addReadOnlyStatusChangeListener(listener); + } + + /** * Removes a previously registered read-only status change listener. * * @param listener * the listener to be removed. */ @Override - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + public void removeReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { if (readOnlyStatusChangeListeners != null) { readOnlyStatusChangeListeners.remove(listener); } } /** + * @deprecated Since 7.0, replaced by + * {@link #removeReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + removeReadOnlyStatusChangeListener(listener); + } + + /** * Sends a read only status change event to all registered listeners. */ protected void fireReadOnlyStatusChange() { @@ -186,7 +206,7 @@ public abstract class AbstractProperty<T> implements Property<T>, } @Override - public void addListener(ValueChangeListener listener) { + public void addValueChangeListener(ValueChangeListener listener) { if (valueChangeListeners == null) { valueChangeListeners = new LinkedList<ValueChangeListener>(); } @@ -194,8 +214,17 @@ public abstract class AbstractProperty<T> implements Property<T>, } + /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void addListener(ValueChangeListener listener) { + addValueChangeListener(listener); + } + @Override - public void removeListener(ValueChangeListener listener) { + public void removeValueChangeListener(ValueChangeListener listener) { if (valueChangeListeners != null) { valueChangeListeners.remove(listener); } @@ -203,6 +232,15 @@ public abstract class AbstractProperty<T> implements Property<T>, } /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void removeListener(ValueChangeListener listener) { + removeValueChangeListener(listener); + } + + /** * Sends a value change event to all registered listeners. */ protected void fireValueChange() { diff --git a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java index 8f9000bce0..24d0a8d3a0 100644 --- a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java +++ b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java @@ -710,53 +710,95 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, * interface. */ @Override - public void addListener(Container.ItemSetChangeListener listener) { + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (container instanceof Container.ItemSetChangeNotifier) { ((Container.ItemSetChangeNotifier) container) - .addListener(new PiggybackListener(listener)); + .addItemSetChangeListener(new PiggybackListener(listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void addListener(Container.ItemSetChangeListener listener) { + addItemSetChangeListener(listener); + } + /* * Removes a Item set change listener from the object. Don't add a JavaDoc * comment here, we use the default documentation from implemented * interface. */ @Override - public void removeListener(Container.ItemSetChangeListener listener) { + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (container instanceof Container.ItemSetChangeNotifier) { ((Container.ItemSetChangeNotifier) container) - .removeListener(new PiggybackListener(listener)); + .removeItemSetChangeListener(new PiggybackListener(listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.ItemSetChangeListener listener) { + removeItemSetChangeListener(listener); + } + /* * Registers a new Property set change listener for this Container. Don't * add a JavaDoc comment here, we use the default documentation from * implemented interface. */ @Override - public void addListener(Container.PropertySetChangeListener listener) { + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (container instanceof Container.PropertySetChangeNotifier) { ((Container.PropertySetChangeNotifier) container) - .addListener(new PiggybackListener(listener)); + .addPropertySetChangeListener(new PiggybackListener( + listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void addListener(Container.PropertySetChangeListener listener) { + addPropertySetChangeListener(listener); + } + /* * Removes a Property set change listener from the object. Don't add a * JavaDoc comment here, we use the default documentation from implemented * interface. */ @Override - public void removeListener(Container.PropertySetChangeListener listener) { + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (container instanceof Container.PropertySetChangeNotifier) { ((Container.PropertySetChangeNotifier) container) - .removeListener(new PiggybackListener(listener)); + .removePropertySetChangeListener(new PiggybackListener( + listener)); } } /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.PropertySetChangeListener listener) { + removePropertySetChangeListener(listener); + } + + /** * This listener 'piggybacks' on the real listener in order to update the * wrapper when needed. It proxies equals() and hashCode() to the real * listener so that the correct listener gets removed. diff --git a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java index d332931008..bb904f4cda 100644 --- a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java +++ b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java @@ -510,52 +510,94 @@ public class ContainerOrderedWrapper implements Container.Ordered, * interface. */ @Override - public void addListener(Container.ItemSetChangeListener listener) { + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (container instanceof Container.ItemSetChangeNotifier) { ((Container.ItemSetChangeNotifier) container) - .addListener(new PiggybackListener(listener)); + .addItemSetChangeListener(new PiggybackListener(listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void addListener(Container.ItemSetChangeListener listener) { + addItemSetChangeListener(listener); + } + /* * Removes a Item set change listener from the object. Don't add a JavaDoc * comment here, we use the default documentation from implemented * interface. */ @Override - public void removeListener(Container.ItemSetChangeListener listener) { + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (container instanceof Container.ItemSetChangeNotifier) { ((Container.ItemSetChangeNotifier) container) - .removeListener(new PiggybackListener(listener)); + .removeItemSetChangeListener(new PiggybackListener(listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.ItemSetChangeListener listener) { + removeItemSetChangeListener(listener); + } + /* * Registers a new Property set change listener for this Container. Don't * add a JavaDoc comment here, we use the default documentation from * implemented interface. */ @Override - public void addListener(Container.PropertySetChangeListener listener) { + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (container instanceof Container.PropertySetChangeNotifier) { ((Container.PropertySetChangeNotifier) container) - .addListener(new PiggybackListener(listener)); + .addPropertySetChangeListener(new PiggybackListener( + listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void addListener(Container.PropertySetChangeListener listener) { + addPropertySetChangeListener(listener); + } + /* * Removes a Property set change listener from the object. Don't add a * JavaDoc comment here, we use the default documentation from implemented * interface. */ @Override - public void removeListener(Container.PropertySetChangeListener listener) { + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (container instanceof Container.PropertySetChangeNotifier) { ((Container.PropertySetChangeNotifier) container) - .removeListener(new PiggybackListener(listener)); + .removePropertySetChangeListener(new PiggybackListener( + listener)); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.PropertySetChangeListener listener) { + removePropertySetChangeListener(listener); + } + /* * (non-Javadoc) * diff --git a/server/src/com/vaadin/data/util/FilesystemContainer.java b/server/src/com/vaadin/data/util/FilesystemContainer.java index 54ee2d6f0c..4c27169409 100644 --- a/server/src/com/vaadin/data/util/FilesystemContainer.java +++ b/server/src/com/vaadin/data/util/FilesystemContainer.java @@ -33,8 +33,8 @@ import java.util.List; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; +import com.vaadin.server.Resource; import com.vaadin.service.FileTypeResolver; -import com.vaadin.terminal.Resource; /** * A hierarchical container wrapper for a filesystem. diff --git a/server/src/com/vaadin/data/util/IndexedContainer.java b/server/src/com/vaadin/data/util/IndexedContainer.java index 5566b2f18c..e0a8fe1dc1 100644 --- a/server/src/com/vaadin/data/util/IndexedContainer.java +++ b/server/src/com/vaadin/data/util/IndexedContainer.java @@ -483,13 +483,35 @@ public class IndexedContainer extends } @Override + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { + super.addPropertySetChangeListener(listener); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + @Override public void addListener(Container.PropertySetChangeListener listener) { - super.addListener(listener); + addPropertySetChangeListener(listener); } @Override + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { + super.removePropertySetChangeListener(listener); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + @Override public void removeListener(Container.PropertySetChangeListener listener) { - super.removeListener(listener); + removePropertySetChangeListener(listener); } /* @@ -499,13 +521,22 @@ public class IndexedContainer extends * vaadin.data.Property.ValueChangeListener) */ @Override - public void addListener(Property.ValueChangeListener listener) { + public void addValueChangeListener(Property.ValueChangeListener listener) { if (propertyValueChangeListeners == null) { propertyValueChangeListeners = new LinkedList<Property.ValueChangeListener>(); } propertyValueChangeListeners.add(listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void addListener(Property.ValueChangeListener listener) { + addValueChangeListener(listener); + } + /* * (non-Javadoc) * @@ -513,13 +544,22 @@ public class IndexedContainer extends * .vaadin.data.Property.ValueChangeListener) */ @Override - public void removeListener(Property.ValueChangeListener listener) { + public void removeValueChangeListener(Property.ValueChangeListener listener) { if (propertyValueChangeListeners != null) { propertyValueChangeListeners.remove(listener); } } /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ValueChangeListener listener) { + removeValueChangeListener(listener); + } + + /** * Sends a Property value change event to all interested listeners. * * @param source @@ -965,10 +1005,19 @@ public class IndexedContainer extends * com.vaadin.data.Property.ValueChangeListener) */ @Override - public void addListener(Property.ValueChangeListener listener) { + public void addValueChangeListener(Property.ValueChangeListener listener) { addSinglePropertyChangeListener(propertyId, itemId, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void addListener(Property.ValueChangeListener listener) { + addValueChangeListener(listener); + } + /* * (non-Javadoc) * @@ -976,10 +1025,20 @@ public class IndexedContainer extends * (com.vaadin.data.Property.ValueChangeListener) */ @Override - public void removeListener(Property.ValueChangeListener listener) { + public void removeValueChangeListener( + Property.ValueChangeListener listener) { removeSinglePropertyChangeListener(propertyId, itemId, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ValueChangeListener listener) { + removeValueChangeListener(listener); + } + private IndexedContainer getHost() { return IndexedContainer.this; } diff --git a/server/src/com/vaadin/data/util/PropertysetItem.java b/server/src/com/vaadin/data/util/PropertysetItem.java index e86d813809..6fba011d75 100644 --- a/server/src/com/vaadin/data/util/PropertysetItem.java +++ b/server/src/com/vaadin/data/util/PropertysetItem.java @@ -200,7 +200,8 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, * the new Listener to be registered. */ @Override - public void addListener(Item.PropertySetChangeListener listener) { + public void addPropertySetChangeListener( + Item.PropertySetChangeListener listener) { if (propertySetChangeListeners == null) { propertySetChangeListeners = new LinkedList<PropertySetChangeListener>(); } @@ -208,19 +209,38 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, } /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Item.PropertySetChangeListener)} + **/ + @Deprecated + public void addListener(Item.PropertySetChangeListener listener) { + addPropertySetChangeListener(listener); + } + + /** * Removes a previously registered property set change listener. * * @param listener * the Listener to be removed. */ @Override - public void removeListener(Item.PropertySetChangeListener listener) { + public void removePropertySetChangeListener( + Item.PropertySetChangeListener listener) { if (propertySetChangeListeners != null) { propertySetChangeListeners.remove(listener); } } /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Item.PropertySetChangeListener)} + **/ + @Deprecated + public void removeListener(Item.PropertySetChangeListener listener) { + removePropertySetChangeListener(listener); + } + + /** * Sends a Property set change event to all interested listeners. */ private void fireItemPropertySetChange() { diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java index 13248f1e06..a53f32b96e 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java @@ -1493,13 +1493,23 @@ public class SQLContainer implements Container, Container.Filterable, */ @Override - public void addListener(Container.ItemSetChangeListener listener) { + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (itemSetChangeListeners == null) { itemSetChangeListeners = new LinkedList<Container.ItemSetChangeListener>(); } itemSetChangeListeners.add(listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void addListener(Container.ItemSetChangeListener listener) { + addItemSetChangeListener(listener); + } + /* * (non-Javadoc) * @@ -1509,12 +1519,22 @@ public class SQLContainer implements Container, Container.Filterable, */ @Override - public void removeListener(Container.ItemSetChangeListener listener) { + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (itemSetChangeListeners != null) { itemSetChangeListeners.remove(listener); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.ItemSetChangeListener listener) { + removeItemSetChangeListener(listener); + } + protected void fireContentsChange() { if (itemSetChangeListeners != null) { final Object[] l = itemSetChangeListeners.toArray(); @@ -1553,7 +1573,7 @@ public class SQLContainer implements Container, Container.Filterable, * * @param listener */ - public void addListener(RowIdChangeListener listener) { + public void addRowIdChangeListener(RowIdChangeListener listener) { if (delegate instanceof QueryDelegate.RowIdChangeNotifier) { ((QueryDelegate.RowIdChangeNotifier) delegate) .addListener(listener); @@ -1561,11 +1581,20 @@ public class SQLContainer implements Container, Container.Filterable, } /** + * @deprecated Since 7.0, replaced by + * {@link #addRowIdChangeListener(RowIdChangeListener)} + **/ + @Deprecated + public void addListener(RowIdChangeListener listener) { + addRowIdChangeListener(listener); + } + + /** * Removes a RowIdChangeListener from the QueryDelegate * * @param listener */ - public void removeListener(RowIdChangeListener listener) { + public void removeRowIdChangeListener(RowIdChangeListener listener) { if (delegate instanceof QueryDelegate.RowIdChangeNotifier) { ((QueryDelegate.RowIdChangeNotifier) delegate) .removeListener(listener); @@ -1573,6 +1602,15 @@ public class SQLContainer implements Container, Container.Filterable, } /** + * @deprecated Since 7.0, replaced by + * {@link #removeRowIdChangeListener(RowIdChangeListener)} + **/ + @Deprecated + public void removeListener(RowIdChangeListener listener) { + removeRowIdChangeListener(listener); + } + + /** * Calling this will enable this SQLContainer to send and receive cache * flush notifications for its lifetime. */ diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/QueryDelegate.java b/server/src/com/vaadin/data/util/sqlcontainer/query/QueryDelegate.java index 3e1866932b..10a710e823 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/QueryDelegate.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/QueryDelegate.java @@ -210,6 +210,14 @@ public interface QueryDelegate extends Serializable { * @param listener * listener to be added */ + public void addRowIdChangeListener( + QueryDelegate.RowIdChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addRowIdChangeListener(RowIdChangeListener)} + **/ + @Deprecated public void addListener(QueryDelegate.RowIdChangeListener listener); /** @@ -218,6 +226,14 @@ public interface QueryDelegate extends Serializable { * @param listener * listener to be removed */ + public void removeRowIdChangeListener( + QueryDelegate.RowIdChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeRowIdChangeListener(RowIdChangeListener)} + **/ + @Deprecated public void removeListener(QueryDelegate.RowIdChangeListener listener); } } diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java index e4544a491a..a6a1a5a8fb 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java @@ -704,7 +704,7 @@ public class TableQuery implements QueryDelegate, * Adds RowIdChangeListener to this query */ @Override - public void addListener(RowIdChangeListener listener) { + public void addRowIdChangeListener(RowIdChangeListener listener) { if (rowIdChangeListeners == null) { rowIdChangeListeners = new LinkedList<QueryDelegate.RowIdChangeListener>(); } @@ -712,15 +712,33 @@ public class TableQuery implements QueryDelegate, } /** + * @deprecated Since 7.0, replaced by + * {@link #addRowIdChangeListener(com.vaadin.data.util.sqlcontainer.query.QueryDelegate.RowIdChangeListener)} + **/ + @Deprecated + public void addListener(RowIdChangeListener listener) { + addRowIdChangeListener(listener); + } + + /** * Removes the given RowIdChangeListener from this query */ @Override - public void removeListener(RowIdChangeListener listener) { + public void removeRowIdChangeListener(RowIdChangeListener listener) { if (rowIdChangeListeners != null) { rowIdChangeListeners.remove(listener); } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeRowIdChangeListener(com.vaadin.data.util.sqlcontainer.query.QueryDelegate.RowIdChangeListener)} + **/ + @Deprecated + public void removeListener(RowIdChangeListener listener) { + removeRowIdChangeListener(listener); + } + private static final Logger getLogger() { return Logger.getLogger(TableQuery.class.getName()); } diff --git a/server/src/com/vaadin/event/Action.java b/server/src/com/vaadin/event/Action.java index aca28940a1..b8296418d3 100644 --- a/server/src/com/vaadin/event/Action.java +++ b/server/src/com/vaadin/event/Action.java @@ -18,7 +18,7 @@ package com.vaadin.event; import java.io.Serializable; -import com.vaadin.terminal.Resource; +import com.vaadin.server.Resource; /** * Implements the action framework. This class contains subinterfaces for action diff --git a/server/src/com/vaadin/event/ActionManager.java b/server/src/com/vaadin/event/ActionManager.java index 296d12ba92..85a1bf0f12 100644 --- a/server/src/com/vaadin/event/ActionManager.java +++ b/server/src/com/vaadin/event/ActionManager.java @@ -20,10 +20,10 @@ import java.util.Map; import com.vaadin.event.Action.Container; import com.vaadin.event.Action.Handler; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.VariableOwner; +import com.vaadin.server.KeyMapper; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.VariableOwner; import com.vaadin.ui.Component; /** diff --git a/server/src/com/vaadin/event/FieldEvents.java b/server/src/com/vaadin/event/FieldEvents.java index 8e247a6fef..10df08291e 100644 --- a/server/src/com/vaadin/event/FieldEvents.java +++ b/server/src/com/vaadin/event/FieldEvents.java @@ -59,6 +59,13 @@ public interface FieldEvents { * @see FocusListener * @since 6.2 */ + public void addFocusListener(FocusListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated public void addListener(FocusListener listener); /** @@ -68,6 +75,13 @@ public interface FieldEvents { * @see FocusListener * @since 6.2 */ + public void removeFocusListener(FocusListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated public void removeListener(FocusListener listener); } @@ -97,6 +111,13 @@ public interface FieldEvents { * @see BlurListener * @since 6.2 */ + public void addBlurListener(BlurListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addBlurListener(BlurListener)} + **/ + @Deprecated public void addListener(BlurListener listener); /** @@ -106,6 +127,13 @@ public interface FieldEvents { * @see BlurListener * @since 6.2 */ + public void removeBlurListener(BlurListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated public void removeListener(BlurListener listener); } @@ -257,8 +285,22 @@ public interface FieldEvents { * {@link TextChangeListener}s. */ public interface TextChangeNotifier extends Serializable { + public void addTextChangeListener(TextChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addTextChangeListener(TextChangeListener)} + **/ + @Deprecated public void addListener(TextChangeListener listener); + public void removeTextChangeListener(TextChangeListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeTextChangeListener(TextChangeListener)} + **/ + @Deprecated public void removeListener(TextChangeListener listener); } diff --git a/server/src/com/vaadin/event/ItemClickEvent.java b/server/src/com/vaadin/event/ItemClickEvent.java index c736353614..99c36cf51b 100644 --- a/server/src/com/vaadin/event/ItemClickEvent.java +++ b/server/src/com/vaadin/event/ItemClickEvent.java @@ -119,6 +119,13 @@ public class ItemClickEvent extends ClickEvent implements Serializable { * @param listener * ItemClickListener to be registered */ + public void addItemClickListener(ItemClickListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemClickListener(ItemClickListener)} + **/ + @Deprecated public void addListener(ItemClickListener listener); /** @@ -127,6 +134,13 @@ public class ItemClickEvent extends ClickEvent implements Serializable { * @param listener * ItemClickListener to be removed */ + public void removeItemClickListener(ItemClickListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemClickListener(ItemClickListener)} + **/ + @Deprecated public void removeListener(ItemClickListener listener); } diff --git a/server/src/com/vaadin/event/LayoutEvents.java b/server/src/com/vaadin/event/LayoutEvents.java index 7fc6e5a42d..7f88ddc640 100644 --- a/server/src/com/vaadin/event/LayoutEvents.java +++ b/server/src/com/vaadin/event/LayoutEvents.java @@ -78,6 +78,13 @@ public interface LayoutEvents { * @param listener * The listener to add */ + public void addLayoutClickListener(LayoutClickListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated public void addListener(LayoutClickListener listener); /** @@ -86,6 +93,13 @@ public interface LayoutEvents { * @param listener * LayoutClickListener to be removed */ + public void removeLayoutClickListener(LayoutClickListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated public void removeListener(LayoutClickListener listener); } diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java index b3f41b474d..b1d14b15fe 100644 --- a/server/src/com/vaadin/event/ShortcutAction.java +++ b/server/src/com/vaadin/event/ShortcutAction.java @@ -20,7 +20,7 @@ import java.io.Serializable; import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.vaadin.terminal.Resource; +import com.vaadin.server.Resource; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.Panel; import com.vaadin.ui.Window; diff --git a/server/src/com/vaadin/event/ShortcutListener.java b/server/src/com/vaadin/event/ShortcutListener.java index 82a09585b3..d7e0577e84 100644 --- a/server/src/com/vaadin/event/ShortcutListener.java +++ b/server/src/com/vaadin/event/ShortcutListener.java @@ -16,7 +16,7 @@ package com.vaadin.event; import com.vaadin.event.Action.Listener; -import com.vaadin.terminal.Resource; +import com.vaadin.server.Resource; public abstract class ShortcutListener extends ShortcutAction implements Listener { diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java b/server/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java index 7b04efc4b3..850e68b231 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java @@ -23,8 +23,8 @@ import java.io.Serializable; import com.vaadin.event.Transferable; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * Criterion that can be used create policy to accept/discard dragged content diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/And.java b/server/src/com/vaadin/event/dd/acceptcriteria/And.java index 3d11ecf7bf..183010a298 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/And.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/And.java @@ -19,8 +19,8 @@ package com.vaadin.event.dd.acceptcriteria; import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * A compound criterion that accepts the drag if all of its criteria accepts the diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/ClientSideCriterion.java b/server/src/com/vaadin/event/dd/acceptcriteria/ClientSideCriterion.java index be7e2d4033..e862cdfd39 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/ClientSideCriterion.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/ClientSideCriterion.java @@ -17,8 +17,8 @@ package com.vaadin.event.dd.acceptcriteria; import java.io.Serializable; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * Parent class for criteria that can be completely validated on client side. diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java b/server/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java index 55ee17fea9..97094814ef 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java @@ -20,8 +20,8 @@ package com.vaadin.event.dd.acceptcriteria; import com.vaadin.event.Transferable; import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * A Criterion that checks whether {@link Transferable} contains given data diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/Not.java b/server/src/com/vaadin/event/dd/acceptcriteria/Not.java index b3f73699ea..9e1b1571ae 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/Not.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/Not.java @@ -19,8 +19,8 @@ package com.vaadin.event.dd.acceptcriteria; import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * Criterion that wraps another criterion and inverts its return value. diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/Or.java b/server/src/com/vaadin/event/dd/acceptcriteria/Or.java index 42d1c3293d..7aa7d8cd20 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/Or.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/Or.java @@ -19,8 +19,8 @@ package com.vaadin.event.dd.acceptcriteria; import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * A compound criterion that accepts the drag if any of its criterion accepts diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java b/server/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java index b9c2855021..b7457605b8 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java @@ -18,8 +18,8 @@ package com.vaadin.event.dd.acceptcriteria; import java.io.Serializable; import com.vaadin.event.Transferable; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * Parent class for criteria which are verified on the server side during a drag diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java index cc1d586076..6258aed423 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java @@ -23,8 +23,8 @@ import java.util.logging.Logger; import com.vaadin.event.TransferableImpl; import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; import com.vaadin.ui.Component; /** diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java b/server/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java index 536ba8780e..a6d3e2c5d5 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java @@ -20,8 +20,8 @@ package com.vaadin.event.dd.acceptcriteria; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.TargetDetails; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * Criterion for checking if drop target details contains the specific property diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index 13e87c16ad..cef27c221d 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -22,9 +22,9 @@ import java.util.LinkedList; import java.util.List; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; -import com.vaadin.terminal.Page; -import com.vaadin.terminal.Page.FragmentChangedEvent; -import com.vaadin.terminal.Page.FragmentChangedListener; +import com.vaadin.server.Page; +import com.vaadin.server.Page.FragmentChangedEvent; +import com.vaadin.server.Page.FragmentChangedListener; import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.CssLayout; @@ -435,7 +435,7 @@ public class Navigator implements Serializable { } } if (viewWithLongestName != null) { - String parameters = null; + String parameters = ""; if (viewAndParameters.length() > longestViewName.length() + 1) { parameters = viewAndParameters.substring(longestViewName .length() + 1); @@ -469,7 +469,7 @@ public class Navigator implements Serializable { if (null != viewName && getFragmentManager() != null) { String currentFragment = viewName; - if (fragmentParameters != null) { + if (!fragmentParameters.equals("")) { currentFragment += "/" + fragmentParameters; } if (!currentFragment.equals(getFragmentManager().getFragment())) { @@ -651,18 +651,36 @@ public class Navigator implements Serializable { * @param listener * Listener to invoke after view changes. */ - public void addListener(ViewChangeListener listener) { + public void addViewChangeListener(ViewChangeListener listener) { listeners.add(listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #addViewChangeListener(ViewChangeListener)} + **/ + @Deprecated + public void addListener(ViewChangeListener listener) { + addViewChangeListener(listener); + } + + /** * Remove a view change listener. * * @param listener * Listener to remove. */ - public void removeListener(ViewChangeListener listener) { + public void removeViewChangeListener(ViewChangeListener listener) { listeners.remove(listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeViewChangeListener(ViewChangeListener)} + **/ + @Deprecated + public void removeListener(ViewChangeListener listener) { + removeViewChangeListener(listener); + } + } diff --git a/server/src/com/vaadin/navigator/View.java b/server/src/com/vaadin/navigator/View.java index 4db334a2dd..caee801f0c 100644 --- a/server/src/com/vaadin/navigator/View.java +++ b/server/src/com/vaadin/navigator/View.java @@ -38,11 +38,9 @@ public interface View extends Serializable { * is any additional id to data what should be shown in the view, it is also * optionally passed as parameter. * - * TODO fragmentParameters null if no parameters or empty string? - * * @param fragmentParameters - * parameters to the view or null if none given. This is the - * string that appears e.g. in URI after "viewname/" + * parameters to the view or empty string if none given. This is + * the string that appears e.g. in URI after "viewname/" */ public void navigateTo(String fragmentParameters); }
\ No newline at end of file diff --git a/server/src/com/vaadin/package.html b/server/src/com/vaadin/package.html index f771019709..097fd94aca 100644 --- a/server/src/com/vaadin/package.html +++ b/server/src/com/vaadin/package.html @@ -5,22 +5,20 @@ <body bgcolor="white"> -<p>The Vaadin base package. Contains the Application class, the -starting point of any application that uses Vaadin.</p> + <p>The Vaadin base package. Contains the Application class, the + starting point of any application that uses Vaadin.</p> -<p>Contains all Vaadin core classes. A Vaadin application is based -on the {@link com.vaadin.Application} class and deployed as a servlet -using {@link com.vaadin.terminal.gwt.server.ApplicationServlet} or -{@link com.vaadin.terminal.gwt.server.GAEApplicationServlet} (for Google -App Engine).</p> + <p>Contains all Vaadin core classes. A Vaadin application is based + on the {@link com.vaadin.Application} class and deployed as a servlet + using {@link com.vaadin.server.ApplicationServlet} or {@link + com.vaadin.server.GAEApplicationServlet} (for Google App Engine).</p> -<p>Vaadin applications can also be deployed as portlets using {@link -com.vaadin.terminal.gwt.server.ApplicationPortlet} (JSR-168) or {@link -com.vaadin.terminal.gwt.server.ApplicationPortlet2} (JSR-286).</p> + <p>Vaadin applications can also be deployed as portlets using + {@link com.vaadin.server.ApplicationPortlet2} (JSR-286).</p> -<p>All classes in Vaadin are serializable unless otherwise noted. -This allows Vaadin applications to run in cluster and cloud -environments.</p> + <p>All classes in Vaadin are serializable unless otherwise noted. + This allows Vaadin applications to run in cluster and cloud + environments.</p> </body> diff --git a/server/src/com/vaadin/portal/gwt/PortalDefaultWidgetSet.gwt.xml b/server/src/com/vaadin/portal/gwt/PortalDefaultWidgetSet.gwt.xml deleted file mode 100644 index bd91d05b02..0000000000 --- a/server/src/com/vaadin/portal/gwt/PortalDefaultWidgetSet.gwt.xml +++ /dev/null @@ -1,6 +0,0 @@ -<module> - <!-- WS Compiler: manually edited --> - - <!-- Inherit the DefaultWidgetSet --> - <inherits name="com.vaadin.terminal.gwt.DefaultWidgetSet" /> -</module> diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/server/src/com/vaadin/server/AbstractApplicationPortlet.java index 345f462239..e47e00577b 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/server/src/com/vaadin/server/AbstractApplicationPortlet.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.BufferedWriter; import java.io.IOException; @@ -57,11 +57,7 @@ import com.vaadin.Application; import com.vaadin.Application.ApplicationStartEvent; import com.vaadin.Application.SystemMessages; import com.vaadin.UIRequiresMoreInformationException; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.Terminal; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager.Callback; +import com.vaadin.server.AbstractCommunicationManager.Callback; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/server/src/com/vaadin/server/AbstractApplicationServlet.java index 13fd869166..2f0dad7079 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/server/src/com/vaadin/server/AbstractApplicationServlet.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.BufferedWriter; import java.io.IOException; @@ -49,13 +49,8 @@ import javax.servlet.http.HttpSession; import com.vaadin.Application; import com.vaadin.Application.ApplicationStartEvent; import com.vaadin.Application.SystemMessages; +import com.vaadin.server.AbstractCommunicationManager.Callback; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.Terminal; -import com.vaadin.terminal.ThemeResource; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager.Callback; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java index 157bd17e41..2f660a443d 100644 --- a/server/src/com/vaadin/terminal/AbstractClientConnector.java +++ b/server/src/com/vaadin/server/AbstractClientConnector.java @@ -13,8 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; +import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; @@ -36,12 +37,6 @@ import com.vaadin.external.json.JSONObject; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.communication.SharedState; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; -import com.vaadin.terminal.gwt.server.ClientConnector; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; -import com.vaadin.terminal.gwt.server.RpcManager; -import com.vaadin.terminal.gwt.server.RpcTarget; -import com.vaadin.terminal.gwt.server.ServerRpcManager; import com.vaadin.ui.HasComponents; import com.vaadin.ui.UI; @@ -373,8 +368,8 @@ public abstract class AbstractClientConnector implements ClientConnector { /** * Finds a UI ancestor of this connector. <code>null</code> is returned if - * no UI ancestor is found (typically because the connector is not - * attached to a proper hierarchy). + * no UI ancestor is found (typically because the connector is not attached + * to a proper hierarchy). * * @return the UI ancestor of this connector, or <code>null</code> if none * is found. @@ -567,4 +562,59 @@ public abstract class AbstractClientConnector implements ClientConnector { public void beforeClientResponse(boolean initial) { // Do nothing by default } + + @Override + public boolean handleConnectorRequest(WrappedRequest request, + WrappedResponse response, String path) throws IOException { + String[] parts = path.split("/", 2); + String key = parts[0]; + + ConnectorResource resource = (ConnectorResource) getResource(key); + if (resource != null) { + DownloadStream stream = resource.getStream(); + stream.writeResponse(request, response); + return true; + } else { + return false; + } + } + + /** + * Gets a resource defined using {@link #setResource(String, Resource)} with + * the corresponding key. + * + * @param key + * the string identifier of the resource + * @return a resource, or <code>null</code> if there's no resource + * associated with the given key + * + * @see #setResource(String, Resource) + */ + protected Resource getResource(String key) { + return ResourceReference.getResource(getState().resources.get(key)); + } + + /** + * Registers a resource with this connector using the given key. This will + * make the URL for retrieving the resource available to the client-side + * connector using + * {@link com.vaadin.terminal.gwt.client.ui.AbstractConnector#getResourceUrl(String)} + * with the same key. + * + * @param key + * the string key to associate the resource with + * @param resource + * the resource to set, or <code>null</code> to clear a previous + * association. + */ + protected void setResource(String key, Resource resource) { + ResourceReference resourceReference = ResourceReference.create( + resource, this, key); + + if (resourceReference == null) { + getState().resources.remove(key); + } else { + getState().resources.put(key, resourceReference); + } + } } diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java index 81c497713b..2655ee9a00 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; @@ -66,6 +66,13 @@ import com.vaadin.annotations.StyleSheet; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; +import com.vaadin.server.BootstrapHandler.BootstrapContext; +import com.vaadin.server.ComponentSizeValidator.InvalidLayout; +import com.vaadin.server.RpcManager.RpcInvocationException; +import com.vaadin.server.StreamVariable.StreamingEndEvent; +import com.vaadin.server.StreamVariable.StreamingErrorEvent; +import com.vaadin.server.Terminal.ErrorEvent; +import com.vaadin.server.Terminal.ErrorListener; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Connector; import com.vaadin.shared.JavaScriptConnectorState; @@ -75,24 +82,6 @@ import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.communication.UidlValue; import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.AbstractClientConnector; -import com.vaadin.terminal.CombinedRequest; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.StreamVariable; -import com.vaadin.terminal.StreamVariable.StreamingEndEvent; -import com.vaadin.terminal.StreamVariable.StreamingErrorEvent; -import com.vaadin.terminal.Terminal.ErrorEvent; -import com.vaadin.terminal.Terminal.ErrorListener; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.VariableOwner; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; -import com.vaadin.terminal.gwt.server.BootstrapHandler.BootstrapContext; -import com.vaadin.terminal.gwt.server.ComponentSizeValidator.InvalidLayout; -import com.vaadin.terminal.gwt.server.RpcManager.RpcInvocationException; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractField; import com.vaadin.ui.Component; @@ -105,7 +94,7 @@ import com.vaadin.ui.Window; * This is a common base class for the server-side implementations of the * communication system between the client code (compiled with GWT into * JavaScript) and the server side components. Its client side counterpart is - * {@link com.vaadin.terminal.gwt.client.ApplicationConnection}. + * {@link com.vaadin.client.ApplicationConnection}. * <p> * TODO Document better! */ @@ -114,10 +103,10 @@ public abstract class AbstractCommunicationManager implements Serializable { private static final String DASHDASH = "--"; - private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler(); - private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler(); + private static final RequestHandler CONNECTOR_RESOURCE_HANDLER = new ConnectorResourceHandler(); + /** * TODO Document me! * @@ -189,8 +178,8 @@ public abstract class AbstractCommunicationManager implements Serializable { public AbstractCommunicationManager(Application application) { this.application = application; application.addRequestHandler(getBootstrapHandler()); - application.addRequestHandler(APP_RESOURCE_HANDLER); application.addRequestHandler(UNSUPPORTED_BROWSER_HANDLER); + application.addRequestHandler(CONNECTOR_RESOURCE_HANDLER); requireLocale(application.getLocale().toString()); } @@ -1342,18 +1331,18 @@ public abstract class AbstractCommunicationManager implements Serializable { private void legacyPaint(PaintTarget paintTarget, ArrayList<ClientConnector> dirtyVisibleConnectors) throws PaintException { - List<Vaadin6Component> legacyComponents = new ArrayList<Vaadin6Component>(); + List<LegacyComponent> legacyComponents = new ArrayList<LegacyComponent>(); for (Connector connector : dirtyVisibleConnectors) { // All Components that want to use paintContent must implement - // Vaadin6Component - if (connector instanceof Vaadin6Component) { - legacyComponents.add((Vaadin6Component) connector); + // LegacyComponent + if (connector instanceof LegacyComponent) { + legacyComponents.add((LegacyComponent) connector); } } sortByHierarchy((List) legacyComponents); - for (Vaadin6Component c : legacyComponents) { + for (LegacyComponent c : legacyComponents) { getLogger().fine( - "Painting Vaadin6Component " + c.getClass().getName() + "@" + "Painting LegacyComponent " + c.getClass().getName() + "@" + Integer.toHexString(c.hashCode())); paintTarget.startTag("change"); final String pid = c.getConnectorId(); diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java index 4052f5a400..d1280d29ce 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.lang.reflect.Constructor; import java.util.Iterator; @@ -22,8 +22,6 @@ import java.util.Properties; import java.util.ServiceLoader; import java.util.logging.Logger; -import com.vaadin.terminal.DeploymentConfiguration; - public abstract class AbstractDeploymentConfiguration implements DeploymentConfiguration { diff --git a/server/src/com/vaadin/terminal/AbstractErrorMessage.java b/server/src/com/vaadin/server/AbstractErrorMessage.java index 808791158a..0928ea4bd4 100644 --- a/server/src/com/vaadin/terminal/AbstractErrorMessage.java +++ b/server/src/com/vaadin/server/AbstractErrorMessage.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.PrintWriter; import java.io.StringWriter; @@ -23,7 +23,6 @@ import java.util.List; import com.vaadin.data.Buffered; import com.vaadin.data.Validator; -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; /** * Base class for component error messages. diff --git a/server/src/com/vaadin/terminal/AbstractExtension.java b/server/src/com/vaadin/server/AbstractExtension.java index 8ac0ce01e3..747caee967 100644 --- a/server/src/com/vaadin/terminal/AbstractExtension.java +++ b/server/src/com/vaadin/server/AbstractExtension.java @@ -14,9 +14,7 @@ * the License. */ -package com.vaadin.terminal; - -import com.vaadin.terminal.gwt.server.ClientConnector; +package com.vaadin.server; /** * An extension is an entity that is attached to a Component or another diff --git a/server/src/com/vaadin/terminal/AbstractJavaScriptExtension.java b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java index 1def6df697..1f67631203 100644 --- a/server/src/com/vaadin/terminal/AbstractJavaScriptExtension.java +++ b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import com.vaadin.shared.JavaScriptExtensionState; import com.vaadin.ui.JavaScriptFunction; @@ -77,8 +77,7 @@ import com.vaadin.ui.JavaScriptFunction; * functions is described bellow.</li> * <li><code>translateVaadinUri(uri)</code> - Translates a Vaadin URI to a URL * that can be used in the browser. This is just way of accessing - * {@link com.vaadin.terminal.gwt.client.ApplicationConnection#translateVaadinUri(String)} - * </li> + * {@link com.vaadin.client.ApplicationConnection#translateVaadinUri(String)}</li> * </ul> * The connector wrapper also supports these special functions: * <ul> diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java b/server/src/com/vaadin/server/AbstractStreamingEvent.java index ec2aa84947..39e43c725d 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java +++ b/server/src/com/vaadin/server/AbstractStreamingEvent.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; -import com.vaadin.terminal.StreamVariable.StreamingEvent; +import com.vaadin.server.StreamVariable.StreamingEvent; /** * Abstract base class for StreamingEvent implementations. diff --git a/server/src/com/vaadin/terminal/AbstractUIProvider.java b/server/src/com/vaadin/server/AbstractUIProvider.java index 5bb4d35b30..07b95fc713 100644 --- a/server/src/com/vaadin/terminal/AbstractUIProvider.java +++ b/server/src/com/vaadin/server/AbstractUIProvider.java @@ -14,7 +14,7 @@ * the License.
*/
-package com.vaadin.terminal;
+package com.vaadin.server;
import com.vaadin.Application;
import com.vaadin.ui.UI;
@@ -22,8 +22,8 @@ import com.vaadin.ui.UI; public abstract class AbstractUIProvider implements UIProvider {
@Override
- public UI instantiateUI(Application application,
- Class<? extends UI> type, WrappedRequest request) {
+ public UI instantiateUI(Application application, Class<? extends UI> type,
+ WrappedRequest request) {
try {
return type.newInstance();
} catch (InstantiationException e) {
diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/server/src/com/vaadin/server/AbstractWebApplicationContext.java index d857eeef4a..cf983f4c80 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java +++ b/server/src/com/vaadin/server/AbstractWebApplicationContext.java @@ -13,14 +13,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,8 +32,6 @@ import javax.servlet.http.HttpSessionBindingListener; import com.vaadin.Application; import com.vaadin.service.ApplicationContext; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.ApplicationResource; /** * Base class for web application contexts (including portlet contexts) that @@ -187,66 +182,6 @@ public abstract class AbstractWebApplicationContext implements applicationToAjaxAppMgrMap.remove(application); } - @Override - public String generateApplicationResourceURL(ApplicationResource resource, - String mapKey) { - - final String filename = resource.getFilename(); - if (filename == null) { - return ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.APP_REQUEST_PATH + mapKey + "/"; - } else { - // #7738 At least Tomcat and JBoss refuses requests containing - // encoded slashes or backslashes in URLs. Application resource URLs - // should really be passed in another way than as part of the path - // in the future. - String encodedFileName = urlEncode(filename).replace("%2F", "/") - .replace("%5C", "\\"); - return ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.APP_REQUEST_PATH + mapKey + "/" - + encodedFileName; - } - - } - - static String urlEncode(String filename) { - try { - return URLEncoder.encode(filename, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException( - "UTF-8 charset not available (\"this should never happen\")", - e); - } - } - - @Override - public boolean isApplicationResourceURL(URL context, String relativeUri) { - // If the relative uri is null, we are ready - if (relativeUri == null) { - return false; - } - - // Resolves the prefix - String prefix = relativeUri; - final int index = relativeUri.indexOf('/'); - if (index >= 0) { - prefix = relativeUri.substring(0, index); - } - - // Handles the resource requests - return (prefix.equals("APP")); - } - - @Override - public String getURLKey(URL context, String relativeUri) { - final int index = relativeUri.indexOf('/'); - final int next = relativeUri.indexOf('/', index + 1); - if (next < 0) { - return null; - } - return relativeUri.substring(index + 1, next); - } - /** * @return The total time spent servicing requests in this session. */ diff --git a/server/src/com/vaadin/terminal/gwt/server/AddonContext.java b/server/src/com/vaadin/server/AddonContext.java index 2af22c560b..b3cd5ea226 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AddonContext.java +++ b/server/src/com/vaadin/server/AddonContext.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.lang.reflect.Method; import java.util.ArrayList; @@ -24,7 +24,6 @@ import java.util.ServiceLoader; import com.vaadin.Application; import com.vaadin.event.EventRouter; -import com.vaadin.terminal.DeploymentConfiguration; import com.vaadin.tools.ReflectTools; /** @@ -35,10 +34,10 @@ import com.vaadin.tools.ReflectTools; * <p> * By default, AddonContextListeners are loaded using {@link ServiceLoader}, * which means that the file - * META-INF/services/com.vaadin.terminal.gwt.server.AddonContextListener will be - * checked for lines containing fully qualified names of classes to use. This - * behavior can however be overridden for custom deployment situations (e.g. to - * use CDI or OSGi) by overriding + * META-INF/services/com.vaadin.server.AddonContextListener will be checked for + * lines containing fully qualified names of classes to use. This behavior can + * however be overridden for custom deployment situations (e.g. to use CDI or + * OSGi) by overriding * {@link DeploymentConfiguration#getAddonContextListeners()}. * * @author Vaadin Ltd diff --git a/server/src/com/vaadin/terminal/gwt/server/AddonContextEvent.java b/server/src/com/vaadin/server/AddonContextEvent.java index 0f3900fa20..d83b1b0084 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AddonContextEvent.java +++ b/server/src/com/vaadin/server/AddonContextEvent.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventObject; diff --git a/server/src/com/vaadin/terminal/gwt/server/AddonContextListener.java b/server/src/com/vaadin/server/AddonContextListener.java index b76d233716..a5d9e8c5c9 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AddonContextListener.java +++ b/server/src/com/vaadin/server/AddonContextListener.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventListener; @@ -22,8 +22,7 @@ import java.util.EventListener; * Listener that gets notified then the {@link AddonContext} is initialized, * allowing an add-on to add listeners to various parts of the framework. In a * default configuration, add-ons can register their listeners by including a - * file named - * META-INF/services/com.vaadin.terminal.gwt.server.AddonContextListener + * file named META-INF/services/com.vaadin.server.AddonContextListener * containing the fully qualified class names of classes implementing this * interface. * diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java b/server/src/com/vaadin/server/ApplicationPortlet2.java index 743670438e..3708d8fe0d 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java +++ b/server/src/com/vaadin/server/ApplicationPortlet2.java @@ -14,13 +14,13 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import javax.portlet.PortletConfig; import javax.portlet.PortletException; import com.vaadin.Application; -import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException; +import com.vaadin.server.ServletPortletHelper.ApplicationClassException; /** * TODO Write documentation, fix JavaDoc tags. diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java b/server/src/com/vaadin/server/ApplicationServlet.java index 857c7c738c..af0cebcf86 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java +++ b/server/src/com/vaadin/server/ApplicationServlet.java @@ -14,14 +14,13 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import com.vaadin.Application; -import com.vaadin.terminal.DefaultUIProvider; -import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException; +import com.vaadin.server.ServletPortletHelper.ApplicationClassException; /** * This servlet connects a Vaadin Application to Web. diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationStartedEvent.java b/server/src/com/vaadin/server/ApplicationStartedEvent.java index 02d73884f5..d06744ae40 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationStartedEvent.java +++ b/server/src/com/vaadin/server/ApplicationStartedEvent.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventObject; diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationStartedListener.java b/server/src/com/vaadin/server/ApplicationStartedListener.java index c6976aee57..c54132d875 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationStartedListener.java +++ b/server/src/com/vaadin/server/ApplicationStartedListener.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventListener; diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapDom.java b/server/src/com/vaadin/server/BootstrapDom.java index 15210a7de5..65ee9f2761 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapDom.java +++ b/server/src/com/vaadin/server/BootstrapDom.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; public class BootstrapDom { diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapFragmentResponse.java b/server/src/com/vaadin/server/BootstrapFragmentResponse.java index 6f69086523..16f7bc653b 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapFragmentResponse.java +++ b/server/src/com/vaadin/server/BootstrapFragmentResponse.java @@ -14,14 +14,13 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.List; import org.jsoup.nodes.Node; import com.vaadin.Application; -import com.vaadin.terminal.WrappedRequest; /** * A representation of a bootstrap fragment being generated. The bootstrap diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java index 02005e8d22..280372a5e5 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java +++ b/server/src/com/vaadin/server/BootstrapHandler.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.BufferedWriter; import java.io.IOException; @@ -43,11 +43,6 @@ import com.vaadin.external.json.JSONObject; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Version; import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; import com.vaadin.ui.UI; public abstract class BootstrapHandler implements RequestHandler { diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapListener.java b/server/src/com/vaadin/server/BootstrapListener.java index d99d5b7b84..9b68df3d51 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapListener.java +++ b/server/src/com/vaadin/server/BootstrapListener.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventListener; diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapPageResponse.java b/server/src/com/vaadin/server/BootstrapPageResponse.java index 847578ef97..d6df145728 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapPageResponse.java +++ b/server/src/com/vaadin/server/BootstrapPageResponse.java @@ -14,15 +14,13 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.Map; import org.jsoup.nodes.Document; import com.vaadin.Application; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; /** * A representation of a bootstrap page being generated. The bootstrap page @@ -52,8 +50,7 @@ public class BootstrapPageResponse extends BootstrapResponse { * the application for which the bootstrap page should be * generated * @param uiId - * the generated id of the UI that will be displayed on the - * page + * the generated id of the UI that will be displayed on the page * @param document * the DOM document making up the HTML page * @param headers diff --git a/server/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java b/server/src/com/vaadin/server/BootstrapResponse.java index a422cba345..962b48dc31 100644 --- a/server/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java +++ b/server/src/com/vaadin/server/BootstrapResponse.java @@ -14,13 +14,12 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.EventObject; import com.vaadin.Application; import com.vaadin.UIRequiresMoreInformationException; -import com.vaadin.terminal.WrappedRequest; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java b/server/src/com/vaadin/server/ChangeVariablesErrorEvent.java index cb0645d94f..f208fffcef 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java +++ b/server/src/com/vaadin/server/ChangeVariablesErrorEvent.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.Map; diff --git a/server/src/com/vaadin/terminal/ClassResource.java b/server/src/com/vaadin/server/ClassResource.java index e4921f2413..2f05115fd4 100644 --- a/server/src/com/vaadin/terminal/ClassResource.java +++ b/server/src/com/vaadin/server/ClassResource.java @@ -14,12 +14,14 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import com.vaadin.Application; import com.vaadin.service.FileTypeResolver; +import com.vaadin.ui.UI; +import com.vaadin.ui.UI.LegacyWindow; /** * <code>ClassResource</code> is a named resource accessed with the class @@ -33,7 +35,7 @@ import com.vaadin.service.FileTypeResolver; * @since 3.0 */ @SuppressWarnings("serial") -public class ClassResource implements ApplicationResource, Serializable { +public class ClassResource implements ConnectorResource, Serializable { /** * Default buffer size for this stream resource. @@ -43,10 +45,10 @@ public class ClassResource implements ApplicationResource, Serializable { /** * Default cache time for this stream resource. */ - private long cacheTime = DEFAULT_CACHETIME; + private long cacheTime = DownloadStream.DEFAULT_CACHETIME; /** - * Associated class used for indetifying the source of the resource. + * Associated class used for identifying the source of the resource. */ private final Class<?> associatedClass; @@ -56,21 +58,15 @@ public class ClassResource implements ApplicationResource, Serializable { private final String resourceName; /** - * Application used for serving the class. - */ - private final Application application; - - /** * Creates a new application resource instance. The resource id is relative - * to the location of the application class. + * to the location of the UI of the component using this resource (or the + * Application if using LegacyWindow). * * @param resourceName * the Unique identifier of the resource within the application. - * @param application - * the application this resource will be added to. */ - public ClassResource(String resourceName, Application application) { - this(application.getClass(), resourceName, application); + public ClassResource(String resourceName) { + this(null, resourceName); } /** @@ -80,74 +76,62 @@ public class ClassResource implements ApplicationResource, Serializable { * the class of the which the resource is associated. * @param resourceName * the Unique identifier of the resource within the application. - * @param application - * the application this resource will be added to. */ - public ClassResource(Class<?> associatedClass, String resourceName, - Application application) { + public ClassResource(Class<?> associatedClass, String resourceName) { this.associatedClass = associatedClass; this.resourceName = resourceName; - this.application = application; - if (resourceName == null || associatedClass == null) { + if (resourceName == null) { throw new NullPointerException(); } - application.addResource(this); } /** * Gets the MIME type of this resource. * - * @see com.vaadin.terminal.Resource#getMIMEType() + * @see com.vaadin.server.Resource#getMIMEType() */ @Override public String getMIMEType() { return FileTypeResolver.getMIMEType(resourceName); } - /** - * Gets the application of this resource. - * - * @see com.vaadin.terminal.ApplicationResource#getApplication() - */ - @Override - public Application getApplication() { - return application; - } - - /** - * Gets the virtual filename for this resource. - * - * @return the file name associated to this resource. - * @see com.vaadin.terminal.ApplicationResource#getFilename() - */ @Override public String getFilename() { - int index = 0; - int next = 0; - while ((next = resourceName.indexOf('/', index)) > 0 - && next + 1 < resourceName.length()) { - index = next + 1; - } - return resourceName.substring(index); + String[] parts = resourceName.split("/"); + return parts[parts.length - 1]; } - /** - * Gets resource as stream. - * - * @see com.vaadin.terminal.ApplicationResource#getStream() - */ @Override public DownloadStream getStream() { - final DownloadStream ds = new DownloadStream( - associatedClass.getResourceAsStream(resourceName), - getMIMEType(), getFilename()); + final DownloadStream ds = new DownloadStream(getAssociatedClass() + .getResourceAsStream(resourceName), getMIMEType(), + getFilename()); ds.setBufferSize(getBufferSize()); - ds.setCacheTime(cacheTime); + ds.setCacheTime(getCacheTime()); return ds; } - /* documented in superclass */ - @Override + protected Class<?> getAssociatedClass() { + if (associatedClass == null) { + Class<? extends UI> associatedClass = UI.getCurrent().getClass(); + if (associatedClass == LegacyWindow.class) { + return Application.getCurrent().getClass(); + } + return associatedClass; + } + return associatedClass; + } + + /** + * Gets the size of the download buffer used for this resource. + * + * <p> + * If the buffer size is 0, the buffer size is decided by the terminal + * adapter. The default value is 0. + * </p> + * + * @return the size of the buffer in bytes. + */ public int getBufferSize() { return bufferSize; } @@ -157,13 +141,24 @@ public class ClassResource implements ApplicationResource, Serializable { * * @param bufferSize * the size of the buffer in bytes. + * + * @see #getBufferSize() */ public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } - /* documented in superclass */ - @Override + /** + * Gets the length of cache expiration time. + * + * <p> + * This gives the adapter the possibility cache streams sent to the client. + * The caching may be made in adapter or at the client if the client + * supports caching. Default is {@link DownloadStream#DEFAULT_CACHETIME}. + * </p> + * + * @return Cache time in milliseconds + */ public long getCacheTime() { return cacheTime; } @@ -174,7 +169,7 @@ public class ClassResource implements ApplicationResource, Serializable { * <p> * This gives the adapter the possibility cache streams sent to the client. * The caching may be made in adapter or at the client if the client - * supports caching. Zero or negavive value disbales the caching of this + * supports caching. Zero or negative value disables the caching of this * stream. * </p> * diff --git a/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/server/src/com/vaadin/server/ClientConnector.java index c2fbbe37d4..3a340c2d7d 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java +++ b/server/src/com/vaadin/server/ClientConnector.java @@ -13,8 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; +import java.io.IOException; import java.util.Collection; import java.util.List; @@ -22,8 +23,6 @@ import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; import com.vaadin.shared.Connector; import com.vaadin.shared.communication.SharedState; -import com.vaadin.terminal.AbstractClientConnector; -import com.vaadin.terminal.Extension; import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.UI; @@ -213,4 +212,30 @@ public interface ClientConnector extends Connector, RpcTarget { * if the state can not be encoded */ public JSONObject encodeState() throws JSONException; + + /** + * Handle a request directed to this connector. This can be used by + * connectors to dynamically generate a response and it is also used + * internally when serving {@link ConnectorResource}s. + * <p> + * Requests to <code>/APP/connector/[ui id]/[connector id]/</code> are + * routed to this method with the remaining part of the requested path + * available in the path parameter. + * <p> + * {@link DynamicConnectorResource} can be used to easily make an + * appropriate URL available to the client-side code. + * + * @param request + * the request that should be handled + * @param response + * the response object to which the response should be written + * @param path + * the requested relative path + * @return <code>true</code> if the request has been handled, + * <code>false</code> if no response has been written. + * @throws IOException + * if there is a problem generating a response. + */ + public boolean handleConnectorRequest(WrappedRequest request, + WrappedResponse response, String path) throws IOException; } diff --git a/server/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java b/server/src/com/vaadin/server/ClientMethodInvocation.java index 7cc5159bc0..1533222b3a 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java +++ b/server/src/com/vaadin/server/ClientMethodInvocation.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; import java.lang.reflect.Method; diff --git a/server/src/com/vaadin/terminal/CombinedRequest.java b/server/src/com/vaadin/server/CombinedRequest.java index 3d6c3c2149..c186fcc87c 100644 --- a/server/src/com/vaadin/terminal/CombinedRequest.java +++ b/server/src/com/vaadin/server/CombinedRequest.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.InputStream; @@ -28,8 +28,6 @@ import com.vaadin.Application; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; -import com.vaadin.terminal.gwt.server.WebApplicationContext; -import com.vaadin.terminal.gwt.server.WebBrowser; /** * A {@link WrappedRequest} with path and parameters from one request and diff --git a/server/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/server/src/com/vaadin/server/CommunicationManager.java index 7551e849a1..9b56e20fd4 100644 --- a/server/src/com/vaadin/terminal/gwt/server/CommunicationManager.java +++ b/server/src/com/vaadin/server/CommunicationManager.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.InputStream; import java.net.URL; @@ -23,8 +23,6 @@ import javax.servlet.ServletContext; import com.vaadin.Application; import com.vaadin.external.json.JSONException; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.WrappedRequest; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java b/server/src/com/vaadin/server/ComponentSizeValidator.java index 2349be1974..08fa150a9d 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java +++ b/server/src/com/vaadin/server/ComponentSizeValidator.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.PrintStream; import java.io.PrintWriter; @@ -28,7 +28,7 @@ import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; -import com.vaadin.terminal.Sizeable.Unit; +import com.vaadin.server.Sizeable.Unit; import com.vaadin.ui.AbstractOrderedLayout; import com.vaadin.ui.AbstractSplitPanel; import com.vaadin.ui.Component; diff --git a/server/src/com/vaadin/terminal/CompositeErrorMessage.java b/server/src/com/vaadin/server/CompositeErrorMessage.java index e86102ae3b..f51ba559eb 100644 --- a/server/src/com/vaadin/terminal/CompositeErrorMessage.java +++ b/server/src/com/vaadin/server/CompositeErrorMessage.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.util.Collection; import java.util.Iterator; diff --git a/server/src/com/vaadin/server/ConnectorResource.java b/server/src/com/vaadin/server/ConnectorResource.java new file mode 100644 index 0000000000..e696c35c0d --- /dev/null +++ b/server/src/com/vaadin/server/ConnectorResource.java @@ -0,0 +1,42 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.server; + +/** + * A resource that is served through the Connector that is using the resource. + * + * @see AbstractClientConnector#setResource(String, Resource) + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ +public interface ConnectorResource extends Resource { + public static final String CONNECTOR_REQUEST_PATH = "connector/"; + + /** + * Gets resource as stream. + */ + public DownloadStream getStream(); + + /** + * Gets the virtual filename for this resource. + * + * @return the file name associated to this resource. + */ + public String getFilename(); +} diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java new file mode 100644 index 0000000000..b988510b8e --- /dev/null +++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java @@ -0,0 +1,81 @@ +package com.vaadin.server; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletResponse; + +import com.vaadin.Application; +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.ui.UI; + +public class ConnectorResourceHandler implements RequestHandler { + // APP/connector/[uiid]/[cid]/[filename.xyz] + private static final Pattern CONNECTOR_RESOURCE_PATTERN = Pattern + .compile("^/?" + ApplicationConstants.APP_REQUEST_PATH + + ConnectorResource.CONNECTOR_REQUEST_PATH + + "(\\d+)/(\\d+)/(.*)"); + + private static Logger getLogger() { + return Logger.getLogger(ConnectorResourceHandler.class.getName()); + + } + + @Override + public boolean handleRequest(Application application, + WrappedRequest request, WrappedResponse response) + throws IOException { + String requestPath = request.getRequestPathInfo(); + if (requestPath == null) { + return false; + } + Matcher matcher = CONNECTOR_RESOURCE_PATTERN.matcher(requestPath); + if (matcher.matches()) { + String uiId = matcher.group(1); + String cid = matcher.group(2); + String key = matcher.group(3); + UI ui = application.getUIById(Integer.parseInt(uiId)); + if (ui == null) { + return error(request, response, + "Ignoring connector request for no-existent root " + + uiId); + } + + UI.setCurrent(ui); + Application.setCurrent(ui.getApplication()); + + ClientConnector connector = ui.getConnectorTracker().getConnector( + cid); + if (connector == null) { + return error(request, response, + "Ignoring connector request for no-existent connector " + + cid + " in root " + uiId); + } + + if (!connector.handleConnectorRequest(request, response, key)) { + return error(request, response, connector.getClass() + .getSimpleName() + + " (" + + connector.getConnectorId() + + ") did not handle connector request for " + key); + } + + return true; + } else { + return false; + } + } + + private static boolean error(WrappedRequest request, + WrappedResponse response, String logMessage) throws IOException { + getLogger().log(Level.WARNING, logMessage); + response.sendError(HttpServletResponse.SC_NOT_FOUND, + request.getRequestPathInfo() + " can not be found"); + + // Request handled (though not in a nice way) + return true; + } +} diff --git a/server/src/com/vaadin/terminal/gwt/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 9640216488..afb2d4dae1 100644 --- a/server/src/com/vaadin/terminal/gwt/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; /** * TODO Document me! @@ -81,7 +81,7 @@ public interface Constants { static final String WIDGETSET_DIRECTORY_PATH = "VAADIN/widgetsets/"; // Name of the default widget set, used if not specified in web.xml - static final String DEFAULT_WIDGETSET = "com.vaadin.terminal.gwt.DefaultWidgetSet"; + static final String DEFAULT_WIDGETSET = "com.vaadin.DefaultWidgetSet"; // Widget set parameter name static final String PARAMETER_WIDGETSET = "widgetset"; diff --git a/server/src/com/vaadin/terminal/DefaultUIProvider.java b/server/src/com/vaadin/server/DefaultUIProvider.java index 8713c45b31..913402c89f 100644 --- a/server/src/com/vaadin/terminal/DefaultUIProvider.java +++ b/server/src/com/vaadin/server/DefaultUIProvider.java @@ -14,7 +14,7 @@ * the License.
*/
-package com.vaadin.terminal;
+package com.vaadin.server;
import com.vaadin.Application;
import com.vaadin.UIRequiresMoreInformationException;
diff --git a/server/src/com/vaadin/terminal/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java index 0cfbdb7544..d1cbdfc499 100644 --- a/server/src/com/vaadin/terminal/DeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DeploymentConfiguration.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.util.Iterator; @@ -24,8 +24,6 @@ import javax.portlet.PortletContext; import javax.servlet.ServletContext; import com.vaadin.service.ApplicationContext; -import com.vaadin.terminal.gwt.server.AddonContext; -import com.vaadin.terminal.gwt.server.AddonContextListener; /** * Provide deployment specific settings that are required outside terminal diff --git a/server/src/com/vaadin/terminal/DownloadStream.java b/server/src/com/vaadin/server/DownloadStream.java index 30810d5da4..0c00f96832 100644 --- a/server/src/com/vaadin/terminal/DownloadStream.java +++ b/server/src/com/vaadin/server/DownloadStream.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.InputStream; @@ -26,8 +26,6 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; -import com.vaadin.terminal.gwt.server.Constants; - /** * Downloadable stream. * @@ -232,14 +230,18 @@ public class DownloadStream implements Serializable { * redirect (302 Moved temporarily) is sent instead of the contents of this * stream. * + * @param request + * the request for which the response should be written * @param response * the wrapped response to write this download stream to + * * @throws IOException * passed through from the wrapped response * * @since 7.0 */ - public void writeTo(WrappedResponse response) throws IOException { + public void writeResponse(WrappedRequest request, WrappedResponse response) + throws IOException { if (getParameter("Location") != null) { response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); response.setHeader("Location", getParameter("Location")); diff --git a/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java index 0106f466fc..3e7de5c9a2 100644 --- a/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java +++ b/server/src/com/vaadin/server/DragAndDropService.java @@ -13,8 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; +import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; import java.util.Collections; @@ -36,9 +37,6 @@ import com.vaadin.external.json.JSONObject; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.ui.dd.DragEventType; -import com.vaadin.terminal.Extension; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.VariableOwner; import com.vaadin.ui.Component; import com.vaadin.ui.UI; @@ -341,4 +339,10 @@ public class DragAndDropService implements VariableOwner, ClientConnector { // TODO Auto-generated method stub return null; } + + @Override + public boolean handleConnectorRequest(WrappedRequest request, + WrappedResponse response, String path) throws IOException { + return false; + } } diff --git a/server/src/com/vaadin/server/DynamicConnectorResource.java b/server/src/com/vaadin/server/DynamicConnectorResource.java new file mode 100644 index 0000000000..8269f261f7 --- /dev/null +++ b/server/src/com/vaadin/server/DynamicConnectorResource.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.server; + +import java.util.Collections; +import java.util.Map; + +import com.vaadin.service.FileTypeResolver; + +/** + * A resource that is served by calling + * {@link ClientConnector#handleConnectorRequest(WrappedRequest, WrappedResponse, String)} + * with appropriate parameters. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ +public class DynamicConnectorResource implements Resource { + + private final ClientConnector connector; + private final String path; + private final Map<String, String> parameters; + + /** + * Creates a DynamicConnectorResoruce for the given connector that will be + * served by calling + * {@link ClientConnector#handleConnectorRequest(WrappedRequest, WrappedResponse, String)} + * with the given path. + * + * @param connector + * the connector that should serve the resource + * @param path + * the relative path of the request + */ + public DynamicConnectorResource(ClientConnector connector, String path) { + this(connector, path, null); + } + + /** + * Creates a DynamicConnectorResoruce for the given connector that will be + * served by calling + * {@link ClientConnector#handleConnectorRequest(WrappedRequest, WrappedResponse, String)} + * with the given path and the given request parameters. + * + * @param connector + * the connector that should serve the resource + * @param path + * the relative path of the request + * @param parameters + * the parameters that should be present in the request + */ + public DynamicConnectorResource(ClientConnector connector, String path, + Map<String, String> parameters) { + this.connector = connector; + this.path = path; + this.parameters = parameters; + } + + @Override + public String getMIMEType() { + return FileTypeResolver.getMIMEType(path); + } + + public String getPath() { + return path; + } + + public ClientConnector getConnector() { + return connector; + } + + public Map<String, String> getParameters() { + if (parameters == null) { + return Collections.emptyMap(); + } else { + return Collections.unmodifiableMap(parameters); + } + } + +} diff --git a/server/src/com/vaadin/terminal/gwt/server/EncodeResult.java b/server/src/com/vaadin/server/EncodeResult.java index a62df2e632..f58c0b4810 100644 --- a/server/src/com/vaadin/terminal/gwt/server/EncodeResult.java +++ b/server/src/com/vaadin/server/EncodeResult.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; public class EncodeResult { private final Object encodedValue; diff --git a/server/src/com/vaadin/terminal/ErrorMessage.java b/server/src/com/vaadin/server/ErrorMessage.java index 15273efb6f..fcc481e826 100644 --- a/server/src/com/vaadin/terminal/ErrorMessage.java +++ b/server/src/com/vaadin/server/ErrorMessage.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/Extension.java b/server/src/com/vaadin/server/Extension.java index 87901c3c13..bb7d133e8e 100644 --- a/server/src/com/vaadin/terminal/Extension.java +++ b/server/src/com/vaadin/server/Extension.java @@ -14,9 +14,7 @@ * the License. */ -package com.vaadin.terminal; - -import com.vaadin.terminal.gwt.server.ClientConnector; +package com.vaadin.server; /** * An extension is an entity that is attached to a Component or another diff --git a/server/src/com/vaadin/terminal/ExternalResource.java b/server/src/com/vaadin/server/ExternalResource.java index d970c0934b..925b0589f3 100644 --- a/server/src/com/vaadin/terminal/ExternalResource.java +++ b/server/src/com/vaadin/server/ExternalResource.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.net.URL; @@ -108,7 +108,7 @@ public class ExternalResource implements Resource, Serializable { /** * Gets the MIME type of the resource. * - * @see com.vaadin.terminal.Resource#getMIMEType() + * @see com.vaadin.server.Resource#getMIMEType() */ @Override public String getMIMEType() { diff --git a/server/src/com/vaadin/terminal/FileResource.java b/server/src/com/vaadin/server/FileResource.java index ab8bc95ce3..fbf353362e 100644 --- a/server/src/com/vaadin/terminal/FileResource.java +++ b/server/src/com/vaadin/server/FileResource.java @@ -14,15 +14,15 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import com.vaadin.Application; +import com.vaadin.server.Terminal.ErrorEvent; import com.vaadin.service.FileTypeResolver; -import com.vaadin.terminal.Terminal.ErrorEvent; /** * <code>FileResources</code> are files or directories on local filesystem. The @@ -34,7 +34,7 @@ import com.vaadin.terminal.Terminal.ErrorEvent; * @since 3.0 */ @SuppressWarnings("serial") -public class FileResource implements ApplicationResource { +public class FileResource implements ConnectorResource { /** * Default buffer size for this stream resource. @@ -47,11 +47,6 @@ public class FileResource implements ApplicationResource { private File sourceFile; /** - * Application. - */ - private final Application application; - - /** * Default cache time for this stream resource. */ private long cacheTime = DownloadStream.DEFAULT_CACHETIME; @@ -59,18 +54,14 @@ public class FileResource implements ApplicationResource { /** * Creates a new file resource for providing given file for client * terminals. + * + * @param sourceFile + * the file that should be served. */ - public FileResource(File sourceFile, Application application) { - this.application = application; + public FileResource(File sourceFile) { setSourceFile(sourceFile); - application.addResource(this); } - /** - * Gets the resource as stream. - * - * @see com.vaadin.terminal.ApplicationResource#getStream() - */ @Override public DownloadStream getStream() { try { @@ -83,14 +74,15 @@ public class FileResource implements ApplicationResource { return ds; } catch (final FileNotFoundException e) { // Log the exception using the application error handler - getApplication().getErrorHandler().terminalError(new ErrorEvent() { + Application.getCurrent().getErrorHandler() + .terminalError(new ErrorEvent() { - @Override - public Throwable getThrowable() { - return e; - } + @Override + public Throwable getThrowable() { + return e; + } - }); + }); return null; } @@ -111,29 +103,15 @@ public class FileResource implements ApplicationResource { * @param sourceFile * the source file to set. */ - public void setSourceFile(File sourceFile) { + private void setSourceFile(File sourceFile) { this.sourceFile = sourceFile; } - /** - * @see com.vaadin.terminal.ApplicationResource#getApplication() - */ - @Override - public Application getApplication() { - return application; - } - - /** - * @see com.vaadin.terminal.ApplicationResource#getFilename() - */ @Override public String getFilename() { return sourceFile.getName(); } - /** - * @see com.vaadin.terminal.Resource#getMIMEType() - */ @Override public String getMIMEType() { return FileTypeResolver.getMIMEType(sourceFile); @@ -147,7 +125,6 @@ public class FileResource implements ApplicationResource { * * @return Cache time in milliseconds. */ - @Override public long getCacheTime() { return cacheTime; } @@ -165,8 +142,16 @@ public class FileResource implements ApplicationResource { this.cacheTime = cacheTime; } - /* documented in superclass */ - @Override + /** + * Gets the size of the download buffer used for this resource. + * + * <p> + * If the buffer size is 0, the buffer size is decided by the terminal + * adapter. The default value is 0. + * </p> + * + * @return the size of the buffer in bytes. + */ public int getBufferSize() { return bufferSize; } diff --git a/server/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java b/server/src/com/vaadin/server/GAEApplicationServlet.java index fe3d384c5c..16345edead 100644 --- a/server/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java +++ b/server/src/com/vaadin/server/GAEApplicationServlet.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -56,7 +56,7 @@ import com.vaadin.service.ApplicationContext; * <pre> * <servlet> * <servlet-name>HelloWorld</servlet-name> - * <servlet-class>com.vaadin.terminal.gwt.server.GAEApplicationServlet</servlet-class> + * <servlet-class>com.vaadin.server.GAEApplicationServlet</servlet-class> * <init-param> * <param-name>application</param-name> * <param-value>com.vaadin.demo.HelloWorld</param-value> diff --git a/server/src/com/vaadin/server/GlobalResourceHandler.java b/server/src/com/vaadin/server/GlobalResourceHandler.java new file mode 100644 index 0000000000..f3a72a0efc --- /dev/null +++ b/server/src/com/vaadin/server/GlobalResourceHandler.java @@ -0,0 +1,239 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.server; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletResponse; + +import com.vaadin.Application; +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.ui.UI; + +/** + * A {@link RequestHandler} that takes care of {@link ConnectorResource}s that + * should not be served by the connector. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ +public class GlobalResourceHandler implements RequestHandler { + private static final String LEGACY_TYPE = "legacy"; + + private static final String RESOURCE_REQUEST_PATH = "global/"; + + /** + * Used to detect when a resource is no longer used by any connector. + */ + private final Map<Resource, Set<ClientConnector>> resourceUsers = new HashMap<Resource, Set<ClientConnector>>(); + /** + * Used to find the resources that might not be needed any more when a + * connector is unregistered. + */ + private final Map<ClientConnector, Set<Resource>> usedResources = new HashMap<ClientConnector, Set<Resource>>(); + + private final Map<ConnectorResource, String> legacyResourceKeys = new HashMap<ConnectorResource, String>(); + private final Map<String, ConnectorResource> legacyResources = new HashMap<String, ConnectorResource>(); + private int nextLegacyId = 0; + + // APP/global/[uiid]/[type]/[id] + private final Matcher matcher = Pattern.compile( + "^/?" + ApplicationConstants.APP_REQUEST_PATH + + RESOURCE_REQUEST_PATH + "(\\d+)/(([^/]+)(/.*))").matcher( + ""); + + @Override + public boolean handleRequest(Application application, + WrappedRequest request, WrappedResponse response) + throws IOException { + String pathInfo = request.getRequestPathInfo(); + if (pathInfo == null) { + return false; + } + + matcher.reset(pathInfo); + if (!matcher.matches()) { + return false; + } + + String uiid = matcher.group(1); + String type = matcher.group(3); + String key = matcher.group(2); + + // Allow GCing pathInfo string + matcher.reset(); + + if (key == null) { + return error(request, response, pathInfo + + " is not a valid global resource path"); + } + + UI ui = application.getUIById(Integer.parseInt(uiid)); + if (ui == null) { + return error(request, response, "No UI found for id " + uiid); + } + UI.setCurrent(ui); + + ConnectorResource resource; + if (LEGACY_TYPE.equals(type)) { + resource = legacyResources.get(key); + } else { + return error(request, response, "Unknown global resource type " + + type + " in requested path " + pathInfo); + } + + if (resource == null) { + return error(request, response, "Global resource " + key + + " not found"); + } + + DownloadStream stream = resource.getStream(); + if (stream == null) { + return error(request, response, "Resource " + resource + + " didn't produce any stream."); + } + + stream.writeResponse(request, response); + return true; + } + + /** + * Registers a resource to be served with a global URL. + * <p> + * A {@link ConnectorResource} registered for a {@link Vaadin6Component} + * will be set to be served with a global URL. Other resource types will be + * ignored and thus not served by this handler. + * + * @param resource + * the resource to register + * @param ownerConnector + * the connector to which the resource belongs + */ + public void register(Resource resource, ClientConnector ownerConnector) { + if (resource instanceof ConnectorResource) { + if (!(ownerConnector instanceof LegacyComponent)) { + throw new IllegalArgumentException( + "A normal ConnectorResource can only be registered for legacy components."); + } + ConnectorResource connectorResource = (ConnectorResource) resource; + if (!legacyResourceKeys.containsKey(resource)) { + String uri = LEGACY_TYPE + '/' + + Integer.toString(nextLegacyId++); + String filename = connectorResource.getFilename(); + if (filename != null && !filename.isEmpty()) { + uri += '/' + filename; + } + legacyResourceKeys.put(connectorResource, uri); + legacyResources.put(uri, connectorResource); + registerResourceUsage(connectorResource, ownerConnector); + } + } + } + + private void unregisterResource(Resource resource) { + String oldUri = legacyResourceKeys.remove(resource); + if (oldUri != null) { + legacyResources.remove(oldUri); + } + } + + private void registerResourceUsage(Resource resource, + ClientConnector connector) { + ensureInSet(resourceUsers, resource, connector); + ensureInSet(usedResources, connector, resource); + } + + private <K, V> void ensureInSet(Map<K, Set<V>> map, K key, V value) { + Set<V> set = map.get(key); + if (set == null) { + set = new HashSet<V>(); + map.put(key, set); + } + set.add(value); + } + + /** + * Gets a global URI for a resource if it's registered with this handler. + * + * @param connector + * the connector for which the uri should be generated. + * @param resource + * the resource for which the uri should be generated. + * @return an URI string, or <code>null</code> if the resource is not + * registered. + */ + public String getUri(ClientConnector connector, ConnectorResource resource) { + // app://APP/global/[ui]/[type]/[id] + String uri = legacyResourceKeys.get(resource); + if (uri != null && !uri.isEmpty()) { + return ApplicationConstants.APP_PROTOCOL_PREFIX + + ApplicationConstants.APP_REQUEST_PATH + + RESOURCE_REQUEST_PATH + connector.getUI().getUIId() + '/' + + uri; + } else { + return null; + } + } + + /** + * Notifies this handler that resources registered for the given connector + * can be released. + * + * @param connector + * the connector for which any registered resources can be + * released. + */ + public void unregisterConnector(ClientConnector connector) { + Set<Resource> set = usedResources.remove(connector); + if (set == null) { + return; + } + + for (Resource resource : set) { + Set<ClientConnector> users = resourceUsers.get(resource); + users.remove(connector); + if (users.isEmpty()) { + resourceUsers.remove(resource); + unregisterResource(resource); + } + } + } + + private static Logger getLogger() { + return Logger.getLogger(GlobalResourceHandler.class.getName()); + } + + private static boolean error(WrappedRequest request, + WrappedResponse response, String logMessage) throws IOException { + getLogger().log(Level.WARNING, logMessage); + response.sendError(HttpServletResponse.SC_NOT_FOUND, + request.getRequestPathInfo() + " can not be found"); + + // Request handled (though not in a nice way) + return true; + } + +} diff --git a/server/src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java b/server/src/com/vaadin/server/HttpServletRequestListener.java index 22467a0c1a..1f9f633c17 100644 --- a/server/src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java +++ b/server/src/com/vaadin/server/HttpServletRequestListener.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; @@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletResponse; import com.vaadin.Application; import com.vaadin.service.ApplicationContext.TransactionListener; -import com.vaadin.terminal.Terminal; /** * {@link Application} that implements this interface gets notified of request diff --git a/server/src/com/vaadin/terminal/JavaScriptCallbackHelper.java b/server/src/com/vaadin/server/JavaScriptCallbackHelper.java index f0063a8708..19b19ce824 100644 --- a/server/src/com/vaadin/terminal/JavaScriptCallbackHelper.java +++ b/server/src/com/vaadin/server/JavaScriptCallbackHelper.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.lang.reflect.Method; @@ -36,7 +36,7 @@ import com.vaadin.ui.JavaScriptFunction; * Internal helper class used to implement functionality common to * {@link AbstractJavaScriptComponent} and {@link AbstractJavaScriptExtension}. * Corresponding support in client-side code is in - * {@link com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper}. + * {@link com.vaadin.client.JavaScriptConnectorHelper}. * <p> * You should most likely no use this class directly. * diff --git a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java index 3ba52a4e91..689ffe034e 100644 --- a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/server/src/com/vaadin/server/JsonCodec.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.beans.IntrospectionException; import java.beans.Introspector; diff --git a/server/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/server/src/com/vaadin/server/JsonPaintTarget.java index cfc3cc7e7e..b193c47528 100644 --- a/server/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java +++ b/server/src/com/vaadin/server/JsonPaintTarget.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.PrintWriter; import java.io.Serializable; @@ -27,11 +27,6 @@ import java.util.Stack; import java.util.Vector; import java.util.logging.Logger; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.StreamVariable; -import com.vaadin.terminal.VariableOwner; import com.vaadin.ui.Alignment; import com.vaadin.ui.Component; import com.vaadin.ui.CustomLayout; @@ -349,7 +344,12 @@ public class JsonPaintTarget implements PaintTarget { if (value == null) { throw new NullPointerException(); } - ResourceReference reference = ResourceReference.create(value); + ClientConnector ownerConnector = openPaintables.peek(); + ownerConnector.getUI().getApplication().getGlobalResourceHandler(true) + .register(value, ownerConnector); + + ResourceReference reference = ResourceReference.create(value, + ownerConnector, name); addAttribute(name, reference.getURL()); } @@ -589,8 +589,7 @@ public class JsonPaintTarget implements PaintTarget { * @throws PaintException * if the paint operation failed. * - * @see com.vaadin.terminal.PaintTarget#addXMLSection(String, String, - * String) + * @see com.vaadin.server.PaintTarget#addXMLSection(String, String, String) */ @Override diff --git a/server/src/com/vaadin/terminal/KeyMapper.java b/server/src/com/vaadin/server/KeyMapper.java index cf54af545f..86714cfc66 100644 --- a/server/src/com/vaadin/terminal/KeyMapper.java +++ b/server/src/com/vaadin/server/KeyMapper.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.util.HashMap; diff --git a/server/src/com/vaadin/terminal/Vaadin6Component.java b/server/src/com/vaadin/server/LegacyComponent.java index eb169c90f9..b6e620f920 100644 --- a/server/src/com/vaadin/terminal/Vaadin6Component.java +++ b/server/src/com/vaadin/server/LegacyComponent.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.util.EventListener; @@ -29,7 +29,7 @@ import com.vaadin.ui.Component; * @since 7.0.0 * */ -public interface Vaadin6Component extends VariableOwner, Component, +public interface LegacyComponent extends VariableOwner, Component, EventListener { /** @@ -55,11 +55,11 @@ public interface Vaadin6Component extends VariableOwner, Component, /** * (non-Javadoc) {@inheritDoc} * <p> - * For a Vaadin6Component, markAsDirty will also cause + * For a LegacyComponent, markAsDirty will also cause * {@link #paintContent(PaintTarget)} to be called before sending changes to * the client. * - * @see com.vaadin.terminal.gwt.server.ClientConnector#markAsDirty() + * @see com.vaadin.server.ClientConnector#markAsDirty() */ @Override public void markAsDirty(); diff --git a/server/src/com/vaadin/terminal/LegacyPaint.java b/server/src/com/vaadin/server/LegacyPaint.java index 3db0f52079..c39e0e8247 100644 --- a/server/src/com/vaadin/terminal/LegacyPaint.java +++ b/server/src/com/vaadin/server/LegacyPaint.java @@ -13,11 +13,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; -import com.vaadin.terminal.PaintTarget.PaintStatus; +import com.vaadin.server.PaintTarget.PaintStatus; import com.vaadin.ui.Component; import com.vaadin.ui.HasComponents; @@ -61,8 +61,8 @@ public class LegacyPaint implements Serializable { target.addAttribute("cached", true); } else { // Paint the contents of the component - if (component instanceof Vaadin6Component) { - ((Vaadin6Component) component).paintContent(target); + if (component instanceof LegacyComponent) { + ((LegacyComponent) component).paintContent(target); } } diff --git a/server/src/com/vaadin/terminal/gwt/server/NoInputStreamException.java b/server/src/com/vaadin/server/NoInputStreamException.java index 445d8c3cb1..acd148864a 100644 --- a/server/src/com/vaadin/terminal/gwt/server/NoInputStreamException.java +++ b/server/src/com/vaadin/server/NoInputStreamException.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; @SuppressWarnings("serial") public class NoInputStreamException extends Exception { diff --git a/server/src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java b/server/src/com/vaadin/server/NoOutputStreamException.java index fc9b3dee8a..8900079b4b 100644 --- a/server/src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java +++ b/server/src/com/vaadin/server/NoOutputStreamException.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; @SuppressWarnings("serial") public class NoOutputStreamException extends Exception { diff --git a/server/src/com/vaadin/terminal/Page.java b/server/src/com/vaadin/server/Page.java index 66ef7da296..b8fdae6cfb 100644 --- a/server/src/com/vaadin/terminal/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.lang.reflect.Method; @@ -24,12 +24,10 @@ import java.util.LinkedList; import java.util.List; import com.vaadin.event.EventRouter; +import com.vaadin.server.WrappedRequest.BrowserDetails; import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.ui.PageClientRpc; import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.WrappedRequest.BrowserDetails; -import com.vaadin.terminal.gwt.server.WebApplicationContext; -import com.vaadin.terminal.gwt.server.WebBrowser; import com.vaadin.tools.ReflectTools; import com.vaadin.ui.JavaScript; import com.vaadin.ui.Notification; @@ -303,17 +301,36 @@ public class Page implements Serializable { } } - public void addListener(Page.FragmentChangedListener listener) { + public void addFragmentChangedListener(Page.FragmentChangedListener listener) { addListener(FragmentChangedEvent.class, listener, FRAGMENT_CHANGED_METHOD); } - public void removeListener(Page.FragmentChangedListener listener) { + /** + * @deprecated Since 7.0, replaced by + * {@link #addFragmentChangedListener(FragmentChangedListener)} + **/ + @Deprecated + public void addListener(Page.FragmentChangedListener listener) { + addFragmentChangedListener(listener); + } + + public void removeFragmentChangedListener( + Page.FragmentChangedListener listener) { removeListener(FragmentChangedEvent.class, listener, FRAGMENT_CHANGED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFragmentChangedListener(FragmentChangedListener)} + **/ + @Deprecated + public void removeListener(Page.FragmentChangedListener listener) { + removeFragmentChangedListener(listener); + } + + /** * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent} * * @param newFragment @@ -400,8 +417,8 @@ public class Page implements Serializable { /** * Adds a new {@link BrowserWindowResizeListener} to this uI. The listener - * will be notified whenever the browser window within which this uI - * resides is resized. + * will be notified whenever the browser window within which this uI resides + * is resized. * * @param resizeListener * the listener to add @@ -409,25 +426,45 @@ public class Page implements Serializable { * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent) * @see #setResizeLazy(boolean) */ - public void addListener(BrowserWindowResizeListener resizeListener) { + public void addBrowserWindowResizeListener( + BrowserWindowResizeListener resizeListener) { addListener(BrowserWindowResizeEvent.class, resizeListener, BROWSWER_RESIZE_METHOD); } /** - * Removes a {@link BrowserWindowResizeListener} from this uI. The - * listener will no longer be notified when the browser window is resized. + * @deprecated Since 7.0, replaced by + * {@link #addBrowserWindowResizeListener(BrowserWindowResizeListener)} + **/ + @Deprecated + public void addListener(BrowserWindowResizeListener resizeListener) { + addBrowserWindowResizeListener(resizeListener); + } + + /** + * Removes a {@link BrowserWindowResizeListener} from this UI. The listener + * will no longer be notified when the browser window is resized. * * @param resizeListener * the listener to remove */ - public void removeListener(BrowserWindowResizeListener resizeListener) { + public void removeBrowserWindowResizeListener( + BrowserWindowResizeListener resizeListener) { removeListener(BrowserWindowResizeEvent.class, resizeListener, BROWSWER_RESIZE_METHOD); } /** - * Gets the last known height of the browser window in which this uI + * @deprecated Since 7.0, replaced by + * {@link #removeBrowserWindowResizeListener(BrowserWindowResizeListener)} + **/ + @Deprecated + public void removeListener(BrowserWindowResizeListener resizeListener) { + removeBrowserWindowResizeListener(resizeListener); + } + + /** + * Gets the last known height of the browser window in which this UI * resides. * * @return the browser window height in pixels @@ -437,8 +474,7 @@ public class Page implements Serializable { } /** - * Gets the last known width of the browser window in which this uI - * resides. + * Gets the last known width of the browser window in which this uI resides. * * @return the browser window width in pixels */ @@ -515,8 +551,8 @@ public class Page implements Serializable { } /** - * Opens the given resource in this uI. The contents of this UI is - * replaced by the {@code Resource}. + * Opens the given resource in this uI. The contents of this UI is replaced + * by the {@code Resource}. * * @param resource * the resource to show in this uI diff --git a/server/src/com/vaadin/terminal/PaintException.java b/server/src/com/vaadin/server/PaintException.java index dd5752653a..5d6f7b1d58 100644 --- a/server/src/com/vaadin/terminal/PaintException.java +++ b/server/src/com/vaadin/server/PaintException.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/PaintTarget.java b/server/src/com/vaadin/server/PaintTarget.java index 5ccca8a8f0..268523f92f 100644 --- a/server/src/com/vaadin/terminal/PaintTarget.java +++ b/server/src/com/vaadin/server/PaintTarget.java @@ -14,13 +14,12 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.util.Map; -import com.vaadin.terminal.StreamVariable.StreamingStartEvent; -import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.server.StreamVariable.StreamingStartEvent; import com.vaadin.ui.Component; /** @@ -194,7 +193,7 @@ public interface PaintTarget extends Serializable { * <p> * The urls in UIDL message may use Vaadin specific protocol. Before * actually using the urls on the client side, they should be passed via - * {@link com.vaadin.terminal.gwt.client.ApplicationConnection#translateVaadinUri(String)}. + * {@link com.vaadin.client.ApplicationConnection#translateVaadinUri(String)}. * <p> * Note that in current terminal implementation StreamVariables are cleaned * from the terminal only when: diff --git a/server/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/server/src/com/vaadin/server/PortletApplicationContext2.java index 3e0f8d6b99..aca80f9c17 100644 --- a/server/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java +++ b/server/src/com/vaadin/server/PortletApplicationContext2.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.File; import java.io.Serializable; @@ -45,7 +45,6 @@ import javax.servlet.http.HttpSessionBindingListener; import javax.xml.namespace.QName; import com.vaadin.Application; -import com.vaadin.terminal.ExternalResource; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java b/server/src/com/vaadin/server/PortletCommunicationManager.java index e127425786..f7d9371022 100644 --- a/server/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java +++ b/server/src/com/vaadin/server/PortletCommunicationManager.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.IOException; import java.io.InputStream; @@ -30,10 +30,6 @@ import com.vaadin.Application; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java b/server/src/com/vaadin/server/PortletRequestListener.java index f7b6421e11..35f2a946c5 100644 --- a/server/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java +++ b/server/src/com/vaadin/server/PortletRequestListener.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; @@ -23,7 +23,6 @@ import javax.servlet.Filter; import com.vaadin.Application; import com.vaadin.service.ApplicationContext.TransactionListener; -import com.vaadin.terminal.Terminal; /** * An {@link Application} that implements this interface gets notified of diff --git a/server/src/com/vaadin/terminal/RequestHandler.java b/server/src/com/vaadin/server/RequestHandler.java index 2ea02487b1..fcc506cc54 100644 --- a/server/src/com/vaadin/terminal/RequestHandler.java +++ b/server/src/com/vaadin/server/RequestHandler.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/gwt/server/RequestTimer.java b/server/src/com/vaadin/server/RequestTimer.java index e3e0dc0106..1dfe24f23b 100644 --- a/server/src/com/vaadin/terminal/gwt/server/RequestTimer.java +++ b/server/src/com/vaadin/server/RequestTimer.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/Resource.java b/server/src/com/vaadin/server/Resource.java index 27adb16869..fa1e040929 100644 --- a/server/src/com/vaadin/terminal/Resource.java +++ b/server/src/com/vaadin/server/Resource.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/server/ResourceReference.java b/server/src/com/vaadin/server/ResourceReference.java new file mode 100644 index 0000000000..098fb6c3e4 --- /dev/null +++ b/server/src/com/vaadin/server/ResourceReference.java @@ -0,0 +1,147 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.server; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map.Entry; +import java.util.Set; + +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.communication.URLReference; + +public class ResourceReference extends URLReference { + + private final Resource resource; + private final ClientConnector connector; + private final String key; + + public ResourceReference(Resource resource, ClientConnector connector, + String key) { + this.resource = resource; + this.connector = connector; + this.key = key; + } + + public Resource getResource() { + return resource; + } + + @Override + public String getURL() { + if (resource instanceof ExternalResource) { + return ((ExternalResource) resource).getURL(); + } else if (resource instanceof DynamicConnectorResource) { + DynamicConnectorResource dcr = (DynamicConnectorResource) resource; + + String filename = dcr.getPath(); + StringBuilder builder = new StringBuilder(getConnectorResourceBase( + filename, dcr.getConnector())); + + Set<Entry<String, String>> entrySet = dcr.getParameters() + .entrySet(); + boolean first = true; + for (Entry<String, String> entry : entrySet) { + String key = entry.getKey(); + String value = entry.getValue(); + if (first) { + builder.append('?'); + first = false; + } else { + builder.append('&'); + } + // TODO URL encode!!! + builder.append(key).append('=').append(value); + } + return builder.toString(); + } else if (resource instanceof ConnectorResource) { + ConnectorResource connectorResource = (ConnectorResource) resource; + + GlobalResourceHandler globalResourceHandler = connector.getUI() + .getApplication().getGlobalResourceHandler(false); + if (globalResourceHandler != null) { + String uri = globalResourceHandler.getUri(connector, + connectorResource); + if (uri != null && !uri.isEmpty()) { + return uri; + } + } + + // app://APP/connector/[uiid]/[cid]/[key]/[filename] + String prefix = key; + String filename = connectorResource.getFilename(); + if (filename != null && !filename.isEmpty()) { + prefix += '/' + filename; + } + String uri = getConnectorResourceBase(prefix, connector); + return uri; + } else if (resource instanceof ThemeResource) { + final String uri = "theme://" + + ((ThemeResource) resource).getResourceId(); + return uri; + } else { + throw new RuntimeException(getClass().getSimpleName() + + " does not support resources of type: " + + resource.getClass().getName()); + } + + } + + private static String getConnectorResourceBase(String filename, + ClientConnector connector) { + String uri = ApplicationConstants.APP_PROTOCOL_PREFIX + + ApplicationConstants.APP_REQUEST_PATH + + ConnectorResource.CONNECTOR_REQUEST_PATH + + connector.getUI().getUIId() + '/' + + connector.getConnectorId() + '/' + encodeFileName(filename); + return uri; + } + + public static String encodeFileName(String filename) { + // #7738 At least Tomcat and JBoss refuses requests containing + // encoded slashes or backslashes in URLs. Application resource URLs + // should really be passed in another way than as part of the path + // in the future. + return urlEncode(filename).replace("%2F", "/").replace("%5C", "\\"); + } + + static String urlEncode(String filename) { + try { + return URLEncoder.encode(filename, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException( + "UTF-8 charset not available (\"this should never happen\")", + e); + } + } + + public static ResourceReference create(Resource resource, + ClientConnector connector, String key) { + if (resource == null) { + return null; + } else { + return new ResourceReference(resource, connector, key); + } + } + + public static Resource getResource(URLReference reference) { + if (reference == null) { + return null; + } + assert reference instanceof ResourceReference; + return ((ResourceReference) reference).getResource(); + } +} diff --git a/server/src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java b/server/src/com/vaadin/server/RestrictedRenderResponse.java index 1e23a48388..6923a042d6 100644 --- a/server/src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java +++ b/server/src/com/vaadin/server/RestrictedRenderResponse.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.IOException; import java.io.OutputStream; diff --git a/server/src/com/vaadin/terminal/gwt/server/RpcManager.java b/server/src/com/vaadin/server/RpcManager.java index 4d1e0fc152..bb1c116388 100644 --- a/server/src/com/vaadin/terminal/gwt/server/RpcManager.java +++ b/server/src/com/vaadin/server/RpcManager.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/gwt/server/RpcTarget.java b/server/src/com/vaadin/server/RpcTarget.java index 1a3cf28fcc..c491707995 100644 --- a/server/src/com/vaadin/terminal/gwt/server/RpcTarget.java +++ b/server/src/com/vaadin/server/RpcTarget.java @@ -14,12 +14,10 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; -import com.vaadin.terminal.VariableOwner; - /** * Marker interface for server side classes that can receive RPC calls. * diff --git a/server/src/com/vaadin/terminal/Scrollable.java b/server/src/com/vaadin/server/Scrollable.java index 641b20ab34..ca89d598c5 100644 --- a/server/src/com/vaadin/terminal/Scrollable.java +++ b/server/src/com/vaadin/server/Scrollable.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java b/server/src/com/vaadin/server/ServerRpcManager.java index 9db6c20f00..92e4d24240 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java +++ b/server/src/com/vaadin/server/ServerRpcManager.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; diff --git a/server/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java b/server/src/com/vaadin/server/ServerRpcMethodInvocation.java index 060fb686d4..761db687bb 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java +++ b/server/src/com/vaadin/server/ServerRpcMethodInvocation.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.lang.reflect.Method; import java.util.Map; diff --git a/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java index 1d35785a57..cce98ab925 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java +++ b/server/src/com/vaadin/server/ServletPortletHelper.java @@ -1,11 +1,9 @@ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.Serializable; import com.vaadin.Application; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.WrappedRequest; import com.vaadin.ui.UI; /* diff --git a/server/src/com/vaadin/terminal/gwt/server/SessionExpiredException.java b/server/src/com/vaadin/server/SessionExpiredException.java index 05e85c1f72..1e93fbf4ee 100644 --- a/server/src/com/vaadin/terminal/gwt/server/SessionExpiredException.java +++ b/server/src/com/vaadin/server/SessionExpiredException.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; @SuppressWarnings("serial") public class SessionExpiredException extends Exception { diff --git a/server/src/com/vaadin/terminal/Sizeable.java b/server/src/com/vaadin/server/Sizeable.java index d8d0b0e043..36562a059d 100644 --- a/server/src/com/vaadin/terminal/Sizeable.java +++ b/server/src/com/vaadin/server/Sizeable.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/StreamResource.java b/server/src/com/vaadin/server/StreamResource.java index bbb58c71e2..26514c9353 100644 --- a/server/src/com/vaadin/terminal/StreamResource.java +++ b/server/src/com/vaadin/server/StreamResource.java @@ -14,12 +14,11 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.InputStream; import java.io.Serializable; -import com.vaadin.Application; import com.vaadin.service.FileTypeResolver; /** @@ -32,7 +31,7 @@ import com.vaadin.service.FileTypeResolver; * @since 3.0 */ @SuppressWarnings("serial") -public class StreamResource implements ApplicationResource { +public class StreamResource implements ConnectorResource { /** * Source stream the downloaded content is fetched from. @@ -50,11 +49,6 @@ public class StreamResource implements ApplicationResource { private String filename; /** - * Application. - */ - private final Application application; - - /** * Default buffer size for this stream resource. */ private int bufferSize = 0; @@ -62,7 +56,7 @@ public class StreamResource implements ApplicationResource { /** * Default cache time for this stream resource. */ - private long cacheTime = DEFAULT_CACHETIME; + private long cacheTime = DownloadStream.DEFAULT_CACHETIME; /** * Creates a new stream resource for downloading from stream. @@ -74,20 +68,13 @@ public class StreamResource implements ApplicationResource { * @param application * the Application object. */ - public StreamResource(StreamSource streamSource, String filename, - Application application) { - - this.application = application; + public StreamResource(StreamSource streamSource, String filename) { setFilename(filename); setStreamSource(streamSource); - - // Register to application - application.addResource(this); - } /** - * @see com.vaadin.terminal.Resource#getMIMEType() + * @see com.vaadin.server.Resource#getMIMEType() */ @Override public String getMIMEType() { @@ -149,17 +136,6 @@ public class StreamResource implements ApplicationResource { this.filename = filename; } - /** - * @see com.vaadin.terminal.ApplicationResource#getApplication() - */ - @Override - public Application getApplication() { - return application; - } - - /** - * @see com.vaadin.terminal.ApplicationResource#getStream() - */ @Override public DownloadStream getStream() { final StreamSource ss = getStreamSource(); @@ -187,8 +163,16 @@ public class StreamResource implements ApplicationResource { public InputStream getStream(); } - /* documented in superclass */ - @Override + /** + * Gets the size of the download buffer used for this resource. + * + * <p> + * If the buffer size is 0, the buffer size is decided by the terminal + * adapter. The default value is 0. + * </p> + * + * @return the size of the buffer in bytes. + */ public int getBufferSize() { return bufferSize; } @@ -203,8 +187,14 @@ public class StreamResource implements ApplicationResource { this.bufferSize = bufferSize; } - /* documented in superclass */ - @Override + /** + * Gets the length of cache expiration time. This gives the adapter the + * possibility cache streams sent to the client. The caching may be made in + * adapter or at the client if the client supports caching. Default is + * <code>DownloadStream.DEFAULT_CACHETIME</code>. + * + * @return Cache time in milliseconds. + */ public long getCacheTime() { return cacheTime; } @@ -227,4 +217,29 @@ public class StreamResource implements ApplicationResource { this.cacheTime = cacheTime; } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof StreamResource) { + StreamResource that = (StreamResource) obj; + return getStreamSource().equals(that.getStreamSource()) + && getMIMEType().equals(that.getMIMEType()) + && String.valueOf(getFilename()).equals( + String.valueOf(that.getFilename())) + && getBufferSize() == that.getBufferSize() + && getCacheTime() == that.getCacheTime(); + } else { + return false; + } + } + + @Override + public int hashCode() { + return (int) (getStreamSource().hashCode() + 37 + * getMIMEType().hashCode() + 37 ^ 2 + * String.valueOf(getFilename()).hashCode() + 37 ^ 3 + * getBufferSize() + 37 ^ 4 * getCacheTime()); + } + } diff --git a/server/src/com/vaadin/terminal/StreamVariable.java b/server/src/com/vaadin/server/StreamVariable.java index 53f398f09c..f289e7612a 100644 --- a/server/src/com/vaadin/terminal/StreamVariable.java +++ b/server/src/com/vaadin/server/StreamVariable.java @@ -13,15 +13,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.OutputStream; import java.io.Serializable; import com.vaadin.Application; -import com.vaadin.terminal.StreamVariable.StreamingEndEvent; -import com.vaadin.terminal.StreamVariable.StreamingErrorEvent; -import com.vaadin.terminal.StreamVariable.StreamingStartEvent; +import com.vaadin.server.StreamVariable.StreamingEndEvent; +import com.vaadin.server.StreamVariable.StreamingErrorEvent; +import com.vaadin.server.StreamVariable.StreamingStartEvent; /** * StreamVariable is a special kind of variable whose value is streamed to an @@ -152,7 +152,7 @@ public interface StreamVariable extends Serializable { * the streaming ended before the end of the input. The streaming may fail * due an interruption by {@link } or due an other unknown exception in * communication. In the latter case the exception is also passed to - * {@link Application#terminalError(com.vaadin.terminal.Terminal.ErrorEvent)} + * {@link Application#terminalError(com.vaadin.server.Terminal.ErrorEvent)} * . */ public interface StreamingErrorEvent extends StreamingEvent { diff --git a/server/src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java b/server/src/com/vaadin/server/StreamingEndEventImpl.java index 6bc9f8fbd9..0b97989230 100644 --- a/server/src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java +++ b/server/src/com/vaadin/server/StreamingEndEventImpl.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; -import com.vaadin.terminal.StreamVariable.StreamingEndEvent; +import com.vaadin.server.StreamVariable.StreamingEndEvent; @SuppressWarnings("serial") final class StreamingEndEventImpl extends AbstractStreamingEvent implements diff --git a/server/src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java b/server/src/com/vaadin/server/StreamingErrorEventImpl.java index cf9339d676..b892f5d386 100644 --- a/server/src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java +++ b/server/src/com/vaadin/server/StreamingErrorEventImpl.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; -import com.vaadin.terminal.StreamVariable.StreamingErrorEvent; +import com.vaadin.server.StreamVariable.StreamingErrorEvent; @SuppressWarnings("serial") final class StreamingErrorEventImpl extends AbstractStreamingEvent implements diff --git a/server/src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java b/server/src/com/vaadin/server/StreamingProgressEventImpl.java index bcb114db60..ae665a24e8 100644 --- a/server/src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java +++ b/server/src/com/vaadin/server/StreamingProgressEventImpl.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; -import com.vaadin.terminal.StreamVariable.StreamingProgressEvent; +import com.vaadin.server.StreamVariable.StreamingProgressEvent; @SuppressWarnings("serial") final class StreamingProgressEventImpl extends AbstractStreamingEvent implements diff --git a/server/src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java b/server/src/com/vaadin/server/StreamingStartEventImpl.java index 07ff6cf7b1..5c9b215877 100644 --- a/server/src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java +++ b/server/src/com/vaadin/server/StreamingStartEventImpl.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; -import com.vaadin.terminal.StreamVariable.StreamingStartEvent; +import com.vaadin.server.StreamVariable.StreamingStartEvent; @SuppressWarnings("serial") final class StreamingStartEventImpl extends AbstractStreamingEvent implements diff --git a/server/src/com/vaadin/terminal/SystemError.java b/server/src/com/vaadin/server/SystemError.java index c4cb7eef0c..5d1426e87c 100644 --- a/server/src/com/vaadin/terminal/SystemError.java +++ b/server/src/com/vaadin/server/SystemError.java @@ -14,9 +14,7 @@ * the License. */ -package com.vaadin.terminal; - -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; +package com.vaadin.server; /** * <code>SystemError</code> is an error message for a problem caused by error in diff --git a/server/src/com/vaadin/terminal/gwt/server/SystemMessageException.java b/server/src/com/vaadin/server/SystemMessageException.java index 5575bcb618..9c37d61424 100644 --- a/server/src/com/vaadin/terminal/gwt/server/SystemMessageException.java +++ b/server/src/com/vaadin/server/SystemMessageException.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; @SuppressWarnings("serial") public class SystemMessageException extends RuntimeException { diff --git a/server/src/com/vaadin/terminal/Terminal.java b/server/src/com/vaadin/server/Terminal.java index a02bcb50bb..265668aa42 100644 --- a/server/src/com/vaadin/terminal/Terminal.java +++ b/server/src/com/vaadin/server/Terminal.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; diff --git a/server/src/com/vaadin/terminal/ThemeResource.java b/server/src/com/vaadin/server/ThemeResource.java index 61fe157ee6..7ae0bab828 100644 --- a/server/src/com/vaadin/terminal/ThemeResource.java +++ b/server/src/com/vaadin/server/ThemeResource.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import com.vaadin.service.FileTypeResolver; @@ -97,7 +97,7 @@ public class ThemeResource implements Resource { } /** - * @see com.vaadin.terminal.Resource#getMIMEType() + * @see com.vaadin.server.Resource#getMIMEType() */ @Override public String getMIMEType() { diff --git a/server/src/com/vaadin/terminal/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java index 27b63fbcac..f262a3e225 100644 --- a/server/src/com/vaadin/terminal/UIProvider.java +++ b/server/src/com/vaadin/server/UIProvider.java @@ -14,7 +14,7 @@ * the License.
*/
-package com.vaadin.terminal;
+package com.vaadin.server;
import com.vaadin.Application;
import com.vaadin.UIRequiresMoreInformationException;
@@ -24,6 +24,6 @@ public interface UIProvider { public Class<? extends UI> getUIClass(Application application,
WrappedRequest request) throws UIRequiresMoreInformationException;
- public UI instantiateUI(Application application,
- Class<? extends UI> type, WrappedRequest request);
+ public UI instantiateUI(Application application, Class<? extends UI> type,
+ WrappedRequest request);
}
diff --git a/server/src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java b/server/src/com/vaadin/server/UnsupportedBrowserHandler.java index 22e46cb722..325edb5d61 100644 --- a/server/src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java +++ b/server/src/com/vaadin/server/UnsupportedBrowserHandler.java @@ -13,15 +13,12 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.IOException; import java.io.Writer; import com.vaadin.Application; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; /** * A {@link RequestHandler} that presents an informative page if the browser in diff --git a/server/src/com/vaadin/terminal/gwt/server/UploadException.java b/server/src/com/vaadin/server/UploadException.java index 566c98bf2b..cc3b075a8b 100644 --- a/server/src/com/vaadin/terminal/gwt/server/UploadException.java +++ b/server/src/com/vaadin/server/UploadException.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; @SuppressWarnings("serial") public class UploadException extends Exception { diff --git a/server/src/com/vaadin/terminal/UserError.java b/server/src/com/vaadin/server/UserError.java index 18680f912f..756f2e70e0 100644 --- a/server/src/com/vaadin/terminal/UserError.java +++ b/server/src/com/vaadin/server/UserError.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; /** * <code>UserError</code> is a controlled error occurred in application. User diff --git a/server/src/com/vaadin/terminal/VariableOwner.java b/server/src/com/vaadin/server/VariableOwner.java index faa0298311..c917996e6b 100644 --- a/server/src/com/vaadin/terminal/VariableOwner.java +++ b/server/src/com/vaadin/server/VariableOwner.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.Serializable; import java.util.Map; @@ -31,7 +31,7 @@ import java.util.Map; * @author Vaadin Ltd. * @since 3.0 * @deprecated in 7.0. Only provided to ease porting of Vaadin 6 components. Do - * not implement this directly, implement {@link Vaadin6Component}. + * not implement this directly, implement {@link LegacyComponent}. */ @Deprecated public interface VariableOwner extends Serializable { diff --git a/server/src/com/vaadin/terminal/gwt/server/WebApplicationContext.java b/server/src/com/vaadin/server/WebApplicationContext.java index bfcc0c1038..7059a04682 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WebApplicationContext.java +++ b/server/src/com/vaadin/server/WebApplicationContext.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.File; import java.util.Enumeration; diff --git a/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java index 37bc81cfcf..92090da14a 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java +++ b/server/src/com/vaadin/server/WebBrowser.java @@ -14,13 +14,12 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.util.Date; import java.util.Locale; import com.vaadin.shared.VBrowserDetails; -import com.vaadin.terminal.WrappedRequest; /** * Class that provides information about the web browser the user is using. diff --git a/server/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java b/server/src/com/vaadin/server/WrappedHttpServletRequest.java index a64be4c163..cb8a9e8c5f 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java +++ b/server/src/com/vaadin/server/WrappedHttpServletRequest.java @@ -14,15 +14,12 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import com.vaadin.Application; -import com.vaadin.terminal.CombinedRequest; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.WrappedRequest; /** * Wrapper for {@link HttpServletRequest}. diff --git a/server/src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java b/server/src/com/vaadin/server/WrappedHttpServletResponse.java index 237bb643ee..f2916ac0eb 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java +++ b/server/src/com/vaadin/server/WrappedHttpServletResponse.java @@ -14,14 +14,11 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.WrappedResponse; - /** * Wrapper for {@link HttpServletResponse}. * diff --git a/server/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java b/server/src/com/vaadin/server/WrappedPortletRequest.java index 9ac2e5a608..40a5c5f509 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java +++ b/server/src/com/vaadin/server/WrappedPortletRequest.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.IOException; import java.io.InputStream; @@ -27,9 +27,6 @@ import javax.portlet.ResourceRequest; import com.vaadin.Application; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.CombinedRequest; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.WrappedRequest; /** * Wrapper for {@link PortletRequest} and its subclasses. diff --git a/server/src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java b/server/src/com/vaadin/server/WrappedPortletResponse.java index 39ccacd331..f84e3619d2 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java +++ b/server/src/com/vaadin/server/WrappedPortletResponse.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.server; +package com.vaadin.server; import java.io.IOException; import java.io.OutputStream; @@ -29,9 +29,6 @@ import javax.portlet.MimeResponse; import javax.portlet.PortletResponse; import javax.portlet.ResourceResponse; -import com.vaadin.terminal.DeploymentConfiguration; -import com.vaadin.terminal.WrappedResponse; - /** * Wrapper for {@link PortletResponse} and its subclasses. * diff --git a/server/src/com/vaadin/terminal/WrappedRequest.java b/server/src/com/vaadin/server/WrappedRequest.java index 343a60848e..8ae5335763 100644 --- a/server/src/com/vaadin/terminal/WrappedRequest.java +++ b/server/src/com/vaadin/server/WrappedRequest.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.InputStream; @@ -29,7 +29,6 @@ import javax.servlet.http.HttpServletRequest; import com.vaadin.Application; import com.vaadin.UIRequiresMoreInformationException; import com.vaadin.annotations.EagerInit; -import com.vaadin.terminal.gwt.server.WebBrowser; import com.vaadin.ui.UI; /** diff --git a/server/src/com/vaadin/terminal/WrappedResponse.java b/server/src/com/vaadin/server/WrappedResponse.java index 02daaa1bdd..c8d9342418 100644 --- a/server/src/com/vaadin/terminal/WrappedResponse.java +++ b/server/src/com/vaadin/server/WrappedResponse.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal; +package com.vaadin.server; import java.io.IOException; import java.io.OutputStream; diff --git a/server/src/com/vaadin/terminal/package.html b/server/src/com/vaadin/server/package.html index 83514a0de5..83514a0de5 100644 --- a/server/src/com/vaadin/terminal/package.html +++ b/server/src/com/vaadin/server/package.html diff --git a/server/src/com/vaadin/service/ApplicationContext.java b/server/src/com/vaadin/service/ApplicationContext.java index 55495dcd5c..591704764f 100644 --- a/server/src/com/vaadin/service/ApplicationContext.java +++ b/server/src/com/vaadin/service/ApplicationContext.java @@ -18,12 +18,9 @@ package com.vaadin.service; import java.io.File; import java.io.Serializable; -import java.net.URL; import java.util.Collection; import com.vaadin.Application; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; /** * <code>ApplicationContext</code> provides information about the running @@ -86,59 +83,6 @@ public interface ApplicationContext extends Serializable { public int getMaxInactiveInterval(); /** - * Generate a URL that can be used as the relative location of e.g. an - * {@link ApplicationResource}. - * - * This method should only be called from the processing of a UIDL request, - * not from a background thread. The return value is null if used outside a - * suitable request. - * - * @deprecated this method is intended for terminal implementation only and - * is subject to change/removal from the interface (to - * {@link AbstractCommunicationManager}) - * - * @param resource - * @param urlKey - * a key for the resource that can later be extracted from a URL - * with {@link #getURLKey(URL, String)} - */ - @Deprecated - public String generateApplicationResourceURL(ApplicationResource resource, - String urlKey); - - /** - * Tests if a URL is for an application resource (APP/...). - * - * @deprecated this method is intended for terminal implementation only and - * is subject to change/removal from the interface (to - * {@link AbstractCommunicationManager}) - * - * @param context - * @param relativeUri - * @return - */ - @Deprecated - public boolean isApplicationResourceURL(URL context, String relativeUri); - - /** - * Gets the identifier (key) from an application resource URL. This key is - * the one that was given to - * {@link #generateApplicationResourceURL(ApplicationResource, String)} when - * creating the URL. - * - * @deprecated this method is intended for terminal implementation only and - * is subject to change/removal from the interface (to - * {@link AbstractCommunicationManager}) - * - * - * @param context - * @param relativeUri - * @return - */ - @Deprecated - public String getURLKey(URL context, String relativeUri); - - /** * Interface for listening to transaction events. Implement this interface * to listen to all transactions between the client and the application. * diff --git a/server/src/com/vaadin/service/FileTypeResolver.java b/server/src/com/vaadin/service/FileTypeResolver.java index 2b289d6752..4b1c8697eb 100644 --- a/server/src/com/vaadin/service/FileTypeResolver.java +++ b/server/src/com/vaadin/service/FileTypeResolver.java @@ -23,8 +23,8 @@ import java.util.Hashtable; import java.util.Map; import java.util.StringTokenizer; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.ThemeResource; +import com.vaadin.server.Resource; +import com.vaadin.server.ThemeResource; /** * Utility class that can figure out mime-types and icons related to files. diff --git a/server/src/com/vaadin/terminal/ApplicationResource.java b/server/src/com/vaadin/terminal/ApplicationResource.java deleted file mode 100644 index 1d1444b774..0000000000 --- a/server/src/com/vaadin/terminal/ApplicationResource.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal; - -import java.io.Serializable; - -import com.vaadin.Application; - -/** - * This interface must be implemented by classes wishing to provide Application - * resources. - * <p> - * <code>ApplicationResource</code> are a set of named resources (pictures, - * sounds, etc) associated with some specific application. Having named - * application resources provides a convenient method for having inter-theme - * common resources for an application. - * </p> - * - * @author Vaadin Ltd. - * @since 3.0 - */ -public interface ApplicationResource extends Resource, Serializable { - - /** - * Default cache time. - */ - public static final long DEFAULT_CACHETIME = 1000 * 60 * 60 * 24; - - /** - * Gets resource as stream. - */ - public DownloadStream getStream(); - - /** - * Gets the application of the resource. - */ - public Application getApplication(); - - /** - * Gets the virtual filename for this resource. - * - * @return the file name associated to this resource. - */ - public String getFilename(); - - /** - * Gets the length of cache expiration time. - * - * <p> - * This gives the adapter the possibility cache streams sent to the client. - * The caching may be made in adapter or at the client if the client - * supports caching. Default is <code>DEFAULT_CACHETIME</code>. - * </p> - * - * @return Cache time in milliseconds - */ - public long getCacheTime(); - - /** - * Gets the size of the download buffer used for this resource. - * - * <p> - * If the buffer size is 0, the buffer size is decided by the terminal - * adapter. The default value is 0. - * </p> - * - * @return int the size of the buffer in bytes. - */ - public int getBufferSize(); - -} diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java b/server/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java deleted file mode 100644 index d5c0d604c3..0000000000 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.server; - -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletResponse; - -import com.vaadin.Application; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.DownloadStream; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; - -public class ApplicationResourceHandler implements RequestHandler { - private static final Pattern APP_RESOURCE_PATTERN = Pattern - .compile("^/?APP/(\\d+)/.*"); - - @Override - public boolean handleRequest(Application application, - WrappedRequest request, WrappedResponse response) - throws IOException { - // Check for application resources - String requestPath = request.getRequestPathInfo(); - if (requestPath == null) { - return false; - } - Matcher resourceMatcher = APP_RESOURCE_PATTERN.matcher(requestPath); - - if (resourceMatcher.matches()) { - ApplicationResource resource = application - .getResource(resourceMatcher.group(1)); - if (resource != null) { - DownloadStream stream = resource.getStream(); - if (stream != null) { - stream.setCacheTime(resource.getCacheTime()); - stream.writeTo(response); - return true; - } - } - // We get here if the url looks like an application resource but no - // resource can be served - response.sendError(HttpServletResponse.SC_NOT_FOUND, - request.getRequestPathInfo() + " can not be found"); - return true; - } - - return false; - } -} diff --git a/server/src/com/vaadin/terminal/gwt/server/ResourceReference.java b/server/src/com/vaadin/terminal/gwt/server/ResourceReference.java deleted file mode 100644 index a1d5731f7d..0000000000 --- a/server/src/com/vaadin/terminal/gwt/server/ResourceReference.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.server; - -import com.vaadin.Application; -import com.vaadin.shared.communication.URLReference; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.ExternalResource; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.ThemeResource; - -public class ResourceReference extends URLReference { - - private Resource resource; - - public ResourceReference(Resource resource) { - this.resource = resource; - } - - public Resource getResource() { - return resource; - } - - @Override - public String getURL() { - if (resource instanceof ExternalResource) { - return ((ExternalResource) resource).getURL(); - } else if (resource instanceof ApplicationResource) { - final ApplicationResource r = (ApplicationResource) resource; - final Application a = r.getApplication(); - if (a == null) { - throw new RuntimeException( - "An ApplicationResource (" - + r.getClass().getName() - + " must be attached to an application when it is sent to the client."); - } - final String uri = a.getRelativeLocation(r); - return uri; - } else if (resource instanceof ThemeResource) { - final String uri = "theme://" - + ((ThemeResource) resource).getResourceId(); - return uri; - } else { - throw new RuntimeException(getClass().getSimpleName() - + " does not support resources of type: " - + resource.getClass().getName()); - } - - } - - public static ResourceReference create(Resource resource) { - if (resource == null) { - return null; - } else { - return new ResourceReference(resource); - } - } - - public static Resource getResource(URLReference reference) { - if (reference == null) { - return null; - } - assert reference instanceof ResourceReference; - return ((ResourceReference) reference).getResource(); - } -} diff --git a/server/src/com/vaadin/ui/AbsoluteLayout.java b/server/src/com/vaadin/ui/AbsoluteLayout.java index 56bbd19852..794de49671 100644 --- a/server/src/com/vaadin/ui/AbsoluteLayout.java +++ b/server/src/com/vaadin/ui/AbsoluteLayout.java @@ -24,12 +24,12 @@ import java.util.Map; import com.vaadin.event.LayoutEvents.LayoutClickEvent; import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.LayoutEvents.LayoutClickNotifier; +import com.vaadin.server.Sizeable; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutServerRpc; import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutState; -import com.vaadin.terminal.Sizeable; /** * AbsoluteLayout is a layout implementation that mimics html absolute @@ -629,16 +629,33 @@ public class AbsoluteLayout extends AbstractLayout implements } @Override - public void addListener(LayoutClickListener listener) { + public void addLayoutClickListener(LayoutClickListener listener) { addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener, LayoutClickListener.clickMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void addListener(LayoutClickListener listener) { + addLayoutClickListener(listener); + } + @Override - public void removeListener(LayoutClickListener listener) { + public void removeLayoutClickListener(LayoutClickListener listener) { removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void removeListener(LayoutClickListener listener) { + removeLayoutClickListener(listener); + } } diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index 917b1a516d..045173036e 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -32,14 +32,14 @@ import com.vaadin.event.ActionManager; import com.vaadin.event.EventRouter; import com.vaadin.event.MethodEventSource; import com.vaadin.event.ShortcutListener; +import com.vaadin.server.AbstractClientConnector; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.ComponentSizeValidator; +import com.vaadin.server.ErrorMessage; +import com.vaadin.server.Resource; +import com.vaadin.server.Terminal; +import com.vaadin.shared.ComponentConstants; import com.vaadin.shared.ComponentState; -import com.vaadin.terminal.AbstractClientConnector; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Terminal; -import com.vaadin.terminal.gwt.server.ClientConnector; -import com.vaadin.terminal.gwt.server.ComponentSizeValidator; -import com.vaadin.terminal.gwt.server.ResourceReference; import com.vaadin.tools.ReflectTools; /** @@ -297,7 +297,7 @@ public abstract class AbstractComponent extends AbstractClientConnector */ @Override public Resource getIcon() { - return ResourceReference.getResource(getState().getIcon()); + return getResource(ComponentConstants.ICON_RESOURCE); } /** @@ -309,7 +309,7 @@ public abstract class AbstractComponent extends AbstractClientConnector */ @Override public void setIcon(Resource icon) { - getState().setIcon(ResourceReference.create(icon)); + setResource(ComponentConstants.ICON_RESOURCE, icon); } /* @@ -335,7 +335,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled() + * @see com.vaadin.client.Connector#isConnectorEnabled() */ @Override public boolean isConnectorEnabled() { @@ -1072,7 +1072,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#getHeight() + * @see com.vaadin.Sizeable#getHeight() */ @Override public float getHeight() { @@ -1082,7 +1082,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#getHeightUnits() + * @see com.vaadin.server.Sizeable#getHeightUnits() */ @Override public Unit getHeightUnits() { @@ -1092,7 +1092,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#getWidth() + * @see com.vaadin.server.Sizeable#getWidth() */ @Override public float getWidth() { @@ -1102,7 +1102,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#getWidthUnits() + * @see com.vaadin.server.Sizeable#getWidthUnits() */ @Override public Unit getWidthUnits() { @@ -1112,7 +1112,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setHeight(float, Unit) + * @see com.vaadin.server.Sizeable#setHeight(float, Unit) */ @Override public void setHeight(float height, Unit unit) { @@ -1128,7 +1128,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setSizeFull() + * @see com.vaadin.server.Sizeable#setSizeFull() */ @Override public void setSizeFull() { @@ -1139,7 +1139,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setSizeUndefined() + * @see com.vaadin.server.Sizeable#setSizeUndefined() */ @Override public void setSizeUndefined() { @@ -1150,7 +1150,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setWidth(float, Unit) + * @see com.vaadin.server.Sizeable#setWidth(float, Unit) */ @Override public void setWidth(float width, Unit unit) { @@ -1166,7 +1166,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setWidth(java.lang.String) + * @see com.vaadin.server.Sizeable#setWidth(java.lang.String) */ @Override public void setWidth(String width) { @@ -1181,7 +1181,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /* * (non-Javadoc) * - * @see com.vaadin.terminal.Sizeable#setHeight(java.lang.String) + * @see com.vaadin.server.Sizeable#setHeight(java.lang.String) */ @Override public void setHeight(String height) { diff --git a/server/src/com/vaadin/ui/AbstractComponentContainer.java b/server/src/com/vaadin/ui/AbstractComponentContainer.java index 4939eb1265..cf3bf1d2b9 100644 --- a/server/src/com/vaadin/ui/AbstractComponentContainer.java +++ b/server/src/com/vaadin/ui/AbstractComponentContainer.java @@ -22,7 +22,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; -import com.vaadin.terminal.gwt.server.ComponentSizeValidator; +import com.vaadin.server.ComponentSizeValidator; /** * Extension to {@link AbstractComponent} that defines the default @@ -106,33 +106,69 @@ public abstract class AbstractComponentContainer extends AbstractComponent /* documented in interface */ @Override - public void addListener(ComponentAttachListener listener) { + public void addComponentAttachListener(ComponentAttachListener listener) { addListener(ComponentContainer.ComponentAttachEvent.class, listener, COMPONENT_ATTACHED_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentAttachListener(com.vaadin.ui.ComponentContainer.ComponentAttachListener)} + **/ + @Deprecated + public void addListener(ComponentAttachListener listener) { + addComponentAttachListener(listener); + } + /* documented in interface */ @Override - public void addListener(ComponentDetachListener listener) { + public void addComponentDetachListener(ComponentDetachListener listener) { addListener(ComponentContainer.ComponentDetachEvent.class, listener, COMPONENT_DETACHED_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentDetachListener(com.vaadin.ui.ComponentContainer.ComponentDetachListener)} + **/ + @Deprecated + public void addListener(ComponentDetachListener listener) { + addComponentDetachListener(listener); + } + /* documented in interface */ @Override - public void removeListener(ComponentAttachListener listener) { + public void removeComponentAttachListener(ComponentAttachListener listener) { removeListener(ComponentContainer.ComponentAttachEvent.class, listener, COMPONENT_ATTACHED_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentAttachListener(com.vaadin.ui.ComponentContainer.ComponentAttachListener)} + **/ + @Deprecated + public void removeListener(ComponentAttachListener listener) { + removeComponentAttachListener(listener); + } + /* documented in interface */ @Override - public void removeListener(ComponentDetachListener listener) { + public void removeComponentDetachListener(ComponentDetachListener listener) { removeListener(ComponentContainer.ComponentDetachEvent.class, listener, COMPONENT_DETACHED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentDetachListener(com.vaadin.ui.ComponentContainer.ComponentDetachListener)} + **/ + @Deprecated + public void removeListener(ComponentDetachListener listener) { + removeComponentDetachListener(listener); + } + + /** * Fires the component attached event. This should be called by the * addComponent methods after the component have been added to this * container. diff --git a/server/src/com/vaadin/ui/AbstractEmbedded.java b/server/src/com/vaadin/ui/AbstractEmbedded.java index 9396af5c44..d94f62120f 100644 --- a/server/src/com/vaadin/ui/AbstractEmbedded.java +++ b/server/src/com/vaadin/ui/AbstractEmbedded.java @@ -4,9 +4,8 @@ package com.vaadin.ui; +import com.vaadin.server.Resource; import com.vaadin.shared.ui.AbstractEmbeddedState; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.server.ResourceReference; /** * Abstract base for embedding components. @@ -32,12 +31,7 @@ public abstract class AbstractEmbedded extends AbstractComponent { * the source to set. */ public void setSource(Resource source) { - if (source == null) { - getState().setSource(null); - } else { - getState().setSource(new ResourceReference(source)); - } - requestRepaint(); + setResource(AbstractEmbeddedState.SOURCE_RESOURCE, source); } /** @@ -46,12 +40,7 @@ public abstract class AbstractEmbedded extends AbstractComponent { * @return the source */ public Resource getSource() { - ResourceReference ref = ((ResourceReference) getState().getSource()); - if (ref == null) { - return null; - } else { - return ref.getResource(); - } + return getResource(AbstractEmbeddedState.SOURCE_RESOURCE); } /** diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 5123d08da9..b1d45ae590 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -37,10 +37,10 @@ import com.vaadin.data.util.converter.ConverterUtil; import com.vaadin.event.Action; import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutListener; +import com.vaadin.server.AbstractErrorMessage; +import com.vaadin.server.CompositeErrorMessage; +import com.vaadin.server.ErrorMessage; import com.vaadin.shared.AbstractFieldState; -import com.vaadin.terminal.AbstractErrorMessage; -import com.vaadin.terminal.CompositeErrorMessage; -import com.vaadin.terminal.ErrorMessage; /** * <p> @@ -1047,23 +1047,41 @@ public abstract class AbstractField<T> extends AbstractComponent implements * here, we use the default documentation from the implemented interface. */ @Override - public void addListener(Property.ValueChangeListener listener) { + public void addValueChangeListener(Property.ValueChangeListener listener) { addListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void addListener(Property.ValueChangeListener listener) { + addValueChangeListener(listener); + } + /* * Removes a value change listener from the field. Don't add a JavaDoc * comment here, we use the default documentation from the implemented * interface. */ @Override - public void removeListener(Property.ValueChangeListener listener) { + public void removeValueChangeListener(Property.ValueChangeListener listener) { removeListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ValueChangeListener listener) { + removeValueChangeListener(listener); + } + + /** * Emits the value change event. The value contained in the field is * validated before the event is created. */ @@ -1139,23 +1157,43 @@ public abstract class AbstractField<T> extends AbstractComponent implements * implemented interface. */ @Override - public void addListener(Property.ReadOnlyStatusChangeListener listener) { + public void addReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { addListener(Property.ReadOnlyStatusChangeEvent.class, listener, READ_ONLY_STATUS_CHANGE_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Deprecated + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + addReadOnlyStatusChangeListener(listener); + } + /* * Removes a read-only status change listener from the field. Don't add a * JavaDoc comment here, we use the default documentation from the * implemented interface. */ @Override - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + public void removeReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, READ_ONLY_STATUS_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + removeReadOnlyStatusChangeListener(listener); + } + + /** * Emits the read-only status change event. The value contained in the field * is validated before the event is created. */ diff --git a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java index e19bdf1b2b..47420334d7 100644 --- a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java +++ b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java @@ -15,8 +15,8 @@ */ package com.vaadin.ui; +import com.vaadin.server.JavaScriptCallbackHelper; import com.vaadin.shared.ui.JavaScriptComponentState; -import com.vaadin.terminal.JavaScriptCallbackHelper; /** * Base class for Components with all client-side logic implemented using @@ -35,9 +35,9 @@ import com.vaadin.terminal.JavaScriptCallbackHelper; * <code>com_example_MyComponent</code> has not been defined. * <p> * JavaScript components have a very simple GWT widget ( - * {@link com.vaadin.terminal.gwt.client.ui.JavaScriptWidget} ) just consisting - * of a <code>div</code> element to which the JavaScript code should initialize - * its own user interface. + * {@link com.vaadin.client.ui.JavaScriptWidget} ) just consisting of a + * <code>div</code> element to which the JavaScript code should initialize its + * own user interface. * <p> * The initialization function will be called with <code>this</code> pointing to * a connector wrapper object providing integration to Vaadin with the following @@ -80,8 +80,7 @@ import com.vaadin.terminal.JavaScriptCallbackHelper; * functions is described bellow.</li> * <li><code>translateVaadinUri(uri)</code> - Translates a Vaadin URI to a URL * that can be used in the browser. This is just way of accessing - * {@link com.vaadin.terminal.gwt.client.ApplicationConnection#translateVaadinUri(String)} - * </li> + * {@link com.vaadin.client.ApplicationConnection#translateVaadinUri(String)}</li> * </ul> * The connector wrapper also supports these special functions: * <ul> diff --git a/server/src/com/vaadin/ui/AbstractMedia.java b/server/src/com/vaadin/ui/AbstractMedia.java index 77c12ac045..3f59b070b7 100644 --- a/server/src/com/vaadin/ui/AbstractMedia.java +++ b/server/src/com/vaadin/ui/AbstractMedia.java @@ -16,14 +16,21 @@ package com.vaadin.ui; +import java.io.IOException; import java.util.ArrayList; import java.util.List; - +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.vaadin.server.ConnectorResource; +import com.vaadin.server.Resource; +import com.vaadin.server.ResourceReference; +import com.vaadin.server.WrappedRequest; +import com.vaadin.server.WrappedResponse; import com.vaadin.shared.communication.URLReference; import com.vaadin.shared.ui.AbstractMediaState; import com.vaadin.shared.ui.MediaControl; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.server.ResourceReference; /** * Abstract base class for the HTML5 media components. @@ -64,11 +71,43 @@ public abstract class AbstractMedia extends AbstractComponent { */ public void addSource(Resource source) { if (source != null) { - getState().getSources().add(new ResourceReference(source)); + List<URLReference> sources = getState().getSources(); + sources.add(new ResourceReference(source, this, Integer + .toString(sources.size()))); getState().getSourceTypes().add(source.getMIMEType()); } } + @Override + public boolean handleConnectorRequest(WrappedRequest request, + WrappedResponse response, String path) throws IOException { + Matcher matcher = Pattern.compile("(\\d+)(/.*)?").matcher(path); + if (matcher.matches()) { + List<URLReference> sources = getState().getSources(); + + int sourceIndex = Integer.parseInt(matcher.group(1)); + + if (sourceIndex < 0 || sourceIndex >= sources.size()) { + getLogger().warning( + "Requested source index " + sourceIndex + + " is out of bounds"); + return false; + } + + URLReference reference = sources.get(sourceIndex); + ConnectorResource resource = (ConnectorResource) ResourceReference + .getResource(reference); + resource.getStream().writeResponse(request, response); + return true; + } else { + return super.handleConnectorRequest(request, response, path); + } + } + + private Logger getLogger() { + return Logger.getLogger(AbstractMedia.class.getName()); + } + /** * Set multiple sources at once. Which of the sources is used is selected by * the browser depending on which file formats it supports. See <a diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java index 596bbb7ee2..184f7c40f4 100644 --- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java +++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java @@ -22,6 +22,7 @@ import java.util.LinkedList; import com.vaadin.event.LayoutEvents.LayoutClickEvent; import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.LayoutEvents.LayoutClickNotifier; +import com.vaadin.server.Sizeable; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; @@ -29,7 +30,6 @@ import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState.ChildComponentData; -import com.vaadin.terminal.Sizeable; @SuppressWarnings("serial") public abstract class AbstractOrderedLayout extends AbstractLayout implements @@ -339,19 +339,37 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements } @Override - public void addListener(LayoutClickListener listener) { + public void addLayoutClickListener(LayoutClickListener listener) { addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener, LayoutClickListener.clickMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void addListener(LayoutClickListener listener) { + addLayoutClickListener(listener); + } + @Override - public void removeListener(LayoutClickListener listener) { + public void removeLayoutClickListener(LayoutClickListener listener) { removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void removeListener(LayoutClickListener listener) { + removeLayoutClickListener(listener); + } + + /** * Returns the index of the given component. * * @param component diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index 21ff7ba948..3dba5088df 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -39,12 +39,12 @@ import com.vaadin.event.dd.TargetDetailsImpl; import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion; import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor; import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; +import com.vaadin.server.KeyMapper; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; import com.vaadin.ui.AbstractSelect.ItemCaptionMode; /** @@ -68,7 +68,7 @@ import com.vaadin.ui.AbstractSelect.ItemCaptionMode; public abstract class AbstractSelect extends AbstractField<Object> implements Container, Container.Viewer, Container.PropertySetChangeListener, Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier, - Container.ItemSetChangeListener, Vaadin6Component { + Container.ItemSetChangeListener, LegacyComponent { public enum ItemCaptionMode { /** @@ -1480,7 +1480,8 @@ public abstract class AbstractSelect extends AbstractField<Object> implements * @see com.vaadin.data.Container.PropertySetChangeNotifier#addListener(com.vaadin.data.Container.PropertySetChangeListener) */ @Override - public void addListener(Container.PropertySetChangeListener listener) { + public void addPropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (propertySetEventListeners == null) { propertySetEventListeners = new LinkedHashSet<Container.PropertySetChangeListener>(); } @@ -1488,12 +1489,22 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } /** + * @deprecated Since 7.0, replaced by + * {@link #addPropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void addListener(Container.PropertySetChangeListener listener) { + addPropertySetChangeListener(listener); + } + + /** * Removes a previously registered Property set change listener. * * @see com.vaadin.data.Container.PropertySetChangeNotifier#removeListener(com.vaadin.data.Container.PropertySetChangeListener) */ @Override - public void removeListener(Container.PropertySetChangeListener listener) { + public void removePropertySetChangeListener( + Container.PropertySetChangeListener listener) { if (propertySetEventListeners != null) { propertySetEventListeners.remove(listener); if (propertySetEventListeners.isEmpty()) { @@ -1503,12 +1514,22 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } /** + * @deprecated Since 7.0, replaced by + * {@link #removePropertySetChangeListener(com.vaadin.data.Container.PropertySetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.PropertySetChangeListener listener) { + removePropertySetChangeListener(listener); + } + + /** * Adds an Item set change listener for the object. * * @see com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin.data.Container.ItemSetChangeListener) */ @Override - public void addListener(Container.ItemSetChangeListener listener) { + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (itemSetEventListeners == null) { itemSetEventListeners = new LinkedHashSet<Container.ItemSetChangeListener>(); } @@ -1516,12 +1537,22 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } /** + * @deprecated Since 7.0, replaced by + * {@link #addItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void addListener(Container.ItemSetChangeListener listener) { + addItemSetChangeListener(listener); + } + + /** * Removes the Item set change listener from the object. * * @see com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin.data.Container.ItemSetChangeListener) */ @Override - public void removeListener(Container.ItemSetChangeListener listener) { + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { if (itemSetEventListeners != null) { itemSetEventListeners.remove(listener); if (itemSetEventListeners.isEmpty()) { @@ -1530,6 +1561,15 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemSetChangeListener(com.vaadin.data.Container.ItemSetChangeListener)} + **/ + @Deprecated + public void removeListener(Container.ItemSetChangeListener listener) { + removeItemSetChangeListener(listener); + } + @Override public Collection<?> getListeners(Class<?> eventType) { if (Container.ItemSetChangeEvent.class.isAssignableFrom(eventType)) { diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java index 8b7499115c..f1452caacf 100644 --- a/server/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java @@ -22,12 +22,12 @@ import java.util.Iterator; import com.vaadin.event.ComponentEventListener; import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.server.Sizeable; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelRpc; import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState; import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState.SplitterState; -import com.vaadin.terminal.Sizeable; import com.vaadin.tools.ReflectTools; /** @@ -501,16 +501,34 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { } - public void addListener(SplitterClickListener listener) { + public void addSplitterClickListener(SplitterClickListener listener) { addListener(EventId.CLICK_EVENT_IDENTIFIER, SplitterClickEvent.class, listener, SplitterClickListener.clickMethod); } - public void removeListener(SplitterClickListener listener) { + /** + * @deprecated Since 7.0, replaced by + * {@link #addSplitterClickListener(SplitterClickListener)} + **/ + @Deprecated + public void addListener(SplitterClickListener listener) { + addSplitterClickListener(listener); + } + + public void removeSplitterClickListener(SplitterClickListener listener) { removeListener(EventId.CLICK_EVENT_IDENTIFIER, SplitterClickEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeSplitterClickListener(SplitterClickListener)} + **/ + @Deprecated + public void removeListener(SplitterClickListener listener) { + removeSplitterClickListener(listener); + } + @Override protected AbstractSplitPanelState getState() { return (AbstractSplitPanelState) super.getState(); diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java index 1bd61023a4..c187d9e198 100644 --- a/server/src/com/vaadin/ui/AbstractTextField.java +++ b/server/src/com/vaadin/ui/AbstractTextField.java @@ -27,14 +27,14 @@ import com.vaadin.event.FieldEvents.FocusNotifier; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.event.FieldEvents.TextChangeNotifier; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.textfield.AbstractTextFieldState; import com.vaadin.shared.ui.textfield.TextFieldConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; public abstract class AbstractTextField extends AbstractField<String> implements - BlurNotifier, FocusNotifier, TextChangeNotifier, Vaadin6Component { + BlurNotifier, FocusNotifier, TextChangeNotifier, LegacyComponent { /** * Null representation. @@ -512,18 +512,36 @@ public abstract class AbstractTextField extends AbstractField<String> implements } @Override - public void addListener(TextChangeListener listener) { + public void addTextChangeListener(TextChangeListener listener) { addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, listener, TextChangeListener.EVENT_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addTextChangeListener(TextChangeListener)} + **/ + @Deprecated + public void addListener(TextChangeListener listener) { + addTextChangeListener(listener); + } + @Override - public void removeListener(TextChangeListener listener) { + public void removeTextChangeListener(TextChangeListener listener) { removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeTextChangeListener(TextChangeListener)} + **/ + @Deprecated + public void removeListener(TextChangeListener listener) { + removeTextChangeListener(listener); + } + + /** * The text change timeout modifies how often text change events are * communicated to the application when {@link #getTextChangeEventMode()} is * {@link TextChangeEventMode#LAZY} or {@link TextChangeEventMode#TIMEOUT}. @@ -661,25 +679,60 @@ public abstract class AbstractTextField extends AbstractField<String> implements } @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + } diff --git a/server/src/com/vaadin/ui/Audio.java b/server/src/com/vaadin/ui/Audio.java index 03ed7ba6d5..d111c0c74c 100644 --- a/server/src/com/vaadin/ui/Audio.java +++ b/server/src/com/vaadin/ui/Audio.java @@ -16,7 +16,7 @@ package com.vaadin.ui; -import com.vaadin.terminal.Resource; +import com.vaadin.server.Resource; /** * The Audio component translates into an HTML5 <audio> element and as diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 68b9f1392f..2e026ebc52 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -290,23 +290,41 @@ public class Button extends AbstractComponent implements * @param listener * the Listener to be added. */ - public void addListener(ClickListener listener) { + public void addClickListener(ClickListener listener) { addListener(ClickEvent.class, listener, ClickListener.BUTTON_CLICK_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addClickListener(ClickListener)} + **/ + @Deprecated + public void addListener(ClickListener listener) { + addClickListener(listener); + } + + /** * Removes the button click listener. * * @param listener * the Listener to be removed. */ - public void removeListener(ClickListener listener) { + public void removeClickListener(ClickListener listener) { removeListener(ClickEvent.class, listener, ClickListener.BUTTON_CLICK_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeClickListener(ClickListener)} + **/ + @Deprecated + public void removeListener(ClickListener listener) { + removeClickListener(listener); + } + + /** * Simulates a button click, notifying all server-side listeners. * * No action is taken is the button is disabled. @@ -341,26 +359,60 @@ public class Button extends AbstractComponent implements } @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); + } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); } /* diff --git a/server/src/com/vaadin/ui/CheckBox.java b/server/src/com/vaadin/ui/CheckBox.java index 6da86b9711..149d4779d8 100644 --- a/server/src/com/vaadin/ui/CheckBox.java +++ b/server/src/com/vaadin/ui/CheckBox.java @@ -119,25 +119,60 @@ public class CheckBox extends AbstractField<Boolean> { getState().setChecked(newValue); } - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } - public void removeListener(BlurListener listener) { + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } - public void addListener(FocusListener listener) { + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } - public void removeListener(FocusListener listener) { + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + + /** * Get the boolean value of the button state. * * @return True iff the button is pressed down or checked. diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java index af19ca5b96..da3d2fd91d 100644 --- a/server/src/com/vaadin/ui/ComboBox.java +++ b/server/src/com/vaadin/ui/ComboBox.java @@ -16,12 +16,24 @@ package com.vaadin.ui; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import com.vaadin.data.Container; +import com.vaadin.data.util.filter.SimpleStringFilter; +import com.vaadin.event.FieldEvents; +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; import com.vaadin.shared.ui.combobox.ComboBoxConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; /** * A filtering dropdown single-select. Suitable for newItemsAllowed, but it's @@ -32,11 +44,59 @@ import com.vaadin.terminal.PaintTarget; * */ @SuppressWarnings("serial") -public class ComboBox extends Select { +public class ComboBox extends AbstractSelect implements + AbstractSelect.Filtering, FieldEvents.BlurNotifier, + FieldEvents.FocusNotifier { private String inputPrompt = null; /** + * Holds value of property pageLength. 0 disables paging. + */ + protected int pageLength = 10; + + private int columns = 0; + + // Current page when the user is 'paging' trough options + private int currentPage = -1; + + private int filteringMode = Filtering.FILTERINGMODE_STARTSWITH; + + private String filterstring; + private String prevfilterstring; + + /** + * Number of options that pass the filter, excluding the null item if any. + */ + private int filteredSize; + + /** + * Cache of filtered options, used only by the in-memory filtering system. + */ + private List<Object> filteredOptions; + + /** + * Flag to indicate that request repaint is called by filter request only + */ + private boolean optionRequest; + + /** + * True if the container is being filtered temporarily and item set change + * notifications should be suppressed. + */ + private boolean filteringContainer; + + /** + * Flag to indicate whether to scroll the selected item visible (select the + * page on which it is) when opening the popup or not. Only applies to + * single select mode. + * + * This requires finding the index of the item, which can be expensive in + * many large lazy loading containers. + */ + private boolean scrollToSelectedItem = true; + + /** * If text input is not allowed, the ComboBox behaves like a pretty * NativeSelect - the user can not enter any text and clicking the text * field opens the drop down with options @@ -89,11 +149,139 @@ public class ComboBox extends Select { if (inputPrompt != null) { target.addAttribute(ComboBoxConstants.ATTR_INPUTPROMPT, inputPrompt); } - super.paintContent(target); if (!textInputAllowed) { target.addAttribute(ComboBoxConstants.ATTR_NO_TEXT_INPUT, true); } + + // clear caption change listeners + getCaptionChangeListener().clear(); + + // The tab ordering number + if (getTabIndex() != 0) { + target.addAttribute("tabindex", getTabIndex()); + } + + // If the field is modified, but not committed, set modified attribute + if (isModified()) { + target.addAttribute("modified", true); + } + + if (isNewItemsAllowed()) { + target.addAttribute("allownewitem", true); + } + + boolean needNullSelectOption = false; + if (isNullSelectionAllowed()) { + target.addAttribute("nullselect", true); + needNullSelectOption = (getNullSelectionItemId() == null); + if (!needNullSelectOption) { + target.addAttribute("nullselectitem", true); + } + } + + // Constructs selected keys array + String[] selectedKeys = new String[(getValue() == null + && getNullSelectionItemId() == null ? 0 : 1)]; + + target.addAttribute("pagelength", pageLength); + + target.addAttribute("filteringmode", getFilteringMode()); + + // Paints the options and create array of selected id keys + int keyIndex = 0; + + target.startTag("options"); + + if (currentPage < 0) { + optionRequest = false; + currentPage = 0; + filterstring = ""; + } + + boolean nullFilteredOut = filterstring != null + && !"".equals(filterstring) + && filteringMode != Filtering.FILTERINGMODE_OFF; + // null option is needed and not filtered out, even if not on current + // page + boolean nullOptionVisible = needNullSelectOption && !nullFilteredOut; + + // first try if using container filters is possible + List<?> options = getOptionsWithFilter(nullOptionVisible); + if (null == options) { + // not able to use container filters, perform explicit in-memory + // filtering + options = getFilteredOptions(); + filteredSize = options.size(); + options = sanitetizeList(options, nullOptionVisible); + } + + final boolean paintNullSelection = needNullSelectOption + && currentPage == 0 && !nullFilteredOut; + + if (paintNullSelection) { + target.startTag("so"); + target.addAttribute("caption", ""); + target.addAttribute("key", ""); + target.endTag("so"); + } + + final Iterator<?> i = options.iterator(); + // Paints the available selection options from data source + + while (i.hasNext()) { + + final Object id = i.next(); + + if (!isNullSelectionAllowed() && id != null + && id.equals(getNullSelectionItemId()) && !isSelected(id)) { + continue; + } + + // Gets the option attribute values + final String key = itemIdMapper.key(id); + final String caption = getItemCaption(id); + final Resource icon = getItemIcon(id); + getCaptionChangeListener().addNotifierForItem(id); + + // Paints the option + target.startTag("so"); + if (icon != null) { + target.addAttribute("icon", icon); + } + target.addAttribute("caption", caption); + if (id != null && id.equals(getNullSelectionItemId())) { + target.addAttribute("nullselection", true); + } + target.addAttribute("key", key); + if (isSelected(id) && keyIndex < selectedKeys.length) { + target.addAttribute("selected", true); + selectedKeys[keyIndex++] = key; + } + target.endTag("so"); + } + target.endTag("options"); + + target.addAttribute("totalitems", size() + + (needNullSelectOption ? 1 : 0)); + if (filteredSize > 0 || nullOptionVisible) { + target.addAttribute("totalMatches", filteredSize + + (nullOptionVisible ? 1 : 0)); + } + + // Paint variables + target.addVariable(this, "selected", selectedKeys); + if (isNewItemsAllowed()) { + target.addVariable(this, "newitem", ""); + } + + target.addVariable(this, "filter", filterstring); + target.addVariable(this, "page", currentPage); + + currentPage = -1; // current page is always set by client + + optionRequest = true; + } /** @@ -125,4 +313,504 @@ public class ComboBox extends Select { return textInputAllowed; } + /** + * Returns the filtered options for the current page using a container + * filter. + * + * As a size effect, {@link #filteredSize} is set to the total number of + * items passing the filter. + * + * The current container must be {@link Filterable} and {@link Indexed}, and + * the filtering mode must be suitable for container filtering (tested with + * {@link #canUseContainerFilter()}). + * + * Use {@link #getFilteredOptions()} and + * {@link #sanitetizeList(List, boolean)} if this is not the case. + * + * @param needNullSelectOption + * @return filtered list of options (may be empty) or null if cannot use + * container filters + */ + protected List<?> getOptionsWithFilter(boolean needNullSelectOption) { + Container container = getContainerDataSource(); + + if (pageLength == 0) { + // no paging: return all items + filteredSize = container.size(); + return new ArrayList<Object>(container.getItemIds()); + } + + if (!(container instanceof Filterable) + || !(container instanceof Indexed) + || getItemCaptionMode() != ITEM_CAPTION_MODE_PROPERTY) { + return null; + } + + Filterable filterable = (Filterable) container; + + Filter filter = buildFilter(filterstring, filteringMode); + + // adding and removing filters leads to extraneous item set + // change events from the underlying container, but the ComboBox does + // not process or propagate them based on the flag filteringContainer + if (filter != null) { + filteringContainer = true; + filterable.addContainerFilter(filter); + } + + Indexed indexed = (Indexed) container; + + int indexToEnsureInView = -1; + + // if not an option request (item list when user changes page), go + // to page with the selected item after filtering if accepted by + // filter + Object selection = getValue(); + if (isScrollToSelectedItem() && !optionRequest && selection != null) { + // ensure proper page + indexToEnsureInView = indexed.indexOfId(selection); + } + + filteredSize = container.size(); + currentPage = adjustCurrentPage(currentPage, needNullSelectOption, + indexToEnsureInView, filteredSize); + int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, + filteredSize); + int last = getLastItemIndexOnCurrentPage(needNullSelectOption, + filteredSize, first); + + List<Object> options = new ArrayList<Object>(); + for (int i = first; i <= last && i < filteredSize; ++i) { + options.add(indexed.getIdByIndex(i)); + } + + // to the outside, filtering should not be visible + if (filter != null) { + filterable.removeContainerFilter(filter); + filteringContainer = false; + } + + return options; + } + + /** + * Constructs a filter instance to use when using a Filterable container in + * the <code>ITEM_CAPTION_MODE_PROPERTY</code> mode. + * + * Note that the client side implementation expects the filter string to + * apply to the item caption string it sees, so changing the behavior of + * this method can cause problems. + * + * @param filterString + * @param filteringMode + * @return + */ + protected Filter buildFilter(String filterString, int filteringMode) { + Filter filter = null; + + if (null != filterString && !"".equals(filterString)) { + switch (filteringMode) { + case Filtering.FILTERINGMODE_OFF: + break; + case Filtering.FILTERINGMODE_STARTSWITH: + filter = new SimpleStringFilter(getItemCaptionPropertyId(), + filterString, true, true); + break; + case Filtering.FILTERINGMODE_CONTAINS: + filter = new SimpleStringFilter(getItemCaptionPropertyId(), + filterString, true, false); + break; + } + } + return filter; + } + + @Override + public void containerItemSetChange(Container.ItemSetChangeEvent event) { + if (!filteringContainer) { + super.containerItemSetChange(event); + } + } + + /** + * Makes correct sublist of given list of options. + * + * If paint is not an option request (affected by page or filter change), + * page will be the one where possible selection exists. + * + * Detects proper first and last item in list to return right page of + * options. Also, if the current page is beyond the end of the list, it will + * be adjusted. + * + * @param options + * @param needNullSelectOption + * flag to indicate if nullselect option needs to be taken into + * consideration + */ + private List<?> sanitetizeList(List<?> options, boolean needNullSelectOption) { + + if (pageLength != 0 && options.size() > pageLength) { + + int indexToEnsureInView = -1; + + // if not an option request (item list when user changes page), go + // to page with the selected item after filtering if accepted by + // filter + Object selection = getValue(); + if (isScrollToSelectedItem() && !optionRequest && selection != null) { + // ensure proper page + indexToEnsureInView = options.indexOf(selection); + } + + int size = options.size(); + currentPage = adjustCurrentPage(currentPage, needNullSelectOption, + indexToEnsureInView, size); + int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, + size); + int last = getLastItemIndexOnCurrentPage(needNullSelectOption, + size, first); + return options.subList(first, last + 1); + } else { + return options; + } + } + + /** + * Returns the index of the first item on the current page. The index is to + * the underlying (possibly filtered) contents. The null item, if any, does + * not have an index but takes up a slot on the first page. + * + * @param needNullSelectOption + * true if a null option should be shown before any other options + * (takes up the first slot on the first page, not counted in + * index) + * @param size + * number of items after filtering (not including the null item, + * if any) + * @return first item to show on the UI (index to the filtered list of + * options, not taking the null item into consideration if any) + */ + private int getFirstItemIndexOnCurrentPage(boolean needNullSelectOption, + int size) { + // Not all options are visible, find out which ones are on the + // current "page". + int first = currentPage * pageLength; + if (needNullSelectOption && currentPage > 0) { + first--; + } + return first; + } + + /** + * Returns the index of the last item on the current page. The index is to + * the underlying (possibly filtered) contents. If needNullSelectOption is + * true, the null item takes up the first slot on the first page, + * effectively reducing the first page size by one. + * + * @param needNullSelectOption + * true if a null option should be shown before any other options + * (takes up the first slot on the first page, not counted in + * index) + * @param size + * number of items after filtering (not including the null item, + * if any) + * @param first + * index in the filtered view of the first item of the page + * @return index in the filtered view of the last item on the page + */ + private int getLastItemIndexOnCurrentPage(boolean needNullSelectOption, + int size, int first) { + // page length usable for non-null items + int effectivePageLength = pageLength + - (needNullSelectOption && (currentPage == 0) ? 1 : 0); + return Math.min(size - 1, first + effectivePageLength - 1); + } + + /** + * Adjusts the index of the current page if necessary: make sure the current + * page is not after the end of the contents, and optionally go to the page + * containg a specific item. There are no side effects but the adjusted page + * index is returned. + * + * @param page + * page number to use as the starting point + * @param needNullSelectOption + * true if a null option should be shown before any other options + * (takes up the first slot on the first page, not counted in + * index) + * @param indexToEnsureInView + * index of an item that should be included on the page (in the + * data set, not counting the null item if any), -1 for none + * @param size + * number of items after filtering (not including the null item, + * if any) + */ + private int adjustCurrentPage(int page, boolean needNullSelectOption, + int indexToEnsureInView, int size) { + if (indexToEnsureInView != -1) { + int newPage = (indexToEnsureInView + (needNullSelectOption ? 1 : 0)) + / pageLength; + page = newPage; + } + // adjust the current page if beyond the end of the list + if (page * pageLength > size) { + page = (size + (needNullSelectOption ? 1 : 0)) / pageLength; + } + return page; + } + + /** + * Filters the options in memory and returns the full filtered list. + * + * This can be less efficient than using container filters, so use + * {@link #getOptionsWithFilter(boolean)} if possible (filterable container + * and suitable item caption mode etc.). + * + * @return + */ + protected List<?> getFilteredOptions() { + if (null == filterstring || "".equals(filterstring) + || Filtering.FILTERINGMODE_OFF == filteringMode) { + prevfilterstring = null; + filteredOptions = new LinkedList<Object>(getItemIds()); + return filteredOptions; + } + + if (filterstring.equals(prevfilterstring)) { + return filteredOptions; + } + + Collection<?> items; + if (prevfilterstring != null + && filterstring.startsWith(prevfilterstring)) { + items = filteredOptions; + } else { + items = getItemIds(); + } + prevfilterstring = filterstring; + + filteredOptions = new LinkedList<Object>(); + for (final Iterator<?> it = items.iterator(); it.hasNext();) { + final Object itemId = it.next(); + String caption = getItemCaption(itemId); + if (caption == null || caption.equals("")) { + continue; + } else { + caption = caption.toLowerCase(); + } + switch (filteringMode) { + case Filtering.FILTERINGMODE_CONTAINS: + if (caption.indexOf(filterstring) > -1) { + filteredOptions.add(itemId); + } + break; + case Filtering.FILTERINGMODE_STARTSWITH: + default: + if (caption.startsWith(filterstring)) { + filteredOptions.add(itemId); + } + break; + } + } + + return filteredOptions; + } + + /** + * Invoked when the value of a variable has changed. + * + * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, + * java.util.Map) + */ + @Override + public void changeVariables(Object source, Map<String, Object> variables) { + // Not calling super.changeVariables due the history of select + // component hierarchy + + // Selection change + if (variables.containsKey("selected")) { + final String[] ka = (String[]) variables.get("selected"); + + // Single select mode + if (ka.length == 0) { + + // Allows deselection only if the deselected item is visible + final Object current = getValue(); + final Collection<?> visible = getVisibleItemIds(); + if (visible != null && visible.contains(current)) { + setValue(null, true); + } + } else { + final Object id = itemIdMapper.get(ka[0]); + if (id != null && id.equals(getNullSelectionItemId())) { + setValue(null, true); + } else { + setValue(id, true); + } + } + } + + String newFilter; + if ((newFilter = (String) variables.get("filter")) != null) { + // this is a filter request + currentPage = ((Integer) variables.get("page")).intValue(); + filterstring = newFilter; + if (filterstring != null) { + filterstring = filterstring.toLowerCase(); + } + requestRepaint(); + } else if (isNewItemsAllowed()) { + // New option entered (and it is allowed) + final String newitem = (String) variables.get("newitem"); + if (newitem != null && newitem.length() > 0) { + getNewItemHandler().addNewItem(newitem); + // rebuild list + filterstring = null; + prevfilterstring = null; + } + } + + if (variables.containsKey(FocusEvent.EVENT_ID)) { + fireEvent(new FocusEvent(this)); + } + if (variables.containsKey(BlurEvent.EVENT_ID)) { + fireEvent(new BlurEvent(this)); + } + + } + + @Override + @Deprecated + public void requestRepaint() { + markAsDirty(); + } + + @Override + public void setFilteringMode(int filteringMode) { + this.filteringMode = filteringMode; + } + + @Override + public int getFilteringMode() { + return filteringMode; + } + + public void addBlurListener(BlurListener listener) { + addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, + BlurListener.blurMethod); + } + + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + + @Override + public void removeBlurListener(BlurListener listener) { + removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + + @Override + public void addFocusListener(FocusListener listener) { + addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, + FocusListener.focusMethod); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + + @Override + public void removeFocusListener(FocusListener listener) { + removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); + } + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + + /** + * ComboBox does not support multi select mode. + * + * @deprecated use {@link ListSelect}, {@link OptionGroup} or + * {@link TwinColSelect} instead + * @see com.vaadin.ui.AbstractSelect#setMultiSelect(boolean) + * @throws UnsupportedOperationException + * if trying to activate multiselect mode + */ + @Deprecated + @Override + public void setMultiSelect(boolean multiSelect) { + if (multiSelect) { + throw new UnsupportedOperationException("Multiselect not supported"); + } + } + + /** + * ComboBox does not support multi select mode. + * + * @deprecated use {@link ListSelect}, {@link OptionGroup} or + * {@link TwinColSelect} instead + * + * @see com.vaadin.ui.AbstractSelect#isMultiSelect() + * + * @return false + */ + @Deprecated + @Override + public boolean isMultiSelect() { + return false; + } + + /** + * Sets whether to scroll the selected item visible (directly open the page + * on which it is) when opening the combo box popup or not. Only applies to + * single select mode. + * + * This requires finding the index of the item, which can be expensive in + * many large lazy loading containers. + * + * @param scrollToSelectedItem + * true to find the page with the selected item when opening the + * selection popup + */ + public void setScrollToSelectedItem(boolean scrollToSelectedItem) { + this.scrollToSelectedItem = scrollToSelectedItem; + } + + /** + * Returns true if the select should find the page with the selected item + * when opening the popup (single select combo box only). + * + * @see #setScrollToSelectedItem(boolean) + * + * @return true if the page with the selected item will be shown when + * opening the popup + */ + public boolean isScrollToSelectedItem() { + return scrollToSelectedItem; + } + } diff --git a/server/src/com/vaadin/ui/Component.java b/server/src/com/vaadin/ui/Component.java index 0559cc5e6a..01033ff560 100644 --- a/server/src/com/vaadin/ui/Component.java +++ b/server/src/com/vaadin/ui/Component.java @@ -23,11 +23,11 @@ import java.util.Locale; import com.vaadin.Application; import com.vaadin.event.FieldEvents; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Sizeable; -import com.vaadin.terminal.VariableOwner; -import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.ErrorMessage; +import com.vaadin.server.Resource; +import com.vaadin.server.Sizeable; +import com.vaadin.server.VariableOwner; /** * {@code Component} is the top-level interface that is and must be implemented @@ -136,8 +136,9 @@ public interface Component extends ClientConnector, Sizeable, Serializable { public void setStyleName(String style); /** - * Adds a style name to component. The style name will be rendered as a HTML - * class name, which can be used in a CSS definition. + * Adds one or more style names to this component. Multiple styles can be + * specified as a space-separated list of style names. The style name will + * be rendered as a HTML class name, which can be used in a CSS definition. * * <pre> * Label label = new Label("This text has style"); @@ -462,7 +463,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { * * <p> * The image is loaded by the browser from a resource, typically a - * {@link com.vaadin.terminal.ThemeResource}. + * {@link com.vaadin.server.ThemeResource}. * </p> * * <pre> diff --git a/server/src/com/vaadin/ui/ComponentContainer.java b/server/src/com/vaadin/ui/ComponentContainer.java index c2a75f9313..cee6d7300b 100644 --- a/server/src/com/vaadin/ui/ComponentContainer.java +++ b/server/src/com/vaadin/ui/ComponentContainer.java @@ -94,6 +94,13 @@ public interface ComponentContainer extends HasComponents { * @param listener * the listener to add. */ + public void addComponentAttachListener(ComponentAttachListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentAttachListener(ComponentAttachListener)} + **/ + @Deprecated public void addListener(ComponentAttachListener listener); /** @@ -102,16 +109,37 @@ public interface ComponentContainer extends HasComponents { * @param listener * the listener to removed. */ + public void removeComponentAttachListener(ComponentAttachListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentAttachListener(ComponentAttachListener)} + **/ + @Deprecated public void removeListener(ComponentAttachListener listener); /** * Listens the component detach events. */ + public void addComponentDetachListener(ComponentDetachListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentDetachListener(ComponentDetachListener)} + **/ + @Deprecated public void addListener(ComponentDetachListener listener); /** * Stops the listening component detach events. */ + public void removeComponentDetachListener(ComponentDetachListener listener); + + /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentDetachListener(ComponentDetachListener)} + **/ + @Deprecated public void removeListener(ComponentDetachListener listener); /** diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index b44189f838..3140c26525 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -25,9 +25,10 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import com.vaadin.terminal.AbstractClientConnector; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; -import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.server.AbstractClientConnector; +import com.vaadin.server.AbstractCommunicationManager; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.GlobalResourceHandler; /** * A class which takes care of book keeping of {@link ClientConnector}s for a @@ -42,7 +43,7 @@ import com.vaadin.terminal.gwt.server.ClientConnector; * client when the following response is sent. A connector is dirty when an * operation has been performed on it on the server and as a result of this * operation new information needs to be sent to its - * {@link com.vaadin.terminal.gwt.client.ServerConnector}. + * {@link com.vaadin.client.ServerConnector}. * </p> * * @author Vaadin Ltd @@ -141,11 +142,22 @@ public class ConnectorTracker implements Serializable { getLogger().fine( "Unregistered " + connector.getClass().getSimpleName() + " (" + connectorId + ")"); + + removeFromGlobalResourceHandler(connector); connectorIdToConnector.remove(connectorId); uninitializedConnectors.remove(connector); diffStates.remove(connector); } + private void removeFromGlobalResourceHandler(ClientConnector connector) { + GlobalResourceHandler globalResourceHandler = uI.getApplication() + .getGlobalResourceHandler(false); + // Nothing to do if there is no handler + if (globalResourceHandler != null) { + globalResourceHandler.unregisterConnector(connector); + } + } + /** * Checks whether the given connector has already been initialized in the * browser. The given connector should be registered with this connector @@ -224,6 +236,8 @@ public class ConnectorTracker implements Serializable { "cleanConnectorMap unregistered connector " + getConnectorAndParentInfo(connector) + "). This should have been done when the connector was detached."); + + removeFromGlobalResourceHandler(connector); uninitializedConnectors.remove(connector); diffStates.remove(connector); iterator.remove(); diff --git a/server/src/com/vaadin/ui/CssLayout.java b/server/src/com/vaadin/ui/CssLayout.java index b16bcf31df..b63c8573ba 100644 --- a/server/src/com/vaadin/ui/CssLayout.java +++ b/server/src/com/vaadin/ui/CssLayout.java @@ -281,19 +281,37 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { } @Override - public void addListener(LayoutClickListener listener) { + public void addLayoutClickListener(LayoutClickListener listener) { addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener, LayoutClickListener.clickMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void addListener(LayoutClickListener listener) { + addLayoutClickListener(listener); + } + @Override - public void removeListener(LayoutClickListener listener) { + public void removeLayoutClickListener(LayoutClickListener listener) { removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeLayoutClickListener(LayoutClickListener)} + **/ + @Deprecated + public void removeListener(LayoutClickListener listener) { + removeLayoutClickListener(listener); + } + + /** * Returns the index of the given component. * * @param component diff --git a/server/src/com/vaadin/ui/CustomField.java b/server/src/com/vaadin/ui/CustomField.java index 9ac5e2defb..7bb6e66cf9 100644 --- a/server/src/com/vaadin/ui/CustomField.java +++ b/server/src/com/vaadin/ui/CustomField.java @@ -221,27 +221,64 @@ public abstract class CustomField<T> extends AbstractField<T> implements } @Override - public void addListener(ComponentAttachListener listener) { + public void addComponentAttachListener(ComponentAttachListener listener) { addListener(ComponentContainer.ComponentAttachEvent.class, listener, COMPONENT_ATTACHED_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentAttachListener(com.vaadin.ui.ComponentContainer.ComponentAttachListener)} + **/ + @Deprecated + public void addListener(ComponentAttachListener listener) { + addComponentAttachListener(listener); + } + @Override - public void removeListener(ComponentAttachListener listener) { + public void removeComponentAttachListener(ComponentAttachListener listener) { removeListener(ComponentContainer.ComponentAttachEvent.class, listener, COMPONENT_ATTACHED_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentAttachListener(com.vaadin.ui.ComponentContainer.ComponentAttachListener)} + **/ + @Deprecated + public void removeListener(ComponentAttachListener listener) { + removeComponentAttachListener(listener); + } + @Override - public void addListener(ComponentDetachListener listener) { + public void addComponentDetachListener(ComponentDetachListener listener) { // content never detached } + /** + * @deprecated Since 7.0, replaced by + * {@link #addComponentDetachListener(com.vaadin.ui.ComponentContainer.ComponentDetachListener)} + **/ + @Deprecated + public void addListener(ComponentDetachListener listener) { + addComponentDetachListener(listener); + + } + @Override - public void removeListener(ComponentDetachListener listener) { + public void removeComponentDetachListener(ComponentDetachListener listener) { // content never detached } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeComponentDetachListener(com.vaadin.ui.ComponentContainer.ComponentDetachListener)} + **/ + @Deprecated + public void removeListener(ComponentDetachListener listener) { + removeComponentDetachListener(listener); + } + @Override public boolean isComponentVisible(Component childComponent) { return true; diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java index 54308b99c3..f747b6ff3b 100644 --- a/server/src/com/vaadin/ui/CustomLayout.java +++ b/server/src/com/vaadin/ui/CustomLayout.java @@ -24,11 +24,11 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import com.vaadin.server.JsonPaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.customlayout.CustomLayoutState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.server.JsonPaintTarget; /** * <p> @@ -58,7 +58,7 @@ import com.vaadin.terminal.gwt.server.JsonPaintTarget; * @since 3.0 */ @SuppressWarnings("serial") -public class CustomLayout extends AbstractLayout implements Vaadin6Component { +public class CustomLayout extends AbstractLayout implements LegacyComponent { private static final int BUFFER_SIZE = 10000; diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java index 828fa3b21d..712034a562 100644 --- a/server/src/com/vaadin/ui/DateField.java +++ b/server/src/com/vaadin/ui/DateField.java @@ -36,10 +36,10 @@ import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.datefield.DateFieldConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; /** * <p> @@ -61,7 +61,7 @@ import com.vaadin.terminal.Vaadin6Component; */ @SuppressWarnings("serial") public class DateField extends AbstractField<Date> implements - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, Vaadin6Component { + FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, LegacyComponent { /** * Resolutions for DateFields @@ -741,28 +741,63 @@ public class DateField extends AbstractField<Date> implements } @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + + /** * Checks whether ISO 8601 week numbers are shown in the date selector. * * @return true if week numbers are shown, false otherwise. diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java index ec805ecf46..d3f3e23448 100644 --- a/server/src/com/vaadin/ui/DragAndDropWrapper.java +++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java @@ -29,18 +29,18 @@ import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.TargetDetails; import com.vaadin.event.dd.TargetDetailsImpl; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.StreamVariable; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.dd.HorizontalDropLocation; import com.vaadin.shared.ui.dd.VerticalDropLocation; import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.StreamVariable; -import com.vaadin.terminal.Vaadin6Component; @SuppressWarnings("serial") public class DragAndDropWrapper extends CustomComponent implements DropTarget, - DragSource, Vaadin6Component { + DragSource, LegacyComponent { public class WrapperTransferable extends TransferableImpl { @@ -212,7 +212,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, @Override public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented + // TODO Remove once LegacyComponent is no longer implemented } @Override diff --git a/server/src/com/vaadin/ui/Embedded.java b/server/src/com/vaadin/ui/Embedded.java index 41b93d0b27..b3afb52249 100644 --- a/server/src/com/vaadin/ui/Embedded.java +++ b/server/src/com/vaadin/ui/Embedded.java @@ -22,23 +22,27 @@ import java.util.Map; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.embedded.EmbeddedConstants; import com.vaadin.shared.ui.embedded.EmbeddedServerRpc; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; /** * Component for embedding external objects. + * <p> + * As of Vaadin 7.0, the {@link Image}, {@link Flash}, and + * {@link EmbeddedBrowser} components should be used instead of + * <code>Embedded</code> whenever appropriate. * * @author Vaadin Ltd. * @since 3.0 */ @SuppressWarnings("serial") -public class Embedded extends AbstractComponent implements Vaadin6Component { +public class Embedded extends AbstractComponent implements LegacyComponent { /** * General object type. @@ -47,12 +51,18 @@ public class Embedded extends AbstractComponent implements Vaadin6Component { /** * Image types. + * + * @deprecated As of 7.0, use the {@link Image} component instead. */ + @Deprecated public static final int TYPE_IMAGE = 1; /** * Browser ("iframe") type. + * + * @deprecated As of 7.0, use the {@link EmbeddedBrowser} component instead. */ + @Deprecated public static final int TYPE_BROWSER = 2; /** @@ -452,9 +462,9 @@ public class Embedded extends AbstractComponent implements Vaadin6Component { * <p> * This can be one of the following: * <ul> - * <li>TYPE_OBJECT <i>(This is the default)</i> - * <li>TYPE_IMAGE - * <li>TYPE_BROWSER + * <li>{@link #TYPE_OBJECT} <i>(This is the default)</i> + * <li>{@link #TYPE_IMAGE} <i>(Deprecated)</i> + * <li>{@link #TYPE_BROWSER} <i>(Deprecated)</i> * </ul> * </p> * @@ -516,26 +526,44 @@ public class Embedded extends AbstractComponent implements Vaadin6Component { * @param listener * The listener to add */ - public void addListener(ClickListener listener) { + public void addClickListener(ClickListener listener) { addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener, ClickListener.clickMethod); } /** + * @deprecated Since 7.0, replaced by + * {@link #addClickListener(ClickListener)} + **/ + @Deprecated + public void addListener(ClickListener listener) { + addClickListener(listener); + } + + /** * Remove a click listener from the component. The listener should earlier * have been added using {@link #addListener(ClickListener)}. * * @param listener * The listener to remove */ - public void removeListener(ClickListener listener) { + public void removeClickListener(ClickListener listener) { removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeClickListener(ClickListener)} + **/ + @Deprecated + public void removeListener(ClickListener listener) { + removeClickListener(listener); + } + @Override public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented + // TODO Remove once LegacyComponent is no longer implemented } } diff --git a/server/src/com/vaadin/ui/Form.java b/server/src/com/vaadin/ui/Form.java index 55404b2e6b..7e77117acb 100644 --- a/server/src/com/vaadin/ui/Form.java +++ b/server/src/com/vaadin/ui/Form.java @@ -36,14 +36,14 @@ import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.Action.ShortcutNotifier; import com.vaadin.event.ActionManager; +import com.vaadin.server.AbstractErrorMessage; +import com.vaadin.server.CompositeErrorMessage; +import com.vaadin.server.ErrorMessage; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.UserError; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.form.FormState; -import com.vaadin.terminal.AbstractErrorMessage; -import com.vaadin.terminal.CompositeErrorMessage; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.UserError; -import com.vaadin.terminal.Vaadin6Component; /** * Form component provides easy way of creating and managing sets fields. @@ -79,7 +79,7 @@ import com.vaadin.terminal.Vaadin6Component; @Deprecated public class Form extends AbstractField<Object> implements Item.Editor, Buffered, Item, Validatable, Action.Notifier, HasComponents, - Vaadin6Component { + LegacyComponent { private Object propertyValue; diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java index 3870b71611..21602c6802 100644 --- a/server/src/com/vaadin/ui/GridLayout.java +++ b/server/src/com/vaadin/ui/GridLayout.java @@ -27,16 +27,16 @@ import java.util.Map.Entry; import com.vaadin.event.LayoutEvents.LayoutClickEvent; import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.LayoutEvents.LayoutClickNotifier; +import com.vaadin.server.LegacyPaint; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; import com.vaadin.shared.ui.gridlayout.GridLayoutState; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; /** * A layout where the components are laid out on a grid using cell coordinates. @@ -65,7 +65,7 @@ import com.vaadin.terminal.Vaadin6Component; @SuppressWarnings("serial") public class GridLayout extends AbstractLayout implements Layout.AlignmentHandler, Layout.SpacingHandler, Layout.MarginHandler, - LayoutClickNotifier, Vaadin6Component { + LayoutClickNotifier, LegacyComponent { private GridLayoutServerRpc rpc = new GridLayoutServerRpc() { @@ -447,7 +447,7 @@ public class GridLayout extends AbstractLayout implements @Override public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented + // TODO Remove once LegacyComponent is no longer implemented } /** @@ -1354,18 +1354,38 @@ public class GridLayout extends AbstractLayout implements } @Override - public void addListener(LayoutClickListener listener) { + public void addLayoutClickListener(LayoutClickListener listener) { addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener, LayoutClickListener.clickMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addLayoutClickListener(LayoutClickListener)} + **/ @Override - public void removeListener(LayoutClickListener listener) { + @Deprecated + public void addListener(LayoutClickListener listener) { + addLayoutClickListener(listener); + } + + @Override + public void removeLayoutClickListener(LayoutClickListener listener) { removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER, LayoutClickEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeLayoutClickListener(LayoutClickListener)} + **/ + @Override + @Deprecated + public void removeListener(LayoutClickListener listener) { + removeLayoutClickListener(listener); + } + /* * (non-Javadoc) * diff --git a/server/src/com/vaadin/ui/Html5File.java b/server/src/com/vaadin/ui/Html5File.java index 596f83a1d8..47af708160 100644 --- a/server/src/com/vaadin/ui/Html5File.java +++ b/server/src/com/vaadin/ui/Html5File.java @@ -18,7 +18,7 @@ package com.vaadin.ui; import java.io.Serializable; import com.vaadin.event.dd.DropHandler; -import com.vaadin.terminal.StreamVariable; +import com.vaadin.server.StreamVariable; /** * {@link DragAndDropWrapper} can receive also files from client computer if diff --git a/server/src/com/vaadin/ui/Image.java b/server/src/com/vaadin/ui/Image.java index b0dbc9e629..178e557cf3 100644 --- a/server/src/com/vaadin/ui/Image.java +++ b/server/src/com/vaadin/ui/Image.java @@ -6,11 +6,11 @@ package com.vaadin.ui; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.server.Resource; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.image.ImageServerRpc; import com.vaadin.shared.ui.image.ImageState; -import com.vaadin.terminal.Resource; /** * Component for embedding images. @@ -66,28 +66,46 @@ public class Image extends AbstractEmbedded { } /** + * @deprecated As of 7.0.0, use {@link #addClickListener(ClickListener)} + * instead + */ + @Deprecated + public void addListener(ClickListener listener) { + addClickListener(listener); + } + + /** * Add a click listener to the component. The listener is called whenever * the user clicks inside the component. Depending on the content the event * may be blocked and in that case no event is fired. * - * Use {@link #removeListener(ClickListener)} to remove the listener. + * Use {@link #removeClickListener(ClickListener)} to remove the listener. * * @param listener * The listener to add */ - public void addListener(ClickListener listener) { + public void addClickListener(ClickListener listener) { addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener, ClickListener.clickMethod); } /** + * @deprecated As of 7.0.0, use {@link #removeClickListener(ClickListener)} + * instead + */ + @Deprecated + public void removeListener(ClickListener listener) { + removeClickListener(listener); + } + + /** * Remove a click listener from the component. The listener should earlier - * have been added using {@link #addListener(ClickListener)}. + * have been added using {@link #addClickListener(ClickListener)}. * * @param listener * The listener to remove */ - public void removeListener(ClickListener listener) { + public void removeClickListener(ClickListener listener) { removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener); } diff --git a/server/src/com/vaadin/ui/JavaScript.java b/server/src/com/vaadin/ui/JavaScript.java index e34ccae82a..f3e8564fab 100644 --- a/server/src/com/vaadin/ui/JavaScript.java +++ b/server/src/com/vaadin/ui/JavaScript.java @@ -21,11 +21,11 @@ import java.util.Map; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; +import com.vaadin.server.AbstractExtension; +import com.vaadin.server.Page; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc; import com.vaadin.shared.extension.javascriptmanager.JavaScriptManagerState; -import com.vaadin.terminal.AbstractExtension; -import com.vaadin.terminal.Page; /** * Provides access to JavaScript functionality in the web browser. To get an diff --git a/server/src/com/vaadin/ui/JavaScriptFunction.java b/server/src/com/vaadin/ui/JavaScriptFunction.java index 3a17fef995..ebb5e2c073 100644 --- a/server/src/com/vaadin/ui/JavaScriptFunction.java +++ b/server/src/com/vaadin/ui/JavaScriptFunction.java @@ -20,7 +20,7 @@ import java.io.Serializable; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; -import com.vaadin.terminal.AbstractJavaScriptExtension; +import com.vaadin.server.AbstractJavaScriptExtension; /** * Defines a method that is called by a client-side JavaScript function. When diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java index 81a343e937..ff4a5dcb07 100644 --- a/server/src/com/vaadin/ui/Label.java +++ b/server/src/com/vaadin/ui/Label.java @@ -349,11 +349,20 @@ public class Label extends AbstractComponent implements Property<String>, * @see com.vaadin.data.Property.ValueChangeNotifier#addListener(com.vaadin.data.Property.ValueChangeListener) */ @Override - public void addListener(Property.ValueChangeListener listener) { + public void addValueChangeListener(Property.ValueChangeListener listener) { addListener(Label.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void addListener(Property.ValueChangeListener listener) { + addValueChangeListener(listener); + } + + /** * Removes the value change listener. * * @param listener @@ -361,12 +370,21 @@ public class Label extends AbstractComponent implements Property<String>, * @see com.vaadin.data.Property.ValueChangeNotifier#removeListener(com.vaadin.data.Property.ValueChangeListener) */ @Override - public void removeListener(Property.ValueChangeListener listener) { + public void removeValueChangeListener(Property.ValueChangeListener listener) { removeListener(Label.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Deprecated + public void removeListener(Property.ValueChangeListener listener) { + removeValueChangeListener(listener); + } + + /** * Emits the options change event. */ protected void fireValueChange() { diff --git a/server/src/com/vaadin/ui/Link.java b/server/src/com/vaadin/ui/Link.java index f98a2b0d2d..a2737e4483 100644 --- a/server/src/com/vaadin/ui/Link.java +++ b/server/src/com/vaadin/ui/Link.java @@ -18,11 +18,12 @@ package com.vaadin.ui; import java.util.Map; +import com.vaadin.server.LegacyComponent; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; import com.vaadin.shared.ui.BorderStyle; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; +import com.vaadin.shared.ui.link.LinkConstants; /** * Link is used to create external or internal URL links. @@ -31,7 +32,7 @@ import com.vaadin.terminal.Vaadin6Component; * @since 3.0 */ @SuppressWarnings("serial") -public class Link extends AbstractComponent implements Vaadin6Component { +public class Link extends AbstractComponent implements LegacyComponent { /* Target window border type constant: No window border */ @Deprecated @@ -45,8 +46,6 @@ public class Link extends AbstractComponent implements Vaadin6Component { @Deprecated public static final BorderStyle TARGET_BORDER_DEFAULT = BorderStyle.DEFAULT; - private Resource resource = null; - private String targetName; private BorderStyle targetBorder = BorderStyle.DEFAULT; @@ -70,7 +69,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { */ public Link(String caption, Resource resource) { setCaption(caption); - this.resource = resource; + setResource(resource); } /** @@ -94,7 +93,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { public Link(String caption, Resource resource, String targetName, int width, int height, BorderStyle border) { setCaption(caption); - this.resource = resource; + setResource(resource); setTargetName(targetName); setTargetWidth(width); setTargetHeight(height); @@ -111,10 +110,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { */ @Override public void paintContent(PaintTarget target) throws PaintException { - - if (resource != null) { - target.addAttribute("src", resource); - } else { + if (getResource() == null) { return; } @@ -230,7 +226,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { * @return the Resource. */ public Resource getResource() { - return resource; + return getResource(LinkConstants.HREF_RESOURCE); } /** @@ -240,12 +236,11 @@ public class Link extends AbstractComponent implements Vaadin6Component { * the resource to set. */ public void setResource(Resource resource) { - this.resource = resource; - markAsDirty(); + setResource(LinkConstants.HREF_RESOURCE, resource); } @Override public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented + // TODO Remove once LegacyComponent is no longer implemented } } diff --git a/server/src/com/vaadin/ui/ListSelect.java b/server/src/com/vaadin/ui/ListSelect.java index da78e24fa8..90e1c16a4d 100644 --- a/server/src/com/vaadin/ui/ListSelect.java +++ b/server/src/com/vaadin/ui/ListSelect.java @@ -19,8 +19,8 @@ package com.vaadin.ui; import java.util.Collection; import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * This is a simple list select without, for instance, support for new items, diff --git a/server/src/com/vaadin/ui/LoginForm.java b/server/src/com/vaadin/ui/LoginForm.java index 1c154699d8..abcc7ff607 100644 --- a/server/src/com/vaadin/ui/LoginForm.java +++ b/server/src/com/vaadin/ui/LoginForm.java @@ -25,12 +25,12 @@ import java.util.Iterator; import java.util.Map; import com.vaadin.Application; +import com.vaadin.server.ConnectorResource; +import com.vaadin.server.DownloadStream; +import com.vaadin.server.RequestHandler; +import com.vaadin.server.WrappedRequest; +import com.vaadin.server.WrappedResponse; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.DownloadStream; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; /** * LoginForm is a Vaadin component to handle common problem among Ajax @@ -58,23 +58,7 @@ public class LoginForm extends CustomComponent { private Embedded iframe = new Embedded(); - private ApplicationResource loginPage = new ApplicationResource() { - - @Override - public Application getApplication() { - return LoginForm.this.getApplication(); - } - - @Override - public int getBufferSize() { - return getLoginHTML().length; - } - - @Override - public long getCacheTime() { - return -1; - } - + private ConnectorResource loginPage = new ConnectorResource() { @Override public String getFilename() { return "login"; @@ -82,8 +66,13 @@ public class LoginForm extends CustomComponent { @Override public DownloadStream getStream() { - return new DownloadStream(new ByteArrayInputStream(getLoginHTML()), - getMIMEType(), getFilename()); + byte[] loginHTML = getLoginHTML(); + DownloadStream downloadStream = new DownloadStream( + new ByteArrayInputStream(loginHTML), getMIMEType(), + getFilename()); + downloadStream.setBufferSize(loginHTML.length); + downloadStream.setCacheTime(-1); + return downloadStream; } @Override @@ -197,14 +186,12 @@ public class LoginForm extends CustomComponent { @Override public void attach() { super.attach(); - getApplication().addResource(loginPage); getApplication().addRequestHandler(requestHandler); iframe.setSource(loginPage); } @Override public void detach() { - getApplication().removeResource(loginPage); getApplication().removeRequestHandler(requestHandler); super.detach(); @@ -271,19 +258,37 @@ public class LoginForm extends CustomComponent { * * @param listener */ - public void addListener(LoginListener listener) { + public void addLoginListener(LoginListener listener) { addListener(LoginEvent.class, listener, ON_LOGIN_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addLoginListener(LoginListener)} + **/ + @Deprecated + public void addListener(LoginListener listener) { + addLoginListener(listener); + } + + /** * Removes LoginListener * * @param listener */ - public void removeListener(LoginListener listener) { + public void removeLoginListener(LoginListener listener) { removeListener(LoginEvent.class, listener, ON_LOGIN_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeLoginListener(LoginListener)} + **/ + @Deprecated + public void removeListener(LoginListener listener) { + removeLoginListener(listener); + } + @Override public void setWidth(float width, Unit unit) { super.setWidth(width, unit); diff --git a/server/src/com/vaadin/ui/MenuBar.java b/server/src/com/vaadin/ui/MenuBar.java index 51c06cf934..d948ef813a 100644 --- a/server/src/com/vaadin/ui/MenuBar.java +++ b/server/src/com/vaadin/ui/MenuBar.java @@ -22,11 +22,11 @@ import java.util.List; import java.util.Map; import java.util.Stack; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.menubar.MenuBarConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; /** * <p> @@ -36,7 +36,7 @@ import com.vaadin.terminal.Vaadin6Component; * </p> */ @SuppressWarnings("serial") -public class MenuBar extends AbstractComponent implements Vaadin6Component { +public class MenuBar extends AbstractComponent implements LegacyComponent { // Items of the top-level menu private final List<MenuItem> menuItems; diff --git a/server/src/com/vaadin/ui/NativeSelect.java b/server/src/com/vaadin/ui/NativeSelect.java index c2969874b0..8006813276 100644 --- a/server/src/com/vaadin/ui/NativeSelect.java +++ b/server/src/com/vaadin/ui/NativeSelect.java @@ -19,8 +19,8 @@ package com.vaadin.ui; import java.util.Collection; import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * This is a simple drop-down select without, for instance, support for diff --git a/server/src/com/vaadin/ui/Notification.java b/server/src/com/vaadin/ui/Notification.java index 22ad31dffe..758d2c86a3 100644 --- a/server/src/com/vaadin/ui/Notification.java +++ b/server/src/com/vaadin/ui/Notification.java @@ -18,9 +18,9 @@ package com.vaadin.ui; import java.io.Serializable; +import com.vaadin.server.Page; +import com.vaadin.server.Resource; import com.vaadin.shared.Position; -import com.vaadin.terminal.Page; -import com.vaadin.terminal.Resource; /** * A notification message, used to display temporary messages to the user - for diff --git a/server/src/com/vaadin/ui/OptionGroup.java b/server/src/com/vaadin/ui/OptionGroup.java index 12507442c9..983a01381d 100644 --- a/server/src/com/vaadin/ui/OptionGroup.java +++ b/server/src/com/vaadin/ui/OptionGroup.java @@ -27,9 +27,9 @@ import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.optiongroup.OptionGroupConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; /** * Configures select to be used as an option group. @@ -89,28 +89,63 @@ public class OptionGroup extends AbstractSelect implements } @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + @Override protected void setValue(Object newValue, boolean repaintIsNotNeeded) { if (repaintIsNotNeeded) { diff --git a/server/src/com/vaadin/ui/Panel.java b/server/src/com/vaadin/ui/Panel.java index 00810b83db..6f399bcc19 100644 --- a/server/src/com/vaadin/ui/Panel.java +++ b/server/src/com/vaadin/ui/Panel.java @@ -25,14 +25,14 @@ import com.vaadin.event.Action.Handler; import com.vaadin.event.ActionManager; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Scrollable; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.panel.PanelServerRpc; import com.vaadin.shared.ui.panel.PanelState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Scrollable; -import com.vaadin.terminal.Vaadin6Component; import com.vaadin.ui.Component.Focusable; /** @@ -45,7 +45,7 @@ import com.vaadin.ui.Component.Focusable; public class Panel extends AbstractComponentContainer implements Scrollable, ComponentContainer.ComponentAttachListener, ComponentContainer.ComponentDetachListener, Action.Notifier, Focusable, - Vaadin6Component { + LegacyComponent { /** * Content of the panel. @@ -195,8 +195,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * (non-Javadoc) * - * @see - * com.vaadin.terminal.Vaadin6Component#paintContent(com.vaadin.terminal + * @see com.vaadin.server.LegacyComponent#paintContent(com.vaadin.server * .PaintTarget) */ @Override @@ -250,7 +249,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, * Called when one or more variables handled by the implementing class are * changed. * - * @see com.vaadin.terminal.VariableOwner#changeVariables(Object, Map) + * @see com.vaadin.server.VariableOwner#changeVariables(Object, Map) */ @Override @SuppressWarnings("unchecked") @@ -289,7 +288,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * (non-Javadoc) * - * @see com.vaadin.terminal.Scrollable#setScrollable(boolean) + * @see com.vaadin.server.Scrollable#setScrollable(boolean) */ @Override public int getScrollLeft() { @@ -299,7 +298,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * (non-Javadoc) * - * @see com.vaadin.terminal.Scrollable#setScrollable(boolean) + * @see com.vaadin.server.Scrollable#setScrollable(boolean) */ @Override public int getScrollTop() { @@ -309,7 +308,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * (non-Javadoc) * - * @see com.vaadin.terminal.Scrollable#setScrollLeft(int) + * @see com.vaadin.server.Scrollable#setScrollLeft(int) */ @Override public void setScrollLeft(int scrollLeft) { @@ -323,7 +322,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * (non-Javadoc) * - * @see com.vaadin.terminal.Scrollable#setScrollTop(int) + * @see com.vaadin.server.Scrollable#setScrollTop(int) */ @Override public void setScrollTop(int scrollTop) { @@ -432,24 +431,42 @@ public class Panel extends AbstractComponentContainer implements Scrollable, * @param listener * The listener to add */ - public void addListener(ClickListener listener) { + public void addClickListener(ClickListener listener) { addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener, ClickListener.clickMethod); } /** + * @deprecated Since 7.0, replaced by + * {@link #addClickListener(ClickListener)} + **/ + @Deprecated + public void addListener(ClickListener listener) { + addClickListener(listener); + } + + /** * Remove a click listener from the Panel. The listener should earlier have * been added using {@link #addListener(ClickListener)}. * * @param listener * The listener to remove */ - public void removeListener(ClickListener listener) { + public void removeClickListener(ClickListener listener) { removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeClickListener(ClickListener)} + **/ + @Deprecated + public void removeListener(ClickListener listener) { + addClickListener(listener); + } + + /** * {@inheritDoc} */ @Override diff --git a/server/src/com/vaadin/ui/PopupDateField.java b/server/src/com/vaadin/ui/PopupDateField.java index acff49a142..39e0578301 100644 --- a/server/src/com/vaadin/ui/PopupDateField.java +++ b/server/src/com/vaadin/ui/PopupDateField.java @@ -19,8 +19,8 @@ package com.vaadin.ui; import java.util.Date; import com.vaadin.data.Property; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; /** * <p> diff --git a/server/src/com/vaadin/ui/PopupView.java b/server/src/com/vaadin/ui/PopupView.java index 786257c240..8d6d28e121 100644 --- a/server/src/com/vaadin/ui/PopupView.java +++ b/server/src/com/vaadin/ui/PopupView.java @@ -20,10 +20,10 @@ import java.lang.reflect.Method; import java.util.Iterator; import java.util.Map; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; +import com.vaadin.server.LegacyPaint; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; /** * @@ -36,7 +36,7 @@ import com.vaadin.terminal.Vaadin6Component; */ @SuppressWarnings("serial") public class PopupView extends AbstractComponentContainer implements - Vaadin6Component { + LegacyComponent { private Content content; private boolean hideOnMouseOut; @@ -309,7 +309,7 @@ public class PopupView extends AbstractComponentContainer implements /** * Paint (serialize) the component for the client. * - * @see com.vaadin.ui.AbstractComponent#paintContent(com.vaadin.terminal.PaintTarget) + * @see com.vaadin.ui.AbstractComponent#paintContent(com.vaadin.server.PaintTarget) */ @Override public void paintContent(PaintTarget target) throws PaintException { @@ -377,12 +377,21 @@ public class PopupView extends AbstractComponentContainer implements * @see #removeListener(PopupVisibilityListener) * */ - public void addListener(PopupVisibilityListener listener) { + public void addPopupVisibilityListener(PopupVisibilityListener listener) { addListener(PopupVisibilityEvent.class, listener, POPUP_VISIBILITY_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addPopupVisibilityListener(PopupVisibilityListener)} + **/ + @Deprecated + public void addListener(PopupVisibilityListener listener) { + addPopupVisibilityListener(listener); + } + + /** * Removes a previously added listener, so that it no longer receives events * when the visibility of the popup changes. * @@ -391,12 +400,21 @@ public class PopupView extends AbstractComponentContainer implements * @see PopupVisibilityListener * @see #addListener(PopupVisibilityListener) */ - public void removeListener(PopupVisibilityListener listener) { + public void removePopupVisibilityListener(PopupVisibilityListener listener) { removeListener(PopupVisibilityEvent.class, listener, POPUP_VISIBILITY_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removePopupVisibilityListener(PopupVisibilityListener)} + **/ + @Deprecated + public void removeListener(PopupVisibilityListener listener) { + removePopupVisibilityListener(listener); + } + + /** * This event is received by the PopupVisibilityListeners when the * visibility of the popup changes. You can get the new visibility directly * with {@link #isPopupVisible()}, or get the PopupView that produced the diff --git a/server/src/com/vaadin/ui/ProgressIndicator.java b/server/src/com/vaadin/ui/ProgressIndicator.java index 528c404ab9..7558ff0e43 100644 --- a/server/src/com/vaadin/ui/ProgressIndicator.java +++ b/server/src/com/vaadin/ui/ProgressIndicator.java @@ -20,9 +20,9 @@ import java.util.Map; import com.vaadin.data.Property; import com.vaadin.data.util.ObjectProperty; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; /** * <code>ProgressIndicator</code> is component that shows user state of a @@ -38,7 +38,7 @@ import com.vaadin.terminal.Vaadin6Component; */ @SuppressWarnings("serial") public class ProgressIndicator extends AbstractField<Number> implements - Property.Viewer, Property.ValueChangeListener, Vaadin6Component { + Property.Viewer, Property.ValueChangeListener, LegacyComponent { /** * Content mode, where the label contains only plain text. The getValue() @@ -260,7 +260,7 @@ public class ProgressIndicator extends AbstractField<Number> implements @Override public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented + // TODO Remove once LegacyComponent is no longer implemented } diff --git a/server/src/com/vaadin/ui/RichTextArea.java b/server/src/com/vaadin/ui/RichTextArea.java index 51caa82136..261701b835 100644 --- a/server/src/com/vaadin/ui/RichTextArea.java +++ b/server/src/com/vaadin/ui/RichTextArea.java @@ -19,9 +19,9 @@ package com.vaadin.ui; import java.util.Map; import com.vaadin.data.Property; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; /** * A simple RichTextArea to edit HTML format text. @@ -31,7 +31,7 @@ import com.vaadin.terminal.Vaadin6Component; * into length of field. */ public class RichTextArea extends AbstractField<String> implements - Vaadin6Component { + LegacyComponent { /** * Null representation. diff --git a/server/src/com/vaadin/ui/Select.java b/server/src/com/vaadin/ui/Select.java index 6ff7c9c9bc..ef8ba6d307 100644 --- a/server/src/com/vaadin/ui/Select.java +++ b/server/src/com/vaadin/ui/Select.java @@ -16,25 +16,9 @@ package com.vaadin.ui; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; import com.vaadin.data.Container; -import com.vaadin.data.util.filter.SimpleStringFilter; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; /** * <p> @@ -51,59 +35,10 @@ import com.vaadin.terminal.Resource; * * @author Vaadin Ltd. * @since 3.0 + * @deprecated as of 7.0. Use {@link ComboBox} instead. */ -@SuppressWarnings("serial") -public class Select extends AbstractSelect implements AbstractSelect.Filtering, - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { - - /** - * Holds value of property pageLength. 0 disables paging. - */ - protected int pageLength = 10; - - private int columns = 0; - - // Current page when the user is 'paging' trough options - private int currentPage = -1; - - private int filteringMode = FILTERINGMODE_STARTSWITH; - - private String filterstring; - private String prevfilterstring; - - /** - * Number of options that pass the filter, excluding the null item if any. - */ - private int filteredSize; - - /** - * Cache of filtered options, used only by the in-memory filtering system. - */ - private List<Object> filteredOptions; - - /** - * Flag to indicate that request repaint is called by filter request only - */ - private boolean optionRequest; - - /** - * True if the container is being filtered temporarily and item set change - * notifications should be suppressed. - */ - private boolean filteringContainer; - - /** - * Flag to indicate whether to scroll the selected item visible (select the - * page on which it is) when opening the popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - */ - private boolean scrollToSelectedItem = true; - - /* Constructors */ - +@Deprecated +public class Select extends ComboBox { /* Component methods */ public Select() { @@ -122,652 +57,4 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, super(caption); } - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (isMultiSelect()) { - // background compatibility hack. This object shouldn't be used for - // multiselect lists anymore (ListSelect instead). This fallbacks to - // a simpler paint method in super class. - super.paintContent(target); - // Fix for #4553 - target.addAttribute("type", "legacy-multi"); - return; - } - - // clear caption change listeners - getCaptionChangeListener().clear(); - - // The tab ordering number - if (getTabIndex() != 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // If the field is modified, but not committed, set modified attribute - if (isModified()) { - target.addAttribute("modified", true); - } - - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - - boolean needNullSelectOption = false; - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - needNullSelectOption = (getNullSelectionItemId() == null); - if (!needNullSelectOption) { - target.addAttribute("nullselectitem", true); - } - } - - // Constructs selected keys array - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set<?>) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null - && getNullSelectionItemId() == null ? 0 : 1)]; - } - - target.addAttribute("pagelength", pageLength); - - target.addAttribute("filteringmode", getFilteringMode()); - - // Paints the options and create array of selected id keys - int keyIndex = 0; - - target.startTag("options"); - - if (currentPage < 0) { - optionRequest = false; - currentPage = 0; - filterstring = ""; - } - - boolean nullFilteredOut = filterstring != null - && !"".equals(filterstring) - && filteringMode != FILTERINGMODE_OFF; - // null option is needed and not filtered out, even if not on current - // page - boolean nullOptionVisible = needNullSelectOption && !nullFilteredOut; - - // first try if using container filters is possible - List<?> options = getOptionsWithFilter(nullOptionVisible); - if (null == options) { - // not able to use container filters, perform explicit in-memory - // filtering - options = getFilteredOptions(); - filteredSize = options.size(); - options = sanitetizeList(options, nullOptionVisible); - } - - final boolean paintNullSelection = needNullSelectOption - && currentPage == 0 && !nullFilteredOut; - - if (paintNullSelection) { - target.startTag("so"); - target.addAttribute("caption", ""); - target.addAttribute("key", ""); - target.endTag("so"); - } - - final Iterator<?> i = options.iterator(); - // Paints the available selection options from data source - - while (i.hasNext()) { - - final Object id = i.next(); - - if (!isNullSelectionAllowed() && id != null - && id.equals(getNullSelectionItemId()) && !isSelected(id)) { - continue; - } - - // Gets the option attribute values - final String key = itemIdMapper.key(id); - final String caption = getItemCaption(id); - final Resource icon = getItemIcon(id); - getCaptionChangeListener().addNotifierForItem(id); - - // Paints the option - target.startTag("so"); - if (icon != null) { - target.addAttribute("icon", icon); - } - target.addAttribute("caption", caption); - if (id != null && id.equals(getNullSelectionItemId())) { - target.addAttribute("nullselection", true); - } - target.addAttribute("key", key); - if (isSelected(id) && keyIndex < selectedKeys.length) { - target.addAttribute("selected", true); - selectedKeys[keyIndex++] = key; - } - target.endTag("so"); - } - target.endTag("options"); - - target.addAttribute("totalitems", size() - + (needNullSelectOption ? 1 : 0)); - if (filteredSize > 0 || nullOptionVisible) { - target.addAttribute("totalMatches", filteredSize - + (nullOptionVisible ? 1 : 0)); - } - - // Paint variables - target.addVariable(this, "selected", selectedKeys); - if (isNewItemsAllowed()) { - target.addVariable(this, "newitem", ""); - } - - target.addVariable(this, "filter", filterstring); - target.addVariable(this, "page", currentPage); - - currentPage = -1; // current page is always set by client - - optionRequest = true; - } - - /** - * Returns the filtered options for the current page using a container - * filter. - * - * As a size effect, {@link #filteredSize} is set to the total number of - * items passing the filter. - * - * The current container must be {@link Filterable} and {@link Indexed}, and - * the filtering mode must be suitable for container filtering (tested with - * {@link #canUseContainerFilter()}). - * - * Use {@link #getFilteredOptions()} and - * {@link #sanitetizeList(List, boolean)} if this is not the case. - * - * @param needNullSelectOption - * @return filtered list of options (may be empty) or null if cannot use - * container filters - */ - protected List<?> getOptionsWithFilter(boolean needNullSelectOption) { - Container container = getContainerDataSource(); - - if (pageLength == 0) { - // no paging: return all items - filteredSize = container.size(); - return new ArrayList<Object>(container.getItemIds()); - } - - if (!(container instanceof Filterable) - || !(container instanceof Indexed) - || getItemCaptionMode() != ITEM_CAPTION_MODE_PROPERTY) { - return null; - } - - Filterable filterable = (Filterable) container; - - Filter filter = buildFilter(filterstring, filteringMode); - - // adding and removing filters leads to extraneous item set - // change events from the underlying container, but the ComboBox does - // not process or propagate them based on the flag filteringContainer - if (filter != null) { - filteringContainer = true; - filterable.addContainerFilter(filter); - } - - Indexed indexed = (Indexed) container; - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = indexed.indexOfId(selection); - } - - filteredSize = container.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, filteredSize); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - filteredSize); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - filteredSize, first); - - List<Object> options = new ArrayList<Object>(); - for (int i = first; i <= last && i < filteredSize; ++i) { - options.add(indexed.getIdByIndex(i)); - } - - // to the outside, filtering should not be visible - if (filter != null) { - filterable.removeContainerFilter(filter); - filteringContainer = false; - } - - return options; - } - - /** - * Constructs a filter instance to use when using a Filterable container in - * the <code>ITEM_CAPTION_MODE_PROPERTY</code> mode. - * - * Note that the client side implementation expects the filter string to - * apply to the item caption string it sees, so changing the behavior of - * this method can cause problems. - * - * @param filterString - * @param filteringMode - * @return - */ - protected Filter buildFilter(String filterString, int filteringMode) { - Filter filter = null; - - if (null != filterString && !"".equals(filterString)) { - switch (filteringMode) { - case FILTERINGMODE_OFF: - break; - case FILTERINGMODE_STARTSWITH: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, true); - break; - case FILTERINGMODE_CONTAINS: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, false); - break; - } - } - return filter; - } - - @Override - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - if (!filteringContainer) { - super.containerItemSetChange(event); - } - } - - /** - * Makes correct sublist of given list of options. - * - * If paint is not an option request (affected by page or filter change), - * page will be the one where possible selection exists. - * - * Detects proper first and last item in list to return right page of - * options. Also, if the current page is beyond the end of the list, it will - * be adjusted. - * - * @param options - * @param needNullSelectOption - * flag to indicate if nullselect option needs to be taken into - * consideration - */ - private List<?> sanitetizeList(List<?> options, boolean needNullSelectOption) { - - if (pageLength != 0 && options.size() > pageLength) { - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = options.indexOf(selection); - } - - int size = options.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, size); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - size); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - size, first); - return options.subList(first, last + 1); - } else { - return options; - } - } - - /** - * Returns the index of the first item on the current page. The index is to - * the underlying (possibly filtered) contents. The null item, if any, does - * not have an index but takes up a slot on the first page. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @return first item to show on the UI (index to the filtered list of - * options, not taking the null item into consideration if any) - */ - private int getFirstItemIndexOnCurrentPage(boolean needNullSelectOption, - int size) { - // Not all options are visible, find out which ones are on the - // current "page". - int first = currentPage * pageLength; - if (needNullSelectOption && currentPage > 0) { - first--; - } - return first; - } - - /** - * Returns the index of the last item on the current page. The index is to - * the underlying (possibly filtered) contents. If needNullSelectOption is - * true, the null item takes up the first slot on the first page, - * effectively reducing the first page size by one. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @param first - * index in the filtered view of the first item of the page - * @return index in the filtered view of the last item on the page - */ - private int getLastItemIndexOnCurrentPage(boolean needNullSelectOption, - int size, int first) { - // page length usable for non-null items - int effectivePageLength = pageLength - - (needNullSelectOption && (currentPage == 0) ? 1 : 0); - return Math.min(size - 1, first + effectivePageLength - 1); - } - - /** - * Adjusts the index of the current page if necessary: make sure the current - * page is not after the end of the contents, and optionally go to the page - * containg a specific item. There are no side effects but the adjusted page - * index is returned. - * - * @param page - * page number to use as the starting point - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param indexToEnsureInView - * index of an item that should be included on the page (in the - * data set, not counting the null item if any), -1 for none - * @param size - * number of items after filtering (not including the null item, - * if any) - */ - private int adjustCurrentPage(int page, boolean needNullSelectOption, - int indexToEnsureInView, int size) { - if (indexToEnsureInView != -1) { - int newPage = (indexToEnsureInView + (needNullSelectOption ? 1 : 0)) - / pageLength; - page = newPage; - } - // adjust the current page if beyond the end of the list - if (page * pageLength > size) { - page = (size + (needNullSelectOption ? 1 : 0)) / pageLength; - } - return page; - } - - /** - * Filters the options in memory and returns the full filtered list. - * - * This can be less efficient than using container filters, so use - * {@link #getOptionsWithFilter(boolean)} if possible (filterable container - * and suitable item caption mode etc.). - * - * @return - */ - protected List<?> getFilteredOptions() { - if (null == filterstring || "".equals(filterstring) - || FILTERINGMODE_OFF == filteringMode) { - prevfilterstring = null; - filteredOptions = new LinkedList<Object>(getItemIds()); - return filteredOptions; - } - - if (filterstring.equals(prevfilterstring)) { - return filteredOptions; - } - - Collection<?> items; - if (prevfilterstring != null - && filterstring.startsWith(prevfilterstring)) { - items = filteredOptions; - } else { - items = getItemIds(); - } - prevfilterstring = filterstring; - - filteredOptions = new LinkedList<Object>(); - for (final Iterator<?> it = items.iterator(); it.hasNext();) { - final Object itemId = it.next(); - String caption = getItemCaption(itemId); - if (caption == null || caption.equals("")) { - continue; - } else { - caption = caption.toLowerCase(); - } - switch (filteringMode) { - case FILTERINGMODE_CONTAINS: - if (caption.indexOf(filterstring) > -1) { - filteredOptions.add(itemId); - } - break; - case FILTERINGMODE_STARTSWITH: - default: - if (caption.startsWith(filterstring)) { - filteredOptions.add(itemId); - } - break; - } - } - - return filteredOptions; - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Not calling super.changeVariables due the history of select - // component hierarchy - - // Selection change - if (variables.containsKey("selected")) { - final String[] ka = (String[]) variables.get("selected"); - - if (isMultiSelect()) { - // Multiselect mode - - // TODO Optimize by adding repaintNotNeeded whan applicaple - - // Converts the key-array to id-set - final LinkedList<Object> s = new LinkedList<Object>(); - for (int i = 0; i < ka.length; i++) { - final Object id = itemIdMapper.get(ka[i]); - if (id != null && containsId(id)) { - s.add(id); - } - } - - // Limits the deselection to the set of visible items - // (non-visible items can not be deselected) - final Collection<?> visible = getVisibleItemIds(); - if (visible != null) { - @SuppressWarnings("unchecked") - Set<Object> newsel = (Set<Object>) getValue(); - if (newsel == null) { - newsel = new HashSet<Object>(); - } else { - newsel = new HashSet<Object>(newsel); - } - newsel.removeAll(visible); - newsel.addAll(s); - setValue(newsel, true); - } - } else { - // Single select mode - if (ka.length == 0) { - - // Allows deselection only if the deselected item is visible - final Object current = getValue(); - final Collection<?> visible = getVisibleItemIds(); - if (visible != null && visible.contains(current)) { - setValue(null, true); - } - } else { - final Object id = itemIdMapper.get(ka[0]); - if (id != null && id.equals(getNullSelectionItemId())) { - setValue(null, true); - } else { - setValue(id, true); - } - } - } - } - - String newFilter; - if ((newFilter = (String) variables.get("filter")) != null) { - // this is a filter request - currentPage = ((Integer) variables.get("page")).intValue(); - filterstring = newFilter; - if (filterstring != null) { - filterstring = filterstring.toLowerCase(); - } - requestRepaint(); - } else if (isNewItemsAllowed()) { - // New option entered (and it is allowed) - final String newitem = (String) variables.get("newitem"); - if (newitem != null && newitem.length() > 0) { - getNewItemHandler().addNewItem(newitem); - // rebuild list - filterstring = null; - prevfilterstring = null; - } - } - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - - } - - @Override - @Deprecated - public void requestRepaint() { - markAsDirty(); - } - - @Override - public void setFilteringMode(int filteringMode) { - this.filteringMode = filteringMode; - } - - @Override - public int getFilteringMode() { - return filteringMode; - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * @see com.vaadin.ui.AbstractSelect#setMultiSelect(boolean) - * @throws UnsupportedOperationException - * if trying to activate multiselect mode - */ - @Deprecated - @Override - public void setMultiSelect(boolean multiSelect) { - if (multiSelect) { - throw new UnsupportedOperationException("Multiselect not supported"); - } - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * - * @see com.vaadin.ui.AbstractSelect#isMultiSelect() - */ - @Deprecated - @Override - public boolean isMultiSelect() { - return super.isMultiSelect(); - } - - /** - * Sets whether to scroll the selected item visible (directly open the page - * on which it is) when opening the combo box popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - * - * @param scrollToSelectedItem - * true to find the page with the selected item when opening the - * selection popup - */ - public void setScrollToSelectedItem(boolean scrollToSelectedItem) { - this.scrollToSelectedItem = scrollToSelectedItem; - } - - /** - * Returns true if the select should find the page with the selected item - * when opening the popup (single select combo box only). - * - * @see #setScrollToSelectedItem(boolean) - * - * @return true if the page with the selected item will be shown when - * opening the popup - */ - public boolean isScrollToSelectedItem() { - return scrollToSelectedItem; - } - } diff --git a/server/src/com/vaadin/ui/TabSheet.java b/server/src/com/vaadin/ui/TabSheet.java index 82faedcc41..eb66de519f 100644 --- a/server/src/com/vaadin/ui/TabSheet.java +++ b/server/src/com/vaadin/ui/TabSheet.java @@ -30,15 +30,15 @@ import com.vaadin.event.FieldEvents.BlurNotifier; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.event.FieldEvents.FocusNotifier; +import com.vaadin.server.ErrorMessage; +import com.vaadin.server.KeyMapper; +import com.vaadin.server.LegacyPaint; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants; import com.vaadin.shared.ui.tabsheet.TabsheetConstants; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; import com.vaadin.ui.Component.Focusable; import com.vaadin.ui.themes.Reindeer; import com.vaadin.ui.themes.Runo; @@ -71,7 +71,7 @@ import com.vaadin.ui.themes.Runo; * @since 3.0 */ public class TabSheet extends AbstractComponentContainer implements Focusable, - FocusNotifier, BlurNotifier, Vaadin6Component { + FocusNotifier, BlurNotifier, LegacyComponent { /** * List of component tabs (tab contents). In addition to being on this list, @@ -791,23 +791,42 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, * @param listener * the Listener to be added. */ - public void addListener(SelectedTabChangeListener listener) { + public void addSelectedTabChangeListener(SelectedTabChangeListener listener) { addListener(SelectedTabChangeEvent.class, listener, SELECTED_TAB_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addSelectedTabChangeListener(SelectedTabChangeListener)} + **/ + @Deprecated + public void addListener(SelectedTabChangeListener listener) { + addSelectedTabChangeListener(listener); + } + + /** * Removes a tab selection listener * * @param listener * the Listener to be removed. */ - public void removeListener(SelectedTabChangeListener listener) { + public void removeSelectedTabChangeListener( + SelectedTabChangeListener listener) { removeListener(SelectedTabChangeEvent.class, listener, SELECTED_TAB_CHANGE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeSelectedTabChangeListener(SelectedTabChangeListener)} + **/ + @Deprecated + public void removeListener(SelectedTabChangeListener listener) { + removeSelectedTabChangeListener(listener); + } + + /** * Sends an event that the currently selected tab has changed. */ protected void fireSelectedTabChange() { @@ -1211,26 +1230,60 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, } @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); + } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); } @Override diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 8fc3fc2572..d1bdcdd708 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -52,13 +52,13 @@ import com.vaadin.event.dd.DragSource; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; +import com.vaadin.server.KeyMapper; +import com.vaadin.server.LegacyPaint; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.table.TableConstants; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; /** * <p> @@ -4575,17 +4575,35 @@ public class Table extends AbstractSelect implements Action.Container, } @Override - public void addListener(ItemClickListener listener) { + public void addItemClickListener(ItemClickListener listener) { addListener(TableConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener, ItemClickEvent.ITEM_CLICK_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemClickListener(ItemClickListener)} + **/ + @Deprecated + public void addListener(ItemClickListener listener) { + addItemClickListener(listener); + } + @Override - public void removeListener(ItemClickListener listener) { + public void removeItemClickListener(ItemClickListener listener) { removeListener(TableConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemClickListener(ItemClickListener)} + **/ + @Deprecated + public void removeListener(ItemClickListener listener) { + removeItemClickListener(listener); + } + // Identical to AbstractCompoenentContainer.setEnabled(); @Override @@ -4759,7 +4777,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse( - * com.vaadin.terminal.PaintTarget) + * com.vaadin.server.PaintTarget) */ @Override @@ -4926,24 +4944,42 @@ public class Table extends AbstractSelect implements Action.Container, * @param listener * The handler which should handle the header click events. */ - public void addListener(HeaderClickListener listener) { + public void addHeaderClickListener(HeaderClickListener listener) { addListener(TableConstants.HEADER_CLICK_EVENT_ID, HeaderClickEvent.class, listener, HeaderClickEvent.HEADER_CLICK_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addHeaderClickListener(HeaderClickListener)} + **/ + @Deprecated + public void addListener(HeaderClickListener listener) { + addHeaderClickListener(listener); + } + + /** * Removes a header click listener * * @param listener * The listener to remove. */ - public void removeListener(HeaderClickListener listener) { + public void removeHeaderClickListener(HeaderClickListener listener) { removeListener(TableConstants.HEADER_CLICK_EVENT_ID, HeaderClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeHeaderClickListener(HeaderClickListener)} + **/ + @Deprecated + public void removeListener(HeaderClickListener listener) { + removeHeaderClickListener(listener); + } + + /** * Adds a footer click listener which handles the click events when the user * clicks on a column footer cell in the Table. * <p> @@ -4954,24 +4990,42 @@ public class Table extends AbstractSelect implements Action.Container, * @param listener * The handler which should handle the footer click events. */ - public void addListener(FooterClickListener listener) { + public void addFooterClickListener(FooterClickListener listener) { addListener(TableConstants.FOOTER_CLICK_EVENT_ID, FooterClickEvent.class, listener, FooterClickEvent.FOOTER_CLICK_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addFooterClickListener(FooterClickListener)} + **/ + @Deprecated + public void addListener(FooterClickListener listener) { + addFooterClickListener(listener); + } + + /** * Removes a footer click listener * * @param listener * The listener to remove. */ - public void removeListener(FooterClickListener listener) { + public void removeFooterClickListener(FooterClickListener listener) { removeListener(TableConstants.FOOTER_CLICK_EVENT_ID, FooterClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFooterClickListener(FooterClickListener)} + **/ + @Deprecated + public void removeListener(FooterClickListener listener) { + removeFooterClickListener(listener); + } + + /** * Gets the footer caption beneath the rows * * @param propertyId @@ -5122,24 +5176,42 @@ public class Table extends AbstractSelect implements Action.Container, * @param listener * The listener to attach to the Table */ - public void addListener(ColumnResizeListener listener) { + public void addColumnResizeListener(ColumnResizeListener listener) { addListener(TableConstants.COLUMN_RESIZE_EVENT_ID, ColumnResizeEvent.class, listener, ColumnResizeEvent.COLUMN_RESIZE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addColumnResizeListener(ColumnResizeListener)} + **/ + @Deprecated + public void addListener(ColumnResizeListener listener) { + addColumnResizeListener(listener); + } + + /** * Removes a column resize listener from the Table. * * @param listener * The listener to remove */ - public void removeListener(ColumnResizeListener listener) { + public void removeColumnResizeListener(ColumnResizeListener listener) { removeListener(TableConstants.COLUMN_RESIZE_EVENT_ID, ColumnResizeEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeColumnResizeListener(ColumnResizeListener)} + **/ + @Deprecated + public void removeListener(ColumnResizeListener listener) { + removeColumnResizeListener(listener); + } + + /** * This event is fired when a columns are reordered by the end user user. */ public static class ColumnReorderEvent extends Component.Event { @@ -5188,23 +5260,41 @@ public class Table extends AbstractSelect implements Action.Container, * @param listener * The listener to attach to the Table */ - public void addListener(ColumnReorderListener listener) { + public void addColumnReorderListener(ColumnReorderListener listener) { addListener(TableConstants.COLUMN_REORDER_EVENT_ID, ColumnReorderEvent.class, listener, ColumnReorderEvent.METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addColumnReorderListener(ColumnReorderListener)} + **/ + @Deprecated + public void addListener(ColumnReorderListener listener) { + addColumnReorderListener(listener); + } + + /** * Removes a column reorder listener from the Table. * * @param listener * The listener to remove */ - public void removeListener(ColumnReorderListener listener) { + public void removeColumnReorderListener(ColumnReorderListener listener) { removeListener(TableConstants.COLUMN_REORDER_EVENT_ID, ColumnReorderEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeColumnReorderListener(ColumnReorderListener)} + **/ + @Deprecated + public void removeListener(ColumnReorderListener listener) { + removeColumnReorderListener(listener); + } + + /** * Set the item description generator which generates tooltips for cells and * rows in the Table * diff --git a/server/src/com/vaadin/ui/Tree.java b/server/src/com/vaadin/ui/Tree.java index 2d6673a67d..9cf1aa3511 100644 --- a/server/src/com/vaadin/ui/Tree.java +++ b/server/src/com/vaadin/ui/Tree.java @@ -49,13 +49,13 @@ import com.vaadin.event.dd.TargetDetails; import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion; import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; +import com.vaadin.server.KeyMapper; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.dd.VerticalDropLocation; import com.vaadin.shared.ui.tree.TreeConstants; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; import com.vaadin.tools.ReflectTools; /** @@ -906,22 +906,40 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, * @param listener * the Listener to be added. */ - public void addListener(ExpandListener listener) { + public void addExpandListener(ExpandListener listener) { addListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addExpandListener(ExpandListener)} + **/ + @Deprecated + public void addListener(ExpandListener listener) { + addExpandListener(listener); + } + + /** * Removes the expand listener. * * @param listener * the Listener to be removed. */ - public void removeListener(ExpandListener listener) { + public void removeExpandListener(ExpandListener listener) { removeListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeExpandListener(ExpandListener)} + **/ + @Deprecated + public void removeListener(ExpandListener listener) { + removeExpandListener(listener); + } + + /** * Emits the expand event. * * @param itemId @@ -991,23 +1009,41 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, * @param listener * the Listener to be added. */ - public void addListener(CollapseListener listener) { + public void addCollapseListener(CollapseListener listener) { addListener(CollapseEvent.class, listener, CollapseListener.COLLAPSE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addCollapseListener(CollapseListener)} + **/ + @Deprecated + public void addListener(CollapseListener listener) { + addCollapseListener(listener); + } + + /** * Removes the collapse listener. * * @param listener * the Listener to be removed. */ - public void removeListener(CollapseListener listener) { + public void removeCollapseListener(CollapseListener listener) { removeListener(CollapseEvent.class, listener, CollapseListener.COLLAPSE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeCollapseListener(CollapseListener)} + **/ + @Deprecated + public void removeListener(CollapseListener listener) { + removeCollapseListener(listener); + } + + /** * Emits collapse event. * * @param itemId @@ -1162,18 +1198,36 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, private DropHandler dropHandler; @Override - public void addListener(ItemClickListener listener) { + public void addItemClickListener(ItemClickListener listener) { addListener(TreeConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener, ItemClickEvent.ITEM_CLICK_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addItemClickListener(ItemClickListener)} + **/ + @Deprecated + public void addListener(ItemClickListener listener) { + addItemClickListener(listener); + } + @Override - public void removeListener(ItemClickListener listener) { + public void removeItemClickListener(ItemClickListener listener) { removeListener(TreeConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeItemClickListener(ItemClickListener)} + **/ + @Deprecated + public void removeListener(ItemClickListener listener) { + removeItemClickListener(listener); + } + + /** * Sets the {@link ItemStyleGenerator} to be used with this tree. * * @param itemStyleGenerator @@ -1449,7 +1503,7 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, * * @see * com.vaadin.event.dd.acceptCriteria.AcceptCriterion#paintResponse( - * com.vaadin.terminal.PaintTarget) + * com.vaadin.server.PaintTarget) */ @Override public void paintResponse(PaintTarget target) throws PaintException { diff --git a/server/src/com/vaadin/ui/TreeTable.java b/server/src/com/vaadin/ui/TreeTable.java index 05757a6d09..ef5850a8af 100644 --- a/server/src/com/vaadin/ui/TreeTable.java +++ b/server/src/com/vaadin/ui/TreeTable.java @@ -32,10 +32,10 @@ import com.vaadin.data.Container.ItemSetChangeEvent; import com.vaadin.data.util.ContainerHierarchicalWrapper; import com.vaadin.data.util.HierarchicalContainer; import com.vaadin.data.util.HierarchicalContainerOrderedWrapper; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; import com.vaadin.shared.ui.treetable.TreeTableConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; import com.vaadin.ui.Tree.CollapseEvent; import com.vaadin.ui.Tree.CollapseListener; import com.vaadin.ui.Tree.ExpandEvent; @@ -752,22 +752,40 @@ public class TreeTable extends Table implements Hierarchical { * @param listener * the Listener to be added. */ - public void addListener(ExpandListener listener) { + public void addExpandListener(ExpandListener listener) { addListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addExpandListener(ExpandListener)} + **/ + @Deprecated + public void addListener(ExpandListener listener) { + addExpandListener(listener); + } + + /** * Removes an expand listener. * * @param listener * the Listener to be removed. */ - public void removeListener(ExpandListener listener) { + public void removeExpandListener(ExpandListener listener) { removeListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeExpandListener(ExpandListener)} + **/ + @Deprecated + public void removeListener(ExpandListener listener) { + removeExpandListener(listener); + } + + /** * Emits an expand event. * * @param itemId @@ -783,23 +801,41 @@ public class TreeTable extends Table implements Hierarchical { * @param listener * the Listener to be added. */ - public void addListener(CollapseListener listener) { + public void addCollapseListener(CollapseListener listener) { addListener(CollapseEvent.class, listener, CollapseListener.COLLAPSE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addCollapseListener(CollapseListener)} + **/ + @Deprecated + public void addListener(CollapseListener listener) { + addCollapseListener(listener); + } + + /** * Removes a collapse listener. * * @param listener * the Listener to be removed. */ - public void removeListener(CollapseListener listener) { + public void removeCollapseListener(CollapseListener listener) { removeListener(CollapseEvent.class, listener, CollapseListener.COLLAPSE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeCollapseListener(CollapseListener)} + **/ + @Deprecated + public void removeListener(CollapseListener listener) { + removeCollapseListener(listener); + } + + /** * Emits a collapse event. * * @param itemId diff --git a/server/src/com/vaadin/ui/TwinColSelect.java b/server/src/com/vaadin/ui/TwinColSelect.java index 891e695a5f..76f1e1e8c7 100644 --- a/server/src/com/vaadin/ui/TwinColSelect.java +++ b/server/src/com/vaadin/ui/TwinColSelect.java @@ -19,9 +19,9 @@ package com.vaadin.ui; import java.util.Collection; import com.vaadin.data.Container; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.twincolselect.TwinColSelectConstants; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; /** * Multiselect component with two lists: left side for available items and right diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 17a028bcdf..a59b96d27a 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -34,22 +34,22 @@ import com.vaadin.event.Action.Handler; import com.vaadin.event.ActionManager; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.server.AbstractApplicationServlet; +import com.vaadin.server.Page; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.Resource; +import com.vaadin.server.LegacyComponent; +import com.vaadin.server.WrappedRequest; +import com.vaadin.server.Page.BrowserWindowResizeEvent; +import com.vaadin.server.Page.BrowserWindowResizeListener; +import com.vaadin.server.WrappedRequest.BrowserDetails; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIServerRpc; import com.vaadin.shared.ui.ui.UIState; -import com.vaadin.terminal.Page; -import com.vaadin.terminal.Page.BrowserWindowResizeEvent; -import com.vaadin.terminal.Page.BrowserWindowResizeListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedRequest.BrowserDetails; -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; import com.vaadin.tools.ReflectTools; /** @@ -90,7 +90,7 @@ import com.vaadin.tools.ReflectTools; * @since 7.0 */ public abstract class UI extends AbstractComponentContainer implements - Action.Container, Action.Notifier, Vaadin6Component { + Action.Container, Action.Notifier, LegacyComponent { /** * Helper class to emulate the main window from Vaadin 6 using UIs. This @@ -1094,45 +1094,39 @@ public abstract class UI extends AbstractComponentContainer implements * @param listener * The listener to add */ - public void addListener(ClickListener listener) { + public void addClickListener(ClickListener listener) { addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener, ClickListener.clickMethod); } /** + * @deprecated Since 7.0, replaced by + * {@link #addClickListener(ClickListener)} + **/ + @Deprecated + public void addListener(ClickListener listener) { + addClickListener(listener); + } + + /** * Remove a click listener from the UI. The listener should earlier have * been added using {@link #addListener(ClickListener)}. * * @param listener * The listener to remove */ - public void removeListener(ClickListener listener) { + public void removeClickListener(ClickListener listener) { removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener); } /** - * Adds a close listener to the UI. The listener is called when the UI is - * removed from the application. - * - * @param listener - * The listener to add. - */ - public void addListener(CloseListener listener) { - addListener(CloseEvent.CLOSE_EVENT_IDENTIFIER, CloseEvent.class, - listener, CloseListener.closeMethod); - } - - /** - * Removes a close listener from the UI if it has previously been added with - * {@link #addListener(ClickListener)}. Otherwise, has no effect. - * - * @param listener - * The listener to remove. - */ - public void removeListener(CloseListener listener) { - removeListener(CloseEvent.CLOSE_EVENT_IDENTIFIER, CloseEvent.class, - listener); + * @deprecated Since 7.0, replaced by + * {@link #removeClickListener(ClickListener)} + **/ + @Deprecated + public void removeListener(ClickListener listener) { + removeClickListener(listener); } @Override diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java index 619db07eea..2323b22e17 100644 --- a/server/src/com/vaadin/ui/Upload.java +++ b/server/src/com/vaadin/ui/Upload.java @@ -24,12 +24,12 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.StreamVariable.StreamingProgressEvent; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.server.NoInputStreamException; -import com.vaadin.terminal.gwt.server.NoOutputStreamException; +import com.vaadin.server.NoInputStreamException; +import com.vaadin.server.NoOutputStreamException; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; +import com.vaadin.server.StreamVariable.StreamingProgressEvent; /** * Component for uploading files from client to server. @@ -71,7 +71,7 @@ import com.vaadin.terminal.gwt.server.NoOutputStreamException; */ @SuppressWarnings("serial") public class Upload extends AbstractComponent implements Component.Focusable, - Vaadin6Component { + LegacyComponent { /** * Should the field be focused on next repaint? @@ -570,87 +570,159 @@ public class Upload extends AbstractComponent implements Component.Focusable, * @param listener * the Listener to be added. */ - public void addListener(StartedListener listener) { + public void addStartedListener(StartedListener listener) { addListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addStartedListener(StartedListener)} + **/ + @Deprecated + public void addListener(StartedListener listener) { + addStartedListener(listener); + } + + /** * Removes the upload started event listener. * * @param listener * the Listener to be removed. */ - public void removeListener(StartedListener listener) { + public void removeStartedListener(StartedListener listener) { removeListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeStartedListener(StartedListener)} + **/ + @Deprecated + public void removeListener(StartedListener listener) { + removeStartedListener(listener); + } + + /** * Adds the upload received event listener. * * @param listener * the Listener to be added. */ - public void addListener(FinishedListener listener) { + public void addFinishedListener(FinishedListener listener) { addListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addFinishedListener(FinishedListener)} + **/ + @Deprecated + public void addListener(FinishedListener listener) { + addFinishedListener(listener); + } + + /** * Removes the upload received event listener. * * @param listener * the Listener to be removed. */ - public void removeListener(FinishedListener listener) { + public void removeFinishedListener(FinishedListener listener) { removeListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFinishedListener(FinishedListener)} + **/ + @Deprecated + public void removeListener(FinishedListener listener) { + removeFinishedListener(listener); + } + + /** * Adds the upload interrupted event listener. * * @param listener * the Listener to be added. */ - public void addListener(FailedListener listener) { + public void addFailedListener(FailedListener listener) { addListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addFailedListener(FailedListener)} + **/ + @Deprecated + public void addListener(FailedListener listener) { + addFailedListener(listener); + } + + /** * Removes the upload interrupted event listener. * * @param listener * the Listener to be removed. */ - public void removeListener(FailedListener listener) { + public void removeFailedListener(FailedListener listener) { removeListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFailedListener(FailedListener)} + **/ + @Deprecated + public void removeListener(FailedListener listener) { + removeFailedListener(listener); + } + + /** * Adds the upload success event listener. * * @param listener * the Listener to be added. */ - public void addListener(SucceededListener listener) { + public void addSucceededListener(SucceededListener listener) { addListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addSucceededListener(SucceededListener)} + **/ + @Deprecated + public void addListener(SucceededListener listener) { + addSucceededListener(listener); + } + + /** * Removes the upload success event listener. * * @param listener * the Listener to be removed. */ - public void removeListener(SucceededListener listener) { + public void removeSucceededListener(SucceededListener listener) { removeListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeSucceededListener(SucceededListener)} + **/ + @Deprecated + public void removeListener(SucceededListener listener) { + removeSucceededListener(listener); + } + + /** * Adds the upload success event listener. * * @param listener * the Listener to be added. */ - public void addListener(ProgressListener listener) { + public void addProgressListener(ProgressListener listener) { if (progressListeners == null) { progressListeners = new LinkedHashSet<ProgressListener>(); } @@ -658,18 +730,36 @@ public class Upload extends AbstractComponent implements Component.Focusable, } /** + * @deprecated Since 7.0, replaced by + * {@link #addProgressListener(ProgressListener)} + **/ + @Deprecated + public void addListener(ProgressListener listener) { + addProgressListener(listener); + } + + /** * Removes the upload success event listener. * * @param listener * the Listener to be removed. */ - public void removeListener(ProgressListener listener) { + public void removeProgressListener(ProgressListener listener) { if (progressListeners != null) { progressListeners.remove(listener); } } /** + * @deprecated Since 7.0, replaced by + * {@link #removeProgressListener(ProgressListener)} + **/ + @Deprecated + public void removeListener(ProgressListener listener) { + removeProgressListener(listener); + } + + /** * Emit upload received event. * * @param filename @@ -936,11 +1026,11 @@ public class Upload extends AbstractComponent implements Component.Focusable, * Handle to terminal via Upload monitors and controls the upload during it * is being streamed. */ - private com.vaadin.terminal.StreamVariable streamVariable; + private com.vaadin.server.StreamVariable streamVariable; - protected com.vaadin.terminal.StreamVariable getStreamVariable() { + protected com.vaadin.server.StreamVariable getStreamVariable() { if (streamVariable == null) { - streamVariable = new com.vaadin.terminal.StreamVariable() { + streamVariable = new com.vaadin.server.StreamVariable() { private StreamingStartEvent lastStartedEvent; @Override diff --git a/server/src/com/vaadin/ui/Video.java b/server/src/com/vaadin/ui/Video.java index b54d404da6..2d83538d57 100644 --- a/server/src/com/vaadin/ui/Video.java +++ b/server/src/com/vaadin/ui/Video.java @@ -16,9 +16,9 @@ package com.vaadin.ui; +import com.vaadin.server.Resource; +import com.vaadin.shared.ui.video.VideoConstants; import com.vaadin.shared.ui.video.VideoState; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.server.ResourceReference; /** * The Video component translates into an HTML5 <video> element and as @@ -79,14 +79,14 @@ public class Video extends AbstractMedia { * @param poster */ public void setPoster(Resource poster) { - getState().setPoster(ResourceReference.create(poster)); + setResource(VideoConstants.POSTER_RESOURCE, poster); } /** * @return The poster image. */ public Resource getPoster() { - return ResourceReference.getResource(getState().getPoster()); + return getResource(VideoConstants.POSTER_RESOURCE); } } diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java index 6102350566..aaf0fbc492 100644 --- a/server/src/com/vaadin/ui/Window.java +++ b/server/src/com/vaadin/ui/Window.java @@ -31,12 +31,12 @@ import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.event.ShortcutAction.ModifierKey; import com.vaadin.event.ShortcutListener; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; +import com.vaadin.server.LegacyComponent; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.window.WindowServerRpc; import com.vaadin.shared.ui.window.WindowState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; /** * A component that represents a floating popup window that can be added to a @@ -65,7 +65,7 @@ import com.vaadin.terminal.Vaadin6Component; */ @SuppressWarnings("serial") public class Window extends Panel implements FocusNotifier, BlurNotifier, - Vaadin6Component { + LegacyComponent { private WindowServerRpc rpc = new WindowServerRpc() { @@ -127,7 +127,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, /* * (non-Javadoc) * - * @see com.vaadin.ui.Panel#paintContent(com.vaadin.terminal.PaintTarget) + * @see com.vaadin.ui.Panel#paintContent(com.vaadin.server.PaintTarget) */ @Override @@ -362,11 +362,20 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * @param listener * the CloseListener to add. */ - public void addListener(CloseListener listener) { + public void addCloseListener(CloseListener listener) { addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addCloseListener(CloseListener)} + **/ + @Deprecated + public void addListener(CloseListener listener) { + addCloseListener(listener); + } + + /** * Removes the CloseListener from the window. * * <p> @@ -376,10 +385,19 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * @param listener * the CloseListener to remove. */ - public void removeListener(CloseListener listener) { + public void removeCloseListener(CloseListener listener) { removeListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); } + /** + * @deprecated Since 7.0, replaced by + * {@link #removeCloseListener(CloseListener)} + **/ + @Deprecated + public void removeListener(CloseListener listener) { + removeCloseListener(listener); + } + protected void fireClose() { fireEvent(new Window.CloseEvent(this)); } @@ -438,20 +456,38 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * * @param listener */ - public void addListener(ResizeListener listener) { + public void addResizeListener(ResizeListener listener) { addListener(ResizeEvent.class, listener, WINDOW_RESIZE_METHOD); } /** + * @deprecated Since 7.0, replaced by + * {@link #addResizeListener(ResizeListener)} + **/ + @Deprecated + public void addListener(ResizeListener listener) { + addResizeListener(listener); + } + + /** * Remove a resize listener. * * @param listener */ - public void removeListener(ResizeListener listener) { + public void removeResizeListener(ResizeListener listener) { removeListener(ResizeEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeResizeListener(ResizeListener)} + **/ + @Deprecated + public void removeListener(ResizeListener listener) { + removeResizeListener(listener); + } + + /** * Fire the resize event. */ protected void fireResize() { @@ -748,17 +784,35 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, */ @Override - public void addListener(FocusListener listener) { + public void addFocusListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + /** + * @deprecated Since 7.0, replaced by + * {@link #addFocusListener(FocusListener)} + **/ + @Deprecated + public void addListener(FocusListener listener) { + addFocusListener(listener); + } + @Override - public void removeListener(FocusListener listener) { + public void removeFocusListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeFocusListener(FocusListener)} + **/ + @Deprecated + public void removeListener(FocusListener listener) { + removeFocusListener(listener); + } + + /** * Note, that focus/blur listeners in Window class are only supported by sub * windows. Also note that Window is not considered focused if its contained * component currently has focus. @@ -767,17 +821,34 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, */ @Override - public void addListener(BlurListener listener) { + public void addBlurListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + /** + * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} + **/ + @Deprecated + public void addListener(BlurListener listener) { + addBlurListener(listener); + } + @Override - public void removeListener(BlurListener listener) { + public void removeBlurListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } /** + * @deprecated Since 7.0, replaced by + * {@link #removeBlurListener(BlurListener)} + **/ + @Deprecated + public void removeListener(BlurListener listener) { + removeBlurListener(listener); + } + + /** * {@inheritDoc} * * If the window is a sub-window focusing will cause the sub-window to be diff --git a/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java new file mode 100644 index 0000000000..3c74a45bd7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java @@ -0,0 +1,81 @@ +package com.vaadin.data.util; + +import com.vaadin.data.util.AbstractBeanContainer; +import com.vaadin.data.util.BeanContainer; +import com.vaadin.data.util.BeanItemContainer; + +/** + * Automated test for {@link AbstractBeanContainer}. + * + * Only a limited subset of the functionality is tested here, the rest in tests + * of subclasses including {@link BeanItemContainer} and {@link BeanContainer}. + */ +public abstract class AbstractBeanContainerTest extends + AbstractInMemoryContainerTest { + + public static class Person { + private String name; + + public Person(String name) { + setName(name); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public static class ClassName { + // field names match constants in parent test class + private String fullyQualifiedName; + private String simpleName; + private String reverseFullyQualifiedName; + private Integer idNumber; + + public ClassName(String fullyQualifiedName, Integer idNumber) { + this.fullyQualifiedName = fullyQualifiedName; + simpleName = AbstractContainerTest + .getSimpleName(fullyQualifiedName); + reverseFullyQualifiedName = reverse(fullyQualifiedName); + this.idNumber = idNumber; + } + + public String getFullyQualifiedName() { + return fullyQualifiedName; + } + + public void setFullyQualifiedName(String fullyQualifiedName) { + this.fullyQualifiedName = fullyQualifiedName; + } + + public String getSimpleName() { + return simpleName; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } + + public String getReverseFullyQualifiedName() { + return reverseFullyQualifiedName; + } + + public void setReverseFullyQualifiedName( + String reverseFullyQualifiedName) { + this.reverseFullyQualifiedName = reverseFullyQualifiedName; + } + + public Integer getIdNumber() { + return idNumber; + } + + public void setIdNumber(Integer idNumber) { + this.idNumber = idNumber; + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java new file mode 100644 index 0000000000..b0151a6690 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java @@ -0,0 +1,649 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Filterable; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.SimpleStringFilter; + +public abstract class AbstractContainerTest extends TestCase { + + /** + * Helper class for testing e.g. listeners expecting events to be fired. + */ + protected abstract static class AbstractEventCounter { + private int eventCount = 0; + private int lastAssertedEventCount = 0; + + /** + * Increment the event count. To be called by subclasses e.g. from a + * listener method. + */ + protected void increment() { + ++eventCount; + } + + /** + * Check that no one event has occurred since the previous assert call. + */ + public void assertNone() { + Assert.assertEquals(lastAssertedEventCount, eventCount); + } + + /** + * Check that exactly one event has occurred since the previous assert + * call. + */ + public void assertOnce() { + Assert.assertEquals(++lastAssertedEventCount, eventCount); + } + + /** + * Reset the counter and the expected count. + */ + public void reset() { + eventCount = 0; + lastAssertedEventCount = 0; + } + } + + /** + * Test class for counting item set change events and verifying they have + * been received. + */ + protected static class ItemSetChangeCounter extends AbstractEventCounter + implements ItemSetChangeListener { + + @Override + public void containerItemSetChange(ItemSetChangeEvent event) { + increment(); + } + + } + + // #6043: for items that have been filtered out, Container interface does + // not specify what to return from getItem() and getContainerProperty(), so + // need checkGetItemNull parameter for the test to be usable for most + // current containers + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize) { + Container.Indexed indexed = null; + if (container instanceof Container.Indexed) { + indexed = (Container.Indexed) container; + } + + List<Object> itemIdList = new ArrayList<Object>(container.getItemIds()); + + // size() + assertEquals(expectedSize, container.size()); + assertEquals(expectedSize, itemIdList.size()); + + // first item, last item + Object first = itemIdList.get(0); + Object last = itemIdList.get(itemIdList.size() - 1); + + assertEquals(expectedFirstItemId, first); + assertEquals(expectedLastItemId, last); + + // containsId + assertFalse(container.containsId(itemIdNotInSet)); + assertTrue(container.containsId(itemIdInSet)); + + // getItem + if (checkGetItemNull) { + assertNull(container.getItem(itemIdNotInSet)); + } + assertNotNull(container.getItem(itemIdInSet)); + + // getContainerProperty + for (Object propId : container.getContainerPropertyIds()) { + if (checkGetItemNull) { + assertNull(container.getContainerProperty(itemIdNotInSet, + propId)); + } + assertNotNull(container.getContainerProperty(itemIdInSet, propId)); + } + + if (indexed != null) { + // firstItemId + assertEquals(first, indexed.firstItemId()); + + // lastItemId + assertEquals(last, indexed.lastItemId()); + + // nextItemId + assertEquals(itemIdList.get(1), indexed.nextItemId(first)); + + // prevItemId + assertEquals(itemIdList.get(itemIdList.size() - 2), + indexed.prevItemId(last)); + + // isFirstId + assertTrue(indexed.isFirstId(first)); + assertFalse(indexed.isFirstId(last)); + + // isLastId + assertTrue(indexed.isLastId(last)); + assertFalse(indexed.isLastId(first)); + + // indexOfId + assertEquals(0, indexed.indexOfId(first)); + assertEquals(expectedSize - 1, indexed.indexOfId(last)); + + // getIdByIndex + assertEquals(indexed.getIdByIndex(0), first); + assertEquals(indexed.getIdByIndex(expectedSize - 1), last); + + } + + } + + protected static final Object FULLY_QUALIFIED_NAME = "fullyQualifiedName"; + protected static final Object SIMPLE_NAME = "simpleName"; + protected static final Object REVERSE_FULLY_QUALIFIED_NAME = "reverseFullyQualifiedName"; + protected static final Object ID_NUMBER = "idNumber"; + + protected void testBasicContainerOperations(Container container) { + initializeContainer(container); + + // Basic container + validateContainer(container, sampleData[0], + sampleData[sampleData.length - 1], sampleData[10], "abc", true, + sampleData.length); + } + + protected void testContainerOrdered(Container.Ordered container) { + Object id = container.addItem(); + assertNotNull(id); + Item item = container.getItem(id); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + Object newFirstId = container.addItemAfter(null); + assertNotNull(newFirstId); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(Object) + Object newSecondItemId = container.addItemAfter(newFirstId); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(newSecondItemId); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(Object,Object) + Object fifthId = new Object(); + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + protected void testContainerIndexed(Container.Indexed container, + Object itemId, int itemPosition, boolean testAddEmptyItemAt, + Object newItemId, boolean testAddItemAtWithId) { + initializeContainer(container); + + // indexOfId + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + + // getIdByIndex + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + + // addItemAt + if (testAddEmptyItemAt) { + Object addedId = container.addItemAt(itemPosition); + Assert.assertEquals(itemPosition, container.indexOfId(addedId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(addedId, container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + + Object newFirstId = container.addItemAt(0); + Assert.assertEquals(0, container.indexOfId(newFirstId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newFirstId, container.firstItemId()); + Assert.assertEquals(newFirstId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Object newLastId = container.addItemAt(container.size()); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newLastId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newLastId, container.lastItemId()); + Assert.assertEquals(newLastId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Assert.assertTrue(container.removeItem(addedId)); + Assert.assertTrue(container.removeItem(newFirstId)); + Assert.assertTrue(container.removeItem(newLastId)); + + Assert.assertFalse( + "Removing non-existing item should indicate failure", + container.removeItem(addedId)); + } + + // addItemAt + if (testAddItemAtWithId) { + container.addItemAt(itemPosition, newItemId); + Assert.assertEquals(itemPosition, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(0, newItemId); + Assert.assertEquals(0, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.firstItemId()); + Assert.assertEquals(newItemId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(container.size(), newItemId); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.lastItemId()); + Assert.assertEquals(newItemId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + } + } + + protected void testContainerFiltering(Container.Filterable container) { + initializeContainer(container); + + // Filter by "contains ab" + container.addContainerFilter(new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false)); + + validateContainer(container, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TabSheet", "com.vaadin.client.Focusable", + "com.vaadin.data.Buffered", isFilteredOutItemNull(), 20); + + // Filter by "contains da" (reversed as ad here) + container.removeAllContainerFilters(); + container.addContainerFilter(new SimpleStringFilter( + REVERSE_FULLY_QUALIFIED_NAME, "ad", false, false)); + + validateContainer(container, "com.vaadin.data.Buffered", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.client.ui.VUriFragmentUtility", + isFilteredOutItemNull(), 37); + } + + /** + * Override in subclasses to return false if the container getItem() method + * returns a non-null value for an item that has been filtered out. + * + * @return + */ + protected boolean isFilteredOutItemNull() { + return true; + } + + protected void testContainerSortingAndFiltering(Container.Sortable sortable) { + Filterable filterable = (Filterable) sortable; + + initializeContainer(sortable); + + // Filter by "contains ab" + filterable.addContainerFilter(new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false)); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(sortable, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.data.util.BeanItem", isFilteredOutItemNull(), 20); + } + + protected void testContainerSorting(Container.Filterable container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds().contains( + REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.Application", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + sampleData.length); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.ui.BaseFieldFactory", "blah", true, + sampleData.length); + + } + + protected void initializeContainer(Container container) { + Assert.assertTrue(container.removeAllItems()); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + Item item = container.addItem(id); + + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i); + } + } + + protected static String getSimpleName(String name) { + if (name.contains(".")) { + return name.substring(name.lastIndexOf('.') + 1); + } else { + return name; + } + } + + protected static String reverse(String string) { + return new StringBuilder(string).reverse().toString(); + } + + protected final String[] sampleData = { + "com.vaadin.annotations.AutoGenerated", "com.vaadin.Application", + "com.vaadin.data.Buffered", "com.vaadin.data.BufferedValidatable", + "com.vaadin.data.Container", "com.vaadin.data.Item", + "com.vaadin.data.Property", "com.vaadin.data.util.BeanItem", + "com.vaadin.data.util.BeanItemContainer", + "com.vaadin.data.util.ContainerHierarchicalWrapper", + "com.vaadin.data.util.ContainerOrderedWrapper", + "com.vaadin.data.util.DefaultItemSorter", + "com.vaadin.data.util.FilesystemContainer", + "com.vaadin.data.util.Filter", + "com.vaadin.data.util.HierarchicalContainer", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.data.util.ItemSorter", + "com.vaadin.data.util.MethodProperty", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.data.util.PropertyFormatter", + "com.vaadin.data.util.PropertysetItem", + "com.vaadin.data.util.QueryContainer", + "com.vaadin.data.util.TextFileProperty", + "com.vaadin.data.Validatable", + "com.vaadin.data.validator.AbstractStringValidator", + "com.vaadin.data.validator.AbstractValidator", + "com.vaadin.data.validator.CompositeValidator", + "com.vaadin.data.validator.DoubleValidator", + "com.vaadin.data.validator.EmailValidator", + "com.vaadin.data.validator.IntegerValidator", + "com.vaadin.data.validator.NullValidator", + "com.vaadin.data.validator.RegexpValidator", + "com.vaadin.data.validator.StringLengthValidator", + "com.vaadin.data.Validator", "com.vaadin.event.Action", + "com.vaadin.event.ComponentEventListener", + "com.vaadin.event.EventRouter", "com.vaadin.event.FieldEvents", + "com.vaadin.event.ItemClickEvent", "com.vaadin.event.LayoutEvents", + "com.vaadin.event.ListenerMethod", + "com.vaadin.event.MethodEventSource", + "com.vaadin.event.MouseEvents", "com.vaadin.event.ShortcutAction", + "com.vaadin.launcher.DemoLauncher", + "com.vaadin.launcher.DevelopmentServerLauncher", + "com.vaadin.launcher.util.BrowserLauncher", + "com.vaadin.service.ApplicationContext", + "com.vaadin.service.FileTypeResolver", + "com.vaadin.server.ApplicationResource", + "com.vaadin.server.ClassResource", + "com.vaadin.server.CompositeErrorMessage", + "com.vaadin.server.DownloadStream", + "com.vaadin.server.ErrorMessage", + "com.vaadin.server.ExternalResource", + "com.vaadin.server.FileResource", + "com.vaadin.client.ApplicationConfiguration", + "com.vaadin.client.ApplicationConnection", + "com.vaadin.client.BrowserInfo", + "com.vaadin.client.ClientExceptionHandler", + "com.vaadin.client.ComponentDetail", + "com.vaadin.client.ComponentDetailMap", + "com.vaadin.client.ComponentLocator", "com.vaadin.client.Console", + "com.vaadin.client.Container", + "com.vaadin.client.ContainerResizedListener", + "com.vaadin.client.CSSRule", "com.vaadin.client.DateTimeService", + "com.vaadin.client.DefaultWidgetSet", + "com.vaadin.client.Focusable", + "com.vaadin.client.HistoryImplIEVaadin", + "com.vaadin.client.LocaleNotLoadedException", + "com.vaadin.client.LocaleService", + "com.vaadin.client.MouseEventDetails", + "com.vaadin.client.NullConsole", "com.vaadin.client.Paintable", + "com.vaadin.client.RenderInformation", + "com.vaadin.client.RenderSpace", + "com.vaadin.client.StyleConstants", + "com.vaadin.client.TooltipInfo", "com.vaadin.client.ui.Action", + "com.vaadin.client.ui.ActionOwner", + "com.vaadin.client.ui.AlignmentInfo", + "com.vaadin.client.ui.CalendarEntry", + "com.vaadin.client.ui.ClickEventHandler", + "com.vaadin.client.ui.Field", "com.vaadin.client.ui.Icon", + "com.vaadin.client.ui.layout.CellBasedLayout", + "com.vaadin.client.ui.layout.ChildComponentContainer", + "com.vaadin.client.ui.layout.Margins", + "com.vaadin.client.ui.LayoutClickEventHandler", + "com.vaadin.client.ui.MenuBar", "com.vaadin.client.ui.MenuItem", + "com.vaadin.client.ui.richtextarea.VRichTextArea", + "com.vaadin.client.ui.richtextarea.VRichTextToolbar", + "com.vaadin.client.ui.ShortcutActionHandler", + "com.vaadin.client.ui.SubPartAware", "com.vaadin.client.ui.Table", + "com.vaadin.client.ui.TreeAction", + "com.vaadin.client.ui.TreeImages", + "com.vaadin.client.ui.VAbsoluteLayout", + "com.vaadin.client.ui.VAccordion", "com.vaadin.client.ui.VButton", + "com.vaadin.client.ui.VCalendarPanel", + "com.vaadin.client.ui.VCheckBox", + "com.vaadin.client.ui.VContextMenu", + "com.vaadin.client.ui.VCssLayout", + "com.vaadin.client.ui.VCustomComponent", + "com.vaadin.client.ui.VCustomLayout", + "com.vaadin.client.ui.VDateField", + "com.vaadin.client.ui.VDateFieldCalendar", + "com.vaadin.client.ui.VEmbedded", + "com.vaadin.client.ui.VFilterSelect", "com.vaadin.client.ui.VForm", + "com.vaadin.client.ui.VFormLayout", + "com.vaadin.client.ui.VGridLayout", + "com.vaadin.client.ui.VHorizontalLayout", + "com.vaadin.client.ui.VLabel", "com.vaadin.client.ui.VLink", + "com.vaadin.client.ui.VListSelect", + "com.vaadin.client.ui.VMarginInfo", + "com.vaadin.client.ui.VMenuBar", + "com.vaadin.client.ui.VNativeButton", + "com.vaadin.client.ui.VNativeSelect", + "com.vaadin.client.ui.VNotification", + "com.vaadin.client.ui.VOptionGroup", + "com.vaadin.client.ui.VOptionGroupBase", + "com.vaadin.client.ui.VOrderedLayout", + "com.vaadin.client.ui.VOverlay", "com.vaadin.client.ui.VPanel", + "com.vaadin.client.ui.VPasswordField", + "com.vaadin.client.ui.VPopupCalendar", + "com.vaadin.client.ui.VPopupView", + "com.vaadin.client.ui.VProgressIndicator", + "com.vaadin.client.ui.VScrollTable", + "com.vaadin.client.ui.VSlider", "com.vaadin.client.ui.VSplitPanel", + "com.vaadin.client.ui.VSplitPanelHorizontal", + "com.vaadin.client.ui.VSplitPanelVertical", + "com.vaadin.client.ui.VTablePaging", + "com.vaadin.client.ui.VTabsheet", + "com.vaadin.client.ui.VTabsheetBase", + "com.vaadin.client.ui.VTabsheetPanel", + "com.vaadin.client.ui.VTextArea", + "com.vaadin.client.ui.VTextField", + "com.vaadin.client.ui.VTextualDate", "com.vaadin.client.ui.VTime", + "com.vaadin.client.ui.VTree", + "com.vaadin.client.ui.VTwinColSelect", + "com.vaadin.client.ui.VUnknownComponent", + "com.vaadin.client.ui.VUpload", + "com.vaadin.client.ui.VUriFragmentUtility", + "com.vaadin.client.ui.VVerticalLayout", + "com.vaadin.client.ui.VView", "com.vaadin.client.ui.VWindow", + "com.vaadin.client.UIDL", "com.vaadin.client.Util", + "com.vaadin.client.ValueMap", "com.vaadin.client.VCaption", + "com.vaadin.client.VCaptionWrapper", + "com.vaadin.client.VDebugConsole", + "com.vaadin.client.VErrorMessage", "com.vaadin.client.VTooltip", + "com.vaadin.client.VUIDLBrowser", "com.vaadin.client.WidgetMap", + "com.vaadin.client.WidgetSet", + "com.vaadin.server.AbstractApplicationPortlet", + "com.vaadin.server.AbstractApplicationServlet", + "com.vaadin.server.AbstractCommunicationManager", + "com.vaadin.server.AbstractWebApplicationContext", + "com.vaadin.server.ApplicationPortlet", + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.server.ApplicationRunnerServlet", + "com.vaadin.server.ApplicationServlet", + "com.vaadin.server.ChangeVariablesErrorEvent", + "com.vaadin.server.CommunicationManager", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.server.Constants", + "com.vaadin.server.GAEApplicationServlet", + "com.vaadin.server.HttpServletRequestListener", + "com.vaadin.server.HttpUploadStream", + "com.vaadin.server.JsonPaintTarget", + "com.vaadin.server.PortletApplicationContext", + "com.vaadin.server.PortletApplicationContext2", + "com.vaadin.server.PortletCommunicationManager", + "com.vaadin.server.PortletRequestListener", + "com.vaadin.server.RestrictedRenderResponse", + "com.vaadin.server.SessionExpiredException", + "com.vaadin.server.SystemMessageException", + "com.vaadin.server.WebApplicationContext", + "com.vaadin.server.WebBrowser", + "com.vaadin.server.widgetsetutils.ClassPathExplorer", + "com.vaadin.server.widgetsetutils.WidgetMapGenerator", + "com.vaadin.server.widgetsetutils.WidgetSetBuilder", + "com.vaadin.server.KeyMapper", "com.vaadin.server.Paintable", + "com.vaadin.server.PaintException", + "com.vaadin.server.PaintTarget", + "com.vaadin.server.ParameterHandler", "com.vaadin.server.Resource", + "com.vaadin.server.Scrollable", "com.vaadin.server.Sizeable", + "com.vaadin.server.StreamResource", + "com.vaadin.server.SystemError", "com.vaadin.server.Terminal", + "com.vaadin.server.ThemeResource", + "com.vaadin.server.UploadStream", "com.vaadin.server.URIHandler", + "com.vaadin.server.UserError", "com.vaadin.server.VariableOwner", + "com.vaadin.tools.ReflectTools", + "com.vaadin.tools.WidgetsetCompiler", + "com.vaadin.ui.AbsoluteLayout", "com.vaadin.ui.AbstractComponent", + "com.vaadin.ui.AbstractComponentContainer", + "com.vaadin.ui.AbstractField", "com.vaadin.ui.AbstractLayout", + "com.vaadin.ui.AbstractOrderedLayout", + "com.vaadin.ui.AbstractSelect", "com.vaadin.ui.Accordion", + "com.vaadin.ui.Alignment", "com.vaadin.ui.AlignmentUtils", + "com.vaadin.ui.BaseFieldFactory", "com.vaadin.ui.Button", + "com.vaadin.ui.CheckBox", "com.vaadin.ui.ClientWidget", + "com.vaadin.ui.ComboBox", "com.vaadin.ui.Component", + "com.vaadin.ui.ComponentContainer", "com.vaadin.ui.CssLayout", + "com.vaadin.ui.CustomComponent", "com.vaadin.ui.CustomLayout", + "com.vaadin.ui.DateField", "com.vaadin.ui.DefaultFieldFactory", + "com.vaadin.ui.Embedded", "com.vaadin.ui.ExpandLayout", + "com.vaadin.ui.Field", "com.vaadin.ui.FieldFactory", + "com.vaadin.ui.Form", "com.vaadin.ui.FormFieldFactory", + "com.vaadin.ui.FormLayout", "com.vaadin.ui.GridLayout", + "com.vaadin.ui.HorizontalLayout", "com.vaadin.ui.InlineDateField", + "com.vaadin.ui.Label", "com.vaadin.ui.Layout", + "com.vaadin.ui.Link", "com.vaadin.ui.ListSelect", + "com.vaadin.ui.LoginForm", "com.vaadin.ui.MenuBar", + "com.vaadin.ui.NativeButton", "com.vaadin.ui.NativeSelect", + "com.vaadin.ui.OptionGroup", "com.vaadin.ui.OrderedLayout", + "com.vaadin.ui.Panel", "com.vaadin.ui.PopupDateField", + "com.vaadin.ui.PopupView", "com.vaadin.ui.ProgressIndicator", + "com.vaadin.ui.RichTextArea", "com.vaadin.ui.Select", + "com.vaadin.ui.Slider", "com.vaadin.ui.SplitPanel", + "com.vaadin.ui.Table", "com.vaadin.ui.TableFieldFactory", + "com.vaadin.ui.TabSheet", "com.vaadin.ui.TextField", + "com.vaadin.ui.Tree", "com.vaadin.ui.TwinColSelect", + "com.vaadin.ui.Upload", "com.vaadin.ui.UriFragmentUtility", + "com.vaadin.ui.VerticalLayout", "com.vaadin.ui.Window", + "com.vaadin.util.SerializerHelper", "org.vaadin.test.LastClass" }; + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java new file mode 100644 index 0000000000..772cd250ce --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java @@ -0,0 +1,256 @@ +package com.vaadin.data.util; + +import java.util.Collection; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Hierarchical; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; + +public abstract class AbstractHierarchicalContainerTest extends + AbstractContainerTest { + + /** + * @param container + * The container to validate + * @param expectedFirstItemId + * Expected first item id + * @param expectedLastItemId + * Expected last item id + * @param itemIdInSet + * An item id that is in the container + * @param itemIdNotInSet + * An item id that is not in the container + * @param checkGetItemNull + * true if getItem() should return null for itemIdNotInSet, false + * to skip the check (container.containsId() is checked in any + * case) + * @param expectedSize + * Expected number of items in the container. Not related to + * hierarchy. + * @param expectedTraversalSize + * Expected number of items found when traversing from the roots + * down to all available nodes. + * @param expectedRootSize + * Expected number of root items + * @param rootsHaveChildren + * true if all roots have children, false otherwise (skips some + * asserts) + */ + protected void validateHierarchicalContainer(Hierarchical container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize, int expectedRootSize, + boolean rootsHaveChildren) { + + validateContainer(container, expectedFirstItemId, expectedLastItemId, + itemIdInSet, itemIdNotInSet, checkGetItemNull, expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(expectedRootSize, rootIds.size()); + + for (Object rootId : rootIds) { + // All roots must be in container + assertTrue(container.containsId(rootId)); + + // All roots must have no parent + assertNull(container.getParent(rootId)); + + // all roots must be roots + assertTrue(container.isRoot(rootId)); + + if (rootsHaveChildren) { + // all roots have children allowed in this case + assertTrue(container.areChildrenAllowed(rootId)); + + // all roots have children in this case + Collection<?> children = container.getChildren(rootId); + assertNotNull(rootId + " should have children", children); + assertTrue(rootId + " should have children", + (children.size() > 0)); + // getParent + for (Object childId : children) { + assertEquals(container.getParent(childId), rootId); + } + + } + } + + // isRoot should return false for unknown items + assertFalse(container.isRoot(itemIdNotInSet)); + + // hasChildren should return false for unknown items + assertFalse(container.hasChildren(itemIdNotInSet)); + + // areChildrenAllowed should return false for unknown items + assertFalse(container.areChildrenAllowed(itemIdNotInSet)); + + // removeItem of unknown items should return false + assertFalse(container.removeItem(itemIdNotInSet)); + + assertEquals(expectedSize, countNodes(container)); + + validateHierarchy(container); + } + + private int countNodes(Hierarchical container) { + int totalNodes = 0; + for (Object rootId : container.rootItemIds()) { + totalNodes += countNodes(container, rootId); + } + + return totalNodes; + } + + private int countNodes(Hierarchical container, Object itemId) { + int nodes = 1; // This + Collection<?> children = container.getChildren(itemId); + if (children != null) { + for (Object id : children) { + nodes += countNodes(container, id); + } + } + + return nodes; + } + + private void validateHierarchy(Hierarchical container) { + for (Object rootId : container.rootItemIds()) { + validateHierarchy(container, rootId, null); + } + } + + private void validateHierarchy(Hierarchical container, Object itemId, + Object parentId) { + Collection<?> children = container.getChildren(itemId); + + // getParent + assertEquals(container.getParent(itemId), parentId); + + if (!container.areChildrenAllowed(itemId)) { + // If no children is allowed the item should have no children + assertFalse(container.hasChildren(itemId)); + assertTrue(children == null || children.size() == 0); + + return; + } + if (children != null) { + for (Object id : children) { + validateHierarchy(container, id, itemId); + } + } + } + + protected void testHierarchicalContainer(Container.Hierarchical container) { + initializeContainer(container); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void testHierarchicalSorting(Container.Hierarchical container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 and PROP2 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds().contains( + REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateHierarchicalContainer(container, + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void initializeContainer(Container.Hierarchical container) { + container.removeAllItems(); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + + // Add path as parent + String paths[] = id.split("\\."); + String path = paths[0]; + // Adds "com" and other items multiple times so should return null + // for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME).setValue(getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + } + for (int j = 1; j < paths.length; j++) { + String parent = path; + path = path + "." + paths[j]; + + // Adds "com" and other items multiple times so should return + // null for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + + } + assertTrue(container.setChildrenAllowed(parent, true)); + assertTrue( + "Failed to set " + parent + " as parent for " + path, + container.setParent(path, parent)); + } + + Item item = container.getItem(id); + assertNotNull(item); + String parent = id.substring(0, id.lastIndexOf('.')); + assertTrue(container.setParent(id, parent)); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i % 2); + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java new file mode 100644 index 0000000000..bbad33c5bc --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java @@ -0,0 +1,6 @@ +package com.vaadin.data.util; + +public abstract class AbstractInMemoryContainerTest extends + AbstractContainerTest { + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java new file mode 100644 index 0000000000..9037e303a8 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java @@ -0,0 +1,460 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import junit.framework.Assert; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.AbstractBeanContainer.BeanIdResolver; + +public class BeanContainerTest extends AbstractBeanContainerTest { + + protected static class PersonNameResolver implements + BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return bean != null ? bean.getName() : null; + } + + } + + protected static class NullResolver implements + BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return null; + } + + } + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanContainer<String, ClassName> getContainer() { + return new BeanContainer<String, ClassName>(ClassName.class); + } + + @Override + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanContainer<String, ClassName> beanItemContainer = (BeanContainer<String, ClassName>) container; + + beanItemContainer.removeAllItems(); + + for (Entry<String, ClassName> entry : nameToBean.entrySet()) { + beanItemContainer.addItem(entry.getKey(), entry.getValue()); + } + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + public void testSorting() { + testContainerSorting(getContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanContainer differs from other containers + public void testContainerOrdered() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + String id = "test1"; + + Item item = container.addItem(id, "value"); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId, "newFirstValue"); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId, + "newSecondValue"); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId, + "fourthValue"); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId, "fifthValue"); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + // TODO test Container.Indexed interface operation - testContainerIndexed()? + + public void testAddItemAt() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + container.addItem("id1", "value1"); + // id1 + container.addItemAt(0, "id2", "value2"); + // id2, id1 + container.addItemAt(1, "id3", "value3"); + // id2, id3, id1 + container.addItemAt(container.size(), "id4", "value4"); + // id2, id3, id1, id4 + + assertNull(container.addItemAt(-1, "id5", "value5")); + assertNull(container.addItemAt(container.size() + 1, "id6", "value6")); + + assertEquals(4, container.size()); + assertEquals("id2", container.getIdByIndex(0)); + assertEquals("id3", container.getIdByIndex(1)); + assertEquals("id1", container.getIdByIndex(2)); + assertEquals("id4", container.getIdByIndex(3)); + } + + public void testUnsupportedMethods() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.addItem("John", new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItem(null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(null, null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0, new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + public void testRemoveContainerProperty() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + container.addBean(new Person("John")); + + Assert.assertEquals("John", + container.getContainerProperty("John", "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty("John", "name")); + + Assert.assertNotNull(container.getItem("John")); + // property removed also from item + Assert.assertNull(container.getItem("John").getItemProperty("name")); + } + + public void testAddNullBeans() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.addItem("id1", null)); + assertNull(container.addItemAfter(null, "id2", null)); + assertNull(container.addItemAt(0, "id3", null)); + + assertEquals(0, container.size()); + } + + public void testAddNullId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + Person john = new Person("John"); + + assertNull(container.addItem(null, john)); + assertNull(container.addItemAfter(null, null, john)); + assertNull(container.addItemAt(0, null, john)); + + assertEquals(0, container.size()); + } + + public void testEmptyContainer() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.firstItemId()); + assertNull(container.lastItemId()); + + assertEquals(0, container.size()); + + // could test more about empty container + } + + public void testAddBeanWithoutResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container + .addAll(Arrays.asList(new Person[] { new Person("Jack") })); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + public void testAddAllWithNullItemId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container + .setBeanIdResolver(new BeanIdResolver<String, AbstractBeanContainerTest.Person>() { + + @Override + public String getIdForBean(Person bean) { + return bean.getName(); + } + }); + + List<Person> persons = new ArrayList<Person>(); + persons.add(new Person("John")); + persons.add(new Person("Marc")); + persons.add(new Person(null)); + persons.add(new Person("foo")); + + try { + container.addAll(persons); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + container.removeAllItems(); + persons.remove(2); + container.addAll(persons); + assertEquals(3, container.size()); + } + + public void testAddBeanWithNullResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container.setBeanIdResolver(new NullResolver()); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + public void testAddBeanWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList(new Person[] { new Person("Jill"), + new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + public void testAddNullBeansWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNull(container.addBean(null)); + assertNull(container.addBeanAfter(null, null)); + assertNull(container.addBeanAt(0, null)); + + assertEquals(0, container.size()); + } + + public void testAddBeanWithPropertyResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdProperty("name"); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList(new Person[] { new Person("Jill"), + new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + public void testAddNestedContainerProperty() { + BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + container.setBeanIdProperty("name"); + + container.addBean(new NestedMethodPropertyTest.Person("John", + new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540))); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", + container.getContainerProperty("John", "address.street") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java new file mode 100644 index 0000000000..38f317fef1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java @@ -0,0 +1,170 @@ +package com.vaadin.data.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.data.util.DefaultItemSorter; + +public class BeanItemContainerSortTest { + public class Person { + private String name; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + private int age; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public class Parent extends Person { + private Set<Person> children = new HashSet<Person>(); + + public void setChildren(Set<Person> children) { + this.children = children; + } + + public Set<Person> getChildren() { + return children; + } + } + + String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko", + "Pekka", "John" }; + int[] ages = new int[] { 10, 20, 50, 12, 64, 67 }; + String[] sortedByAge = new String[] { names[0], names[3], names[1], + names[2], names[4], names[5] }; + + public BeanItemContainer<Person> getContainer() { + BeanItemContainer<Person> bc = new BeanItemContainer<Person>( + Person.class); + for (int i = 0; i < names.length; i++) { + Person p = new Person(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + + } + + public BeanItemContainer<Parent> getParentContainer() { + BeanItemContainer<Parent> bc = new BeanItemContainer<Parent>( + Parent.class); + for (int i = 0; i < names.length; i++) { + Parent p = new Parent(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + } + + @Test + public void testSort() { + testSort(true); + } + + public void testSort(boolean b) { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "name" }, new boolean[] { b }); + + List<String> asList = Arrays.asList(names); + Collections.sort(asList); + if (!b) { + Collections.reverse(asList); + } + + int i = 0; + for (String string : asList) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testReverseSort() { + testSort(false); + } + + @Test + public void primitiveSorting() { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = 0; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void customSorting() { + BeanItemContainer<Person> container = getContainer(); + + // custom sorter using the reverse order + container.setItemSorter(new DefaultItemSorter() { + @Override + public int compare(Object o1, Object o2) { + return -super.compare(o1, o2); + } + }); + + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = container.size() - 1; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i--); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testGetSortableProperties() { + BeanItemContainer<Person> container = getContainer(); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + + @Test + public void testGetNonSortableProperties() { + BeanItemContainer<Parent> container = getParentContainer(); + + Assert.assertEquals(3, container.getContainerPropertyIds().size()); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java new file mode 100644 index 0000000000..29043b1670 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java @@ -0,0 +1,718 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItemContainer; + +/** + * Test basic functionality of BeanItemContainer. + * + * Most sorting related tests are in {@link BeanItemContainerSortTest}. + */ +public class BeanItemContainerTest extends AbstractBeanContainerTest { + + // basics from the common container test + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanItemContainer<ClassName> getContainer() { + return new BeanItemContainer<ClassName>(ClassName.class); + } + + @Override + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanItemContainer<ClassName> beanItemContainer = (BeanItemContainer<ClassName>) container; + + beanItemContainer.removeAllItems(); + + Iterator<ClassName> it = nameToBean.values().iterator(); + while (it.hasNext()) { + beanItemContainer.addBean(it.next()); + } + } + + @Override + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize) { + Object notInSet = nameToBean.get(itemIdNotInSet); + if (notInSet == null && itemIdNotInSet != null) { + notInSet = new ClassName(String.valueOf(itemIdNotInSet), 9999); + } + super.validateContainer(container, nameToBean.get(expectedFirstItemId), + nameToBean.get(expectedLastItemId), + nameToBean.get(itemIdInSet), notInSet, checkGetItemNull, + expectedSize); + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + public void testSorting() { + testContainerSorting(getContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanItemContainer differs from other containers + public void testContainerOrdered() { + BeanItemContainer<String> container = new BeanItemContainer<String>( + String.class); + + String id = "test1"; + + Item item = container.addBean(id); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(Object) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(Object,Object) + Object fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + public void testContainerIndexed() { + testContainerIndexed(getContainer(), nameToBean.get(sampleData[2]), 2, + false, new ClassName("org.vaadin.test.Test", 8888), true); + } + + @SuppressWarnings("deprecation") + public void testCollectionConstructors() { + List<ClassName> classNames = new ArrayList<ClassName>(); + classNames.add(new ClassName("a.b.c.Def", 1)); + classNames.add(new ClassName("a.b.c.Fed", 2)); + classNames.add(new ClassName("b.c.d.Def", 3)); + + // note that this constructor is problematic, users should use the + // version that + // takes the bean class as a parameter + BeanItemContainer<ClassName> container = new BeanItemContainer<ClassName>( + classNames); + + Assert.assertEquals(3, container.size()); + Assert.assertEquals(classNames.get(0), container.firstItemId()); + Assert.assertEquals(classNames.get(1), container.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container.lastItemId()); + + BeanItemContainer<ClassName> container2 = new BeanItemContainer<ClassName>( + ClassName.class, classNames); + + Assert.assertEquals(3, container2.size()); + Assert.assertEquals(classNames.get(0), container2.firstItemId()); + Assert.assertEquals(classNames.get(1), container2.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container2.lastItemId()); + } + + // this only applies to the collection constructor with no type parameter + @SuppressWarnings("deprecation") + public void testEmptyCollectionConstructor() { + try { + new BeanItemContainer<ClassName>((Collection<ClassName>) null); + Assert.fail("Initializing BeanItemContainer from a null collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + try { + new BeanItemContainer<ClassName>(new ArrayList<ClassName>()); + Assert.fail("Initializing BeanItemContainer from an empty collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + } + + public void testItemSetChangeListeners() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + + initializeContainer(container); + counter.reset(); + container.addBean(cn1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + // no notification if already in container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + public void testItemSetChangeListenersFiltering() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + ClassName other = new ClassName("com.example.Other", 3333); + + // simply adding or removing container filters should cause event + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + + // perform operations while filtering container + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + counter.assertOnce(); + + // passes filter + container.addBean(cn1); + counter.assertOnce(); + + // passes filter but already in the container + container.addBean(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + + // passes filter + container.addItem(cn1); + counter.assertOnce(); + // already in the container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + // does not pass filter + container.addItem(other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + // does not pass filter + // note: testAddRemoveWhileFiltering() checks position for these after + // removing filter etc, here concentrating on listeners + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), other); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + container.removeItem(cn1); + counter.assertOnce(); + + // does not pass filter + + initializeContainer(container); + counter.reset(); + // not visible + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertNone(); + + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + + public void testAddRemoveWhileFiltering() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + Person william = new Person("William"); + Person julia = new Person("Julia"); + Person george = new Person("George"); + Person mark = new Person("Mark"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // add a bean that passes the filter + container.addBean(jack); + assertEquals(3, container.size()); + assertEquals(jack, container.lastItemId()); + // john, jane, (matthew), jack + + // add beans that do not pass the filter + container.addBean(michael); + // john, jane, (matthew), jack, (michael) + container.addItemAfter(null, william); + // (william), john, jane, (matthew), jack, (michael) + + // add after an item that is shown + container.addItemAfter(john, george); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + // add after an item that is not shown does nothing + container.addItemAfter(william, julia); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + container.addItemAt(1, julia); + // (william), john, julia, (george), jane, (matthew), jack, (michael) + + container.addItemAt(2, mark); + // (william), john, julia, (mark), (george), jane, (matthew), jack, + // (michael) + + container.removeItem(matthew); + // (william), john, julia, (mark), (george), jane, jack, (michael) + + assertEquals(4, container.size()); + assertEquals(jack, container.lastItemId()); + + container.removeContainerFilters("name"); + + assertEquals(8, container.size()); + assertEquals(william, container.firstItemId()); + assertEquals(john, container.nextItemId(william)); + assertEquals(julia, container.nextItemId(john)); + assertEquals(mark, container.nextItemId(julia)); + assertEquals(george, container.nextItemId(mark)); + assertEquals(jane, container.nextItemId(george)); + assertEquals(jack, container.nextItemId(jane)); + assertEquals(michael, container.lastItemId()); + } + + public void testRefilterOnPropertyModification() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // #6053 currently, modification of an item that is not visible does not + // trigger refiltering - should it? + // matthew.setName("Julia"); + // assertEquals(3, container.size()); + // john, jane, julia + + john.setName("Mark"); + assertEquals(2, container.size()); + // (mark), jane, julia + + container.removeAllContainerFilters(); + + assertEquals(3, container.size()); + } + + public void testAddAll() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + + // addAll + container.addAll(Arrays.asList(jack, michael)); + // john, jane, matthew, jack, michael + + assertEquals(5, container.size()); + assertEquals(jane, container.nextItemId(john)); + assertEquals(matthew, container.nextItemId(jane)); + assertEquals(jack, container.nextItemId(matthew)); + assertEquals(michael, container.nextItemId(jack)); + } + + public void testUnsupportedMethods() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + container.addBean(new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + public void testRemoveContainerProperty() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + Assert.assertEquals("John", container + .getContainerProperty(john, "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty(john, "name")); + + Assert.assertNotNull(container.getItem(john)); + // property removed also from item + Assert.assertNull(container.getItem(john).getItemProperty("name")); + } + + public void testAddNullBean() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + assertNull(container.addItem(null)); + assertNull(container.addItemAfter(null, null)); + assertNull(container.addItemAfter(john, null)); + assertNull(container.addItemAt(0, null)); + + assertEquals(1, container.size()); + } + + public void testBeanIdResolver() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + + assertSame(john, container.getBeanIdResolver().getIdForBean(john)); + } + + public void testNullBeanClass() { + try { + new BeanItemContainer<Object>((Class<Object>) null); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testAddNestedContainerProperty() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", + 20540)); + container.addBean(john); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", + container.getContainerProperty(john, "address.street") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemTest.java b/server/tests/src/com/vaadin/data/util/BeanItemTest.java new file mode 100644 index 0000000000..e1ad75796c --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemTest.java @@ -0,0 +1,333 @@ +package com.vaadin.data.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +/** + * Test BeanItem specific features. + * + * Only public API is tested, not the methods with package visibility. + * + * See also {@link PropertySetItemTest}, which tests the base class. + */ +public class BeanItemTest extends TestCase { + + @SuppressWarnings("unused") + protected static class MySuperClass { + private int superPrivate = 1; + private int superPrivate2 = 2; + protected double superProtected = 3.0; + private double superProtected2 = 4.0; + public boolean superPublic = true; + private boolean superPublic2 = true; + + public int getSuperPrivate() { + return superPrivate; + } + + public void setSuperPrivate(int superPrivate) { + this.superPrivate = superPrivate; + } + + public double getSuperProtected() { + return superProtected; + } + + public void setSuperProtected(double superProtected) { + this.superProtected = superProtected; + } + + public boolean isSuperPublic() { + return superPublic; + } + + public void setSuperPublic(boolean superPublic) { + this.superPublic = superPublic; + } + + } + + protected static class MyClass extends MySuperClass { + private String name; + public int value = 123; + + public MyClass(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setNoField(String name) { + } + + public String getNoField() { + return "no field backing this setter"; + } + + public String getName2() { + return name; + } + } + + protected static class MyClass2 extends MyClass { + public MyClass2(String name) { + super(name); + } + + @Override + public void setName(String name) { + super.setName(name + "2"); + } + + @Override + public String getName() { + return super.getName() + "2"; + } + + @Override + public String getName2() { + return super.getName(); + } + + public void setName2(String name) { + super.setName(name); + } + } + + protected static interface MySuperInterface { + public int getSuper1(); + + public void setSuper1(int i); + + public int getOverride(); + } + + protected static interface MySuperInterface2 { + public int getSuper2(); + } + + protected static interface MySubInterface extends MySuperInterface, + MySuperInterface2 { + public int getSub(); + + public void setSub(int i); + + @Override + public int getOverride(); + + public void setOverride(int i); + } + + public void testGetProperties() { + BeanItem<MySuperClass> item = new BeanItem<MySuperClass>( + new MySuperClass()); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(3, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + } + + public void testGetSuperClassProperties() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + Assert.assertTrue(itemPropertyIds.contains("name")); + Assert.assertTrue(itemPropertyIds.contains("noField")); + Assert.assertTrue(itemPropertyIds.contains("name2")); + } + + public void testOverridingProperties() { + BeanItem<MyClass2> item = new BeanItem<MyClass2>(new MyClass2("bean2")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + Assert.assertTrue(MyClass2.class.equals(item.getBean().getClass())); + + // check that name2 accessed via MyClass2, not MyClass + Assert.assertFalse(item.getItemProperty("name2").isReadOnly()); + } + + public void testGetInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class.getDeclaredMethod( + "getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySuperInterface.class); + + Assert.assertEquals(2, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertTrue(property.isReadOnly()); + } + + public void testGetSuperInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class.getDeclaredMethod( + "getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySubInterface.class); + + Assert.assertEquals(4, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("sub")); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("super2")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertFalse(property.isReadOnly()); + } + + public void testPropertyExplicitOrder() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name"); + ids.add("superPublic"); + ids.add("name2"); + ids.add("noField"); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testPropertyExplicitOrder2() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + new String[] { "name", "superPublic", "name2", "noField" }); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testPropertyBadPropertyName() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name3"); + ids.add("name"); + + // currently silently ignores non-existent properties + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testRemoveProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("name2"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("name2")); + } + + public void testRemoveSuperProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("superPrivate"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("superPrivate")); + } + + public void testPropertyTypes() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertTrue(Integer.class.equals(item.getItemProperty( + "superPrivate").getType())); + Assert.assertTrue(Double.class.equals(item.getItemProperty( + "superProtected").getType())); + Assert.assertTrue(Boolean.class.equals(item.getItemProperty( + "superPublic").getType())); + Assert.assertTrue(String.class.equals(item.getItemProperty("name") + .getType())); + } + + public void testPropertyReadOnly() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertFalse(item.getItemProperty("name").isReadOnly()); + Assert.assertTrue(item.getItemProperty("name2").isReadOnly()); + } + + public void testCustomProperties() throws Exception { + LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>> propertyDescriptors = new LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>>(); + propertyDescriptors.put( + "myname", + new MethodPropertyDescriptor<BeanItemTest.MyClass>("myname", + MyClass.class, MyClass.class + .getDeclaredMethod("getName"), MyClass.class + .getDeclaredMethod("setName", String.class))); + MyClass instance = new MyClass("bean1"); + Constructor<BeanItem> constructor = BeanItem.class + .getDeclaredConstructor(Object.class, Map.class); + constructor.setAccessible(true); + BeanItem<MyClass> item = constructor.newInstance(instance, + propertyDescriptors); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + } + + public void testAddRemoveProperty() throws Exception { + MethodPropertyDescriptor<BeanItemTest.MyClass> pd = new MethodPropertyDescriptor<BeanItemTest.MyClass>( + "myname", MyClass.class, + MyClass.class.getDeclaredMethod("getName"), + MyClass.class.getDeclaredMethod("setName", String.class)); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + + item.addItemProperty("myname", pd.createProperty(item.getBean())); + Assert.assertEquals(7, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + item.removeItemProperty("myname"); + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java b/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java new file mode 100644 index 0000000000..f4bb794e5c --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java @@ -0,0 +1,16 @@ +package com.vaadin.data.util; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Test; + +public class FileSystemContainerTest { + + @Test + public void nonExistingDirectory() { + FilesystemContainer fsc = new FilesystemContainer(new File( + "/non/existing")); + Assert.assertTrue(fsc.getItemIds().isEmpty()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java new file mode 100644 index 0000000000..640ede8743 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java @@ -0,0 +1,327 @@ +package com.vaadin.data.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class NestedMethodPropertyTest extends TestCase { + + public static class Address implements Serializable { + private String street; + private int postalCodePrimitive; + private Integer postalCodeObject; + + public Address(String street, int postalCode) { + this.street = street; + postalCodePrimitive = postalCode; + postalCodeObject = postalCode; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getStreet() { + return street; + } + + public void setPostalCodePrimitive(int postalCodePrimitive) { + this.postalCodePrimitive = postalCodePrimitive; + } + + public int getPostalCodePrimitive() { + return postalCodePrimitive; + } + + public void setPostalCodeObject(Integer postalCodeObject) { + this.postalCodeObject = postalCodeObject; + } + + public Integer getPostalCodeObject() { + return postalCodeObject; + } + + // read-only boolean property + public boolean isBoolean() { + return true; + } + } + + public static class Person implements Serializable { + private String name; + private Address address; + + public Person(String name, Address address) { + this.name = name; + this.address = address; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Address getAddress() { + return address; + } + } + + public static class Team implements Serializable { + private String name; + private Person manager; + + public Team(String name, Person manager) { + this.name = name; + this.manager = manager; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setManager(Person manager) { + this.manager = manager; + } + + public Person getManager() { + return manager; + } + } + + private Address oldMill; + private Person joonas; + private Team vaadin; + + @Override + public void setUp() { + oldMill = new Address("Ruukinkatu 2-4", 20540); + joonas = new Person("Joonas", oldMill); + vaadin = new Team("Vaadin", joonas); + } + + @Override + public void tearDown() { + vaadin = null; + joonas = null; + oldMill = null; + } + + public void testSingleLevelNestedSimpleProperty() { + NestedMethodProperty<String> nameProperty = new NestedMethodProperty<String>( + vaadin, "name"); + + Assert.assertEquals(String.class, nameProperty.getType()); + Assert.assertEquals("Vaadin", nameProperty.getValue()); + } + + public void testSingleLevelNestedObjectProperty() { + NestedMethodProperty<Person> managerProperty = new NestedMethodProperty<Person>( + vaadin, "manager"); + + Assert.assertEquals(Person.class, managerProperty.getType()); + Assert.assertEquals(joonas, managerProperty.getValue()); + } + + public void testMultiLevelNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertEquals(String.class, managerNameProperty.getType()); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + + Assert.assertEquals(Address.class, addressProperty.getType()); + Assert.assertEquals(oldMill, addressProperty.getValue()); + + Assert.assertEquals(String.class, streetProperty.getType()); + Assert.assertEquals("Ruukinkatu 2-4", streetProperty.getValue()); + + Assert.assertEquals(Integer.class, + postalCodePrimitiveProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodePrimitiveProperty.getValue()); + + Assert.assertEquals(Integer.class, postalCodeObjectProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodeObjectProperty.getValue()); + + Assert.assertEquals(Boolean.class, booleanProperty.getType()); + Assert.assertEquals(Boolean.TRUE, booleanProperty.getValue()); + } + + public void testEmptyPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, ""); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, " "); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testInvalidPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, ".manager"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager..name"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testInvalidNestedPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "member"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.pet"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.address.city"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testNullNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + + joonas.setAddress(null); + try { + streetProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + + vaadin.setManager(null); + try { + managerNameProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + try { + streetProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + + vaadin.setManager(joonas); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + } + + public void testMultiLevelNestedPropertySetValue() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + + managerNameProperty.setValue("Joonas L"); + Assert.assertEquals("Joonas L", joonas.getName()); + streetProperty.setValue("Ruukinkatu"); + Assert.assertEquals("Ruukinkatu", oldMill.getStreet()); + postalCodePrimitiveProperty.setValue(0); + postalCodeObjectProperty.setValue(1); + Assert.assertEquals(0, oldMill.getPostalCodePrimitive()); + Assert.assertEquals(Integer.valueOf(1), oldMill.getPostalCodeObject()); + + postalCodeObjectProperty.setValue(null); + Assert.assertNull(oldMill.getPostalCodeObject()); + + Address address2 = new Address("Other street", 12345); + addressProperty.setValue(address2); + Assert.assertEquals("Other street", streetProperty.getValue()); + } + + public void testSerialization() throws IOException, ClassNotFoundException { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(streetProperty); + @SuppressWarnings("unchecked") + NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Assert.assertEquals("Ruukinkatu 2-4", property2.getValue()); + } + + public void testIsReadOnly() { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertFalse(streetProperty.isReadOnly()); + Assert.assertTrue(booleanProperty.isReadOnly()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java b/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java new file mode 100644 index 0000000000..99ca58ba42 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java @@ -0,0 +1,97 @@ +package com.vaadin.data.util; + +import junit.framework.TestCase; + +import org.junit.Assert; + +public class ObjectPropertyTest extends TestCase { + + public static class TestSuperClass { + private String name; + + public TestSuperClass(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return getName(); + } + } + + public static class TestSubClass extends TestSuperClass { + public TestSubClass(String name) { + super("Subclass: " + name); + } + } + + private TestSuperClass super1 = new TestSuperClass("super1"); + private TestSubClass sub1 = new TestSubClass("sub1"); + + public void testSimple() { + ObjectProperty<TestSuperClass> prop1 = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop1.getValue().getName()); + prop1 = new ObjectProperty<TestSuperClass>(super1); + Assert.assertEquals("super1", prop1.getValue().getName()); + + ObjectProperty<TestSubClass> prop2 = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + prop2 = new ObjectProperty<TestSubClass>(sub1); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + } + + public void testSetValueObjectSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + public void testSetValueObjectSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + public void testSetValueStringSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + public void testSetValueStringSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + public void testMixedGenerics() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + sub1); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + Assert.assertEquals(prop.getType(), TestSubClass.class); + // create correct subclass based on the runtime type of the instance + // given to ObjectProperty constructor, which is a subclass of the type + // parameter + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java new file mode 100644 index 0000000000..c4ed12efc0 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java @@ -0,0 +1,117 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.util.IndexedContainer; + +public class PerformanceTestIndexedContainer extends TestCase { + + private static final int REPEATS = 10; + private final static int ITEMS = 50000; + private static final long ADD_ITEM_FAIL_THRESHOLD = 200; + // TODO should improve performance of these methods + private static final long ADD_ITEM_AT_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD = 200; + + public void testAddItemPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItem(); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItem()", + ADD_ITEM_FAIL_THRESHOLD); + } + + public void testAddItemAtPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAt(0); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAt()", + ADD_ITEM_AT_FAIL_THRESHOLD); + } + + public void testAddItemAfterPerformance() { + Object initialId = "Item0"; + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(initialId); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAfter(initialId); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAfter()", + ADD_ITEM_AFTER_FAIL_THRESHOLD); + } + + public void testAddItemAfterLastPerformance() { + // TODO running with less items because slow otherwise + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS / 3; i++) { + c.addItemAfter(c.lastItemId()); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS / 3, times, "IndexedContainer.addItemAfter(lastId)", + ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD); + } + + public void testAddItemsConstructorPerformance() { + Collection<Object> items = new ArrayList<Object>(50000); + for (int i = 0; i < ITEMS; ++i) { + items.add(new Object()); + } + + SortedSet<Long> times = new TreeSet<Long>(); + for (int j = 0; j < REPEATS; ++j) { + long start = System.currentTimeMillis(); + new IndexedContainer(items); + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer(Collection)", + ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD); + } + + private void checkMedian(int items, Collection<Long> times, + String methodName, long threshold) { + long median = median(times); + System.out.println(methodName + " timings (ms) for " + items + + " items: " + times); + Assert.assertTrue(methodName + " too slow, median time " + median + + "ms for " + items + " items", median <= threshold); + } + + private Long median(Collection<Long> times) { + ArrayList<Long> list = new ArrayList<Long>(times); + Collections.sort(list); + // not exact median in some cases, but good enough + return list.get(list.size() / 2); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java new file mode 100644 index 0000000000..14e70d76d4 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java @@ -0,0 +1,55 @@ +package com.vaadin.data.util; + +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.Property; +import com.vaadin.data.util.NestedMethodPropertyTest.Person; + +public class PropertyDescriptorTest extends TestCase { + public void testMethodPropertyDescriptorSerialization() throws Exception { + PropertyDescriptor[] pds = Introspector.getBeanInfo(Person.class) + .getPropertyDescriptors(); + + MethodPropertyDescriptor<Person> descriptor = null; + + for (PropertyDescriptor pd : pds) { + if ("name".equals(pd.getName())) { + descriptor = new MethodPropertyDescriptor<Person>(pd.getName(), + String.class, pd.getReadMethod(), pd.getWriteMethod()); + break; + } + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(descriptor); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> descriptor2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = descriptor2.createProperty(new Person("John", + null)); + Assert.assertEquals("John", property.getValue()); + } + + public void testNestedPropertyDescriptorSerialization() throws Exception { + NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>( + "name", Person.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(pd); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = pd2.createProperty(new Person("John", null)); + Assert.assertEquals("John", property.getValue()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java b/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java new file mode 100644 index 0000000000..a3169332ec --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java @@ -0,0 +1,405 @@ +package com.vaadin.data.util; + +import java.util.Iterator; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.data.Item.PropertySetChangeEvent; +import com.vaadin.data.Item.PropertySetChangeListener; + +public class PropertySetItemTest extends TestCase { + + private static final String ID1 = "id1"; + private static final String ID2 = "id2"; + private static final String ID3 = "id3"; + + private static final String VALUE1 = "value1"; + private static final String VALUE2 = "value2"; + private static final String VALUE3 = "value3"; + + private ObjectProperty<String> prop1; + private ObjectProperty<String> prop2; + private ObjectProperty<String> prop3; + + private PropertySetChangeListener propertySetListenerMock; + private PropertySetChangeListener propertySetListenerMock2; + + @Override + protected void setUp() throws Exception { + prop1 = new ObjectProperty<String>(VALUE1, String.class); + prop2 = new ObjectProperty<String>(VALUE2, String.class); + prop3 = new ObjectProperty<String>(VALUE3, String.class); + + propertySetListenerMock = EasyMock + .createStrictMock(PropertySetChangeListener.class); + propertySetListenerMock2 = EasyMock + .createMock(PropertySetChangeListener.class); + } + + @Override + protected void tearDown() throws Exception { + prop1 = null; + prop2 = null; + prop3 = null; + + propertySetListenerMock = null; + propertySetListenerMock2 = null; + } + + private PropertysetItem createPropertySetItem() { + return new PropertysetItem(); + } + + public void testEmptyItem() { + PropertysetItem item = createPropertySetItem(); + Assert.assertNotNull(item.getItemPropertyIds()); + Assert.assertEquals(0, item.getItemPropertyIds().size()); + } + + public void testGetProperty() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertNull(item.getItemProperty(ID1)); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertNull(item.getItemProperty(ID2)); + } + + public void testAddSingleProperty() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Object firstValue = item.getItemPropertyIds().iterator().next(); + Assert.assertEquals(ID1, firstValue); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testAddMultipleProperties() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + item.addItemProperty(ID2, prop2); + Assert.assertEquals(2, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertEquals(prop2, item.getItemProperty(ID2)); + + item.addItemProperty(ID3, prop3); + Assert.assertEquals(3, item.getItemPropertyIds().size()); + } + + public void testAddedPropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID2, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + public void testAddPropertyTwice() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + Assert.assertFalse(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testCannotChangeProperty() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + Assert.assertFalse(item.addItemProperty(ID1, prop2)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testRemoveProperty() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.removeItemProperty(ID1); + + Assert.assertEquals(0, item.getItemPropertyIds().size()); + Assert.assertNull(item.getItemProperty(ID1)); + } + + public void testRemovePropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + item.removeItemProperty(ID2); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + public void testRemoveNonExistentListener() { + PropertysetItem item = createPropertySetItem(); + item.removeListener(propertySetListenerMock); + } + + public void testRemoveListenerTwice() { + PropertysetItem item = createPropertySetItem(); + item.addListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + } + + public void testAddPropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange(EasyMock + .isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.addItemProperty(ID1, prop1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener when adding a + // property + item.removeListener(propertySetListenerMock); + item.addItemProperty(ID2, prop2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + public void testRemovePropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange(EasyMock + .isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.removeItemProperty(ID1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener + item.removeListener(propertySetListenerMock); + item.removeItemProperty(ID2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + public void testItemEqualsNull() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertFalse(item.equals(null)); + } + + public void testEmptyItemEquals() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertTrue(item1.equals(item2)); + } + + public void testItemEqualsSingleProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + PropertysetItem item4 = createPropertySetItem(); + item4.addItemProperty(ID1, prop2); + PropertysetItem item5 = createPropertySetItem(); + item5.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item1.equals(item3)); + Assert.assertFalse(item1.equals(item4)); + Assert.assertFalse(item1.equals(item5)); + + Assert.assertTrue(item2.equals(item3)); + Assert.assertFalse(item2.equals(item4)); + Assert.assertFalse(item2.equals(item5)); + + Assert.assertFalse(item3.equals(item4)); + Assert.assertFalse(item3.equals(item5)); + + Assert.assertFalse(item4.equals(item5)); + + Assert.assertFalse(item2.equals(item1)); + } + + public void testItemEqualsMultipleProperties() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + item3.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + + Assert.assertTrue(item2.equals(item3)); + } + + public void testItemEqualsPropertyOrder() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID2, prop2); + item2.addItemProperty(ID1, prop1); + + Assert.assertFalse(item1.equals(item2)); + } + + public void testEqualsSingleListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testEqualsMultipleListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.addListener(propertySetListenerMock2); + + item2.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock2); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testEqualsAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testItemHashCodeEmpty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddProperties() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + // hashCodes can be equal even if items are different + + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addListener(propertySetListenerMock); + // hashCodes can be equal even if items are different + + item2.addListener(propertySetListenerMock); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddRemoveProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addItemProperty(ID1, prop1); + item1.removeItemProperty(ID1); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testToString() { + // toString() behavior is specified in the class javadoc + PropertysetItem item = createPropertySetItem(); + + Assert.assertEquals("", item.toString()); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(String.valueOf(prop1.getValue()), item.toString()); + + item.addItemProperty(ID2, prop2); + + Assert.assertEquals( + String.valueOf(prop1.getValue()) + " " + + String.valueOf(prop2.getValue()), item.toString()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java b/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java new file mode 100644 index 0000000000..ff6de50651 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java @@ -0,0 +1,42 @@ +package com.vaadin.data.util; + +import java.util.Collection; + +public class TestContainerHierarchicalWrapper extends + AbstractHierarchicalContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + public void testHierarchicalContainer() { + testHierarchicalContainer(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + public void testRemoveSubtree() { + testRemoveHierarchicalWrapperSubtree(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + protected void testRemoveHierarchicalWrapperSubtree( + ContainerHierarchicalWrapper container) { + initializeContainer(container); + + // remove root item + container.removeItemRecursively("org"); + + int packages = 21 + 3 - 3; + int expectedSize = sampleData.length + packages - 1; + + validateContainer(container, "com", "com.vaadin.util.SerializerHelper", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(1, rootIds.size()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestContainerSorting.java b/server/tests/src/com/vaadin/data/util/TestContainerSorting.java new file mode 100644 index 0000000000..497699605a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestContainerSorting.java @@ -0,0 +1,224 @@ +package com.vaadin.data.util; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.tests.util.TestUtil; + +public class TestContainerSorting extends TestCase { + + private static final String ITEM_DATA_MINUS2_NULL = "Data -2 null"; + private static final String ITEM_DATA_MINUS2 = "Data -2"; + private static final String ITEM_DATA_MINUS1 = "Data -1"; + private static final String ITEM_DATA_MINUS1_NULL = "Data -1 null"; + private static final String ITEM_ANOTHER_NULL = "Another null"; + private static final String ITEM_STRING_2 = "String 2"; + private static final String ITEM_STRING_NULL2 = "String null"; + private static final String ITEM_STRING_1 = "String 1"; + + private static final String PROPERTY_INTEGER_NULL2 = "integer-null"; + private static final String PROPERTY_INTEGER_NOT_NULL = "integer-not-null"; + private static final String PROPERTY_STRING_NULL = "string-null"; + private static final String PROPERTY_STRING_ID = "string-not-null"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testEmptyFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "aasdfasdfasdf", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + + } + + public void testFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "a", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, + new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS2_NULL, }); + } + + public void testIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_STRING_1, ITEM_STRING_2, ITEM_STRING_NULL2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, new boolean[] { + true, false, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_DATA_MINUS1, ITEM_DATA_MINUS1_NULL, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, new boolean[] { + true, true, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS1, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + } + + public void testHierarchicalContainer() { + HierarchicalContainer hc = new HierarchicalContainer(); + populateContainer(hc); + hc.sort(new Object[] { "name" }, new boolean[] { true }); + verifyOrder(hc, new String[] { "Audi", "C++", "Call of Duty", "Cars", + "English", "Fallout", "Finnish", "Ford", "Games", "Java", + "Might and Magic", "Natural languages", "PHP", + "Programming languages", "Python", "Red Alert", "Swedish", + "Toyota", "Volvo" }); + TestUtil.assertArrays( + hc.rootItemIds().toArray(), + new Integer[] { nameToId.get("Cars"), nameToId.get("Games"), + nameToId.get("Natural languages"), + nameToId.get("Programming languages") }); + TestUtil.assertArrays( + hc.getChildren(nameToId.get("Games")).toArray(), + new Integer[] { nameToId.get("Call of Duty"), + nameToId.get("Fallout"), + nameToId.get("Might and Magic"), + nameToId.get("Red Alert") }); + } + + private static void populateContainer(HierarchicalContainer container) { + container.addContainerProperty("name", String.class, null); + + addItem(container, "Games", null); + addItem(container, "Call of Duty", "Games"); + addItem(container, "Might and Magic", "Games"); + addItem(container, "Fallout", "Games"); + addItem(container, "Red Alert", "Games"); + + addItem(container, "Cars", null); + addItem(container, "Toyota", "Cars"); + addItem(container, "Volvo", "Cars"); + addItem(container, "Audi", "Cars"); + addItem(container, "Ford", "Cars"); + + addItem(container, "Natural languages", null); + addItem(container, "Swedish", "Natural languages"); + addItem(container, "English", "Natural languages"); + addItem(container, "Finnish", "Natural languages"); + + addItem(container, "Programming languages", null); + addItem(container, "C++", "Programming languages"); + addItem(container, "PHP", "Programming languages"); + addItem(container, "Java", "Programming languages"); + addItem(container, "Python", "Programming languages"); + + } + + private static int index = 0; + private static Map<String, Integer> nameToId = new HashMap<String, Integer>(); + private static Map<Integer, String> idToName = new HashMap<Integer, String>(); + + public static void addItem(IndexedContainer container, String string, + String parent) { + nameToId.put(string, index); + idToName.put(index, string); + + Item item = container.addItem(index); + item.getItemProperty("name").setValue(string); + + if (parent != null && container instanceof HierarchicalContainer) { + ((HierarchicalContainer) container).setParent(index, + nameToId.get(parent)); + } + + index++; + } + + private void verifyOrder(Container.Sortable ic, Object[] idOrder) { + int size = ic.size(); + Object[] actual = new Object[size]; + Iterator<?> i = ic.getItemIds().iterator(); + int index = 0; + while (i.hasNext()) { + Object o = i.next(); + if (o.getClass() == Integer.class + && idOrder[index].getClass() == String.class) { + o = idToName.get(o); + } + actual[index++] = o; + } + + TestUtil.assertArrays(actual, idOrder); + + } + + private void populate(IndexedContainer ic) { + addItem(ic, ITEM_STRING_1, ITEM_STRING_1, 1, 1); + addItem(ic, ITEM_STRING_NULL2, null, 0, null); + addItem(ic, ITEM_STRING_2, ITEM_STRING_2, 2, 2); + addItem(ic, ITEM_ANOTHER_NULL, null, 0, null); + addItem(ic, ITEM_DATA_MINUS1, ITEM_DATA_MINUS1, -1, -1); + addItem(ic, ITEM_DATA_MINUS1_NULL, null, -1, null); + addItem(ic, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2, -2, -2); + addItem(ic, ITEM_DATA_MINUS2_NULL, null, -2, null); + } + + private Item addItem(Container ic, String id, String string_null, + int integer, Integer integer_null) { + Item i = ic.addItem(id); + i.getItemProperty(PROPERTY_STRING_ID).setValue(id); + i.getItemProperty(PROPERTY_STRING_NULL).setValue(string_null); + i.getItemProperty(PROPERTY_INTEGER_NOT_NULL).setValue(integer); + i.getItemProperty(PROPERTY_INTEGER_NULL2).setValue(integer_null); + + return i; + } + + private void addProperties(IndexedContainer ic) { + ic.addContainerProperty("id", String.class, null); + ic.addContainerProperty(PROPERTY_STRING_ID, String.class, ""); + ic.addContainerProperty(PROPERTY_STRING_NULL, String.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NULL2, Integer.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NOT_NULL, Integer.class, 0); + ic.addContainerProperty("comparable-null", Integer.class, 0); + } + + public class MyObject implements Comparable<MyObject> { + private String data; + + @Override + public int compareTo(MyObject o) { + if (o == null) { + return 1; + } + + if (o.data == null) { + return data == null ? 0 : 1; + } else if (data == null) { + return -1; + } else { + return data.compareTo(o.data); + } + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java b/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java new file mode 100644 index 0000000000..10bc71c3a7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java @@ -0,0 +1,263 @@ +package com.vaadin.data.util; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; + +public class TestHierarchicalContainer extends + AbstractHierarchicalContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new HierarchicalContainer()); + } + + public void testFiltering() { + testContainerFiltering(new HierarchicalContainer()); + } + + public void testSorting() { + testContainerSorting(new HierarchicalContainer()); + } + + public void testOrdered() { + testContainerOrdered(new HierarchicalContainer()); + } + + public void testHierarchicalSorting() { + testHierarchicalSorting(new HierarchicalContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new HierarchicalContainer()); + } + + public void testRemovingItemsFromFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + + container.removeItem("com.vaadin.ui.TabSheet"); + // Parent for the removed item must be null because the item is no + // longer in the container + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull("Parent should be null, is " + p1, p1); + + container.removeAllItems(); + p1 = container.getParent("com.vaadin.client.Focusable"); + assertNull("Parent should be null, is " + p1, p1); + + } + + public void testParentWhenRemovingFilterFromContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + p1 = container.getParent("com.vaadin.client.ui.VPopupCalendar"); + assertNull(p1); + container.removeAllContainerFilters(); + p1 = container.getParent("com.vaadin.client.ui.VPopupCalendar"); + assertEquals("com.vaadin.client.ui", p1); + + } + + public void testChangeParentInFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Tab", false, false); + + // Change parent of filtered item + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + container.setParent("com.vaadin.ui.TabSheet", "com.vaadin"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin", p1); + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + container.setParent("com.vaadin.ui.TabSheet", null); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull(p1); + + // root -> non-root + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + + } + + public void testHierarchicalFilteringWithParents() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + + // Filter by "contains ab" + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + + // 20 items match the filters and the have 8 parents that should also be + // included + // only one root "com" should exist + // filtered + int expectedSize = 29; + int expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.ui.TabSheet", "com.vaadin.client.Focusable", + "blah", true, expectedSize, expectedRoots, true); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 6; + int classes = 112; + + expectedSize = packages + classes; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.client.WidgetSet", + "com.vaadin.client.ui.VSplitPanelVertical", "blah", true, + expectedSize, expectedRoots, true); + + // Additionally remove all without 'm' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "m", false, false); + + expectedSize = 7 + 18; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.client.ui.VUriFragmentUtility", + "com.vaadin.client.ui.layout.ChildComponentContainer", "blah", + true, expectedSize, expectedRoots, true); + + } + + public void testRemoveLastChild() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + c.removeItem("child"); + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + public void testRemoveLastChildFromFiltered() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + // Dummy filter that does not remove any items + c.addContainerFilter(new Filter() { + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return true; + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return true; + } + }); + c.removeItem("child"); + + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + public void testHierarchicalFilteringWithoutParents() { + HierarchicalContainer container = new HierarchicalContainer(); + + initializeContainer(container); + container.setIncludeParentsWhenFiltering(false); + + // Filter by "contains ab" + container.addContainerFilter(SIMPLE_NAME, "ab", false, false); + + // 20 items match the filter. + // com.vaadin.data.BufferedValidatable + // com.vaadin.data.Validatable + // com.vaadin.client.Focusable + // com.vaadin.client.Paintable + // com.vaadin.client.ui.Table + // com.vaadin.client.ui.VLabel + // com.vaadin.client.ui.VScrollTable + // com.vaadin.client.ui.VTablePaging + // com.vaadin.client.ui.VTabsheet + // com.vaadin.client.ui.VTabsheetBase + // com.vaadin.client.ui.VTabsheetPanel + // com.vaadin.server.ChangeVariablesErrorEvent + // com.vaadin.server.Paintable + // com.vaadin.server.Scrollable + // com.vaadin.server.Sizeable + // com.vaadin.server.VariableOwner + // com.vaadin.ui.Label + // com.vaadin.ui.Table + // com.vaadin.ui.TableFieldFactory + // com.vaadin.ui.TabSheet + // all become roots. + int expectedSize = 20; + int expectedRoots = 20; + + validateHierarchicalContainer(container, + "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TabSheet", "com.vaadin.client.ui.VTabsheetBase", + "blah", true, expectedSize, expectedRoots, false); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 3; + int classes = 110; + + expectedSize = packages + classes; + expectedRoots = 35 + 1; // com.vaadin.client.ui + + // com.vaadin.client.* + + // Sorting is case insensitive + validateHierarchicalContainer(container, + "com.vaadin.client.ApplicationConfiguration", + "com.vaadin.client.WidgetSet", + "com.vaadin.client.ui.VOptionGroup", "blah", true, + expectedSize, expectedRoots, false); + + // Additionally remove all without 'P' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "P", false, false); + + expectedSize = 13; + expectedRoots = expectedSize; + + validateHierarchicalContainer(container, "com.vaadin.client.Paintable", + "com.vaadin.client.ui.VTabsheetPanel", + "com.vaadin.client.ui.VPopupCalendar", "blah", true, + expectedSize, expectedRoots, false); + + } +} diff --git a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java new file mode 100644 index 0000000000..156ff83883 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java @@ -0,0 +1,271 @@ +package com.vaadin.data.util; + +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; + +public class TestIndexedContainer extends AbstractInMemoryContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new IndexedContainer()); + } + + public void testFiltering() { + testContainerFiltering(new IndexedContainer()); + } + + public void testSorting() { + testContainerSorting(new IndexedContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new IndexedContainer()); + } + + public void testContainerOrdered() { + testContainerOrdered(new IndexedContainer()); + } + + public void testContainerIndexed() { + testContainerIndexed(new IndexedContainer(), sampleData[2], 2, true, + "newItemId", true); + } + + public void testItemSetChangeListeners() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + String id1 = "id1"; + String id2 = "id2"; + String id3 = "id3"; + + initializeContainer(container); + counter.reset(); + container.addItem(); + counter.assertOnce(); + container.addItem(id1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0); + counter.assertOnce(); + container.addItemAt(0, id1); + counter.assertOnce(); + container.addItemAt(0, id2); + counter.assertOnce(); + container.addItemAt(container.size(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAt(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null); + counter.assertOnce(); + container.addItemAfter(null, id1); + counter.assertOnce(); + container.addItemAfter(id1); + counter.assertOnce(); + container.addItemAfter(id1, id2); + counter.assertOnce(); + container.addItemAfter(container.firstItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAfter(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeItem(sampleData[0]); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + public void testAddRemoveContainerFilter() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + // simply adding or removing container filters should cause events + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + } + + // TODO other tests should check positions after removing filter etc, + // here concentrating on listeners + public void testItemSetChangeListenersFiltering() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + // no real change, so no notification required + counter.assertNone(); + + String id1 = "com.example.Test1"; + String id2 = "com.example.Test2"; + String id3 = "com.example.Other"; + + // perform operations while filtering container + + Item item; + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItem(id1); + // no event if filtered out + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter after change + item = container.addItemAt(0, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAt(0, id1); + counter.assertNone(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItemAfter(null, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAfter(null, id1); + counter.assertNone(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + + // does not pass filter + + // TODO implement rest + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(null, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.firstItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.lastItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(0, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(1, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(container.size(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + item = container.addItem(id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + container.removeItem(id1); + counter.assertOnce(); + // already removed + container.removeItem(id1); + counter.assertNone(); + + item = container.addItem(id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + // not visible + container.removeItem(id3); + counter.assertNone(); + + // remove all + + initializeContainer(container); + item = container.addItem(id1); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java new file mode 100644 index 0000000000..6f96c3a51a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java @@ -0,0 +1,97 @@ +package com.vaadin.data.util.filter; + +import junit.framework.TestCase; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; + +public abstract class AbstractFilterTest<FILTERTYPE extends Filter> extends + TestCase { + + protected static final String PROPERTY1 = "property1"; + protected static final String PROPERTY2 = "property2"; + + protected static class TestItem<T1, T2> extends PropertysetItem { + + public TestItem(T1 value1, T2 value2) { + addItemProperty(PROPERTY1, new ObjectProperty<T1>(value1)); + addItemProperty(PROPERTY2, new ObjectProperty<T2>(value2)); + } + } + + protected static class NullProperty implements Property<String> { + + @Override + public String getValue() { + return null; + } + + @Override + public void setValue(Object newValue) throws ReadOnlyException { + throw new ReadOnlyException(); + } + + @Override + public Class<String> getType() { + return String.class; + } + + @Override + public boolean isReadOnly() { + return true; + } + + @Override + public void setReadOnly(boolean newStatus) { + // do nothing + } + + } + + public static class SameItemFilter implements Filter { + + private final Item item; + private final Object propertyId; + + public SameItemFilter(Item item) { + this(item, ""); + } + + public SameItemFilter(Item item, Object propertyId) { + this.item = item; + this.propertyId = propertyId; + } + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return this.item == item; + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return this.propertyId != null ? this.propertyId.equals(propertyId) + : true; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + SameItemFilter other = (SameItemFilter) obj; + return item == other.item + && (propertyId == null ? other.propertyId == null + : propertyId.equals(other.propertyId)); + } + + @Override + public int hashCode() { + return item.hashCode(); + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java new file mode 100644 index 0000000000..fdd5b8a645 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java @@ -0,0 +1,232 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; + +public class AndOrFilterTest extends AbstractFilterTest<AbstractJunctionFilter> { + + protected Item item1 = new BeanItem<Integer>(1); + protected Item item2 = new BeanItem<Integer>(2); + + public void testNoFilterAnd() { + Filter filter = new And(); + + Assert.assertTrue(filter.passesFilter(null, item1)); + } + + public void testSingleFilterAnd() { + Filter filter = new And(new SameItemFilter(item1)); + + Assert.assertTrue(filter.passesFilter(null, item1)); + Assert.assertFalse(filter.passesFilter(null, item2)); + } + + public void testTwoFilterAnd() { + Filter filter1 = new And(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2 = new And(new SameItemFilter(item1), new SameItemFilter( + item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertFalse(filter2.passesFilter(null, item2)); + } + + public void testThreeFilterAnd() { + Filter filter1 = new And(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item1)); + Filter filter2 = new And(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertFalse(filter2.passesFilter(null, item2)); + } + + public void testNoFilterOr() { + Filter filter = new Or(); + + Assert.assertFalse(filter.passesFilter(null, item1)); + } + + public void testSingleFilterOr() { + Filter filter = new Or(new SameItemFilter(item1)); + + Assert.assertTrue(filter.passesFilter(null, item1)); + Assert.assertFalse(filter.passesFilter(null, item2)); + } + + public void testTwoFilterOr() { + Filter filter1 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2 = new Or(new SameItemFilter(item1), new SameItemFilter( + item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertTrue(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testThreeFilterOr() { + Filter filter1 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item1)); + Filter filter2 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertTrue(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testAndEqualsHashCode() { + Filter filter0 = new And(); + Filter filter0b = new And(); + Filter filter1a = new And(new SameItemFilter(item1)); + Filter filter1a2 = new And(new SameItemFilter(item1)); + Filter filter1b = new And(new SameItemFilter(item2)); + Filter filter2a = new And(new SameItemFilter(item1), + new SameItemFilter(item1)); + Filter filter2b = new And(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter filter2b2 = new And(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter other0 = new Or(); + Filter other1 = new Or(new SameItemFilter(item1)); + + Assert.assertEquals(filter0, filter0); + Assert.assertEquals(filter0, filter0b); + Assert.assertFalse(filter0.equals(filter1a)); + Assert.assertFalse(filter0.equals(other0)); + Assert.assertFalse(filter0.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter1b)); + Assert.assertFalse(filter1a.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter2a)); + Assert.assertFalse(filter2a.equals(filter1a)); + + Assert.assertFalse(filter2a.equals(filter2b)); + Assert.assertEquals(filter2b, filter2b2); + + // hashCode() + Assert.assertEquals(filter0.hashCode(), filter0.hashCode()); + Assert.assertEquals(filter0.hashCode(), filter0b.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a2.hashCode()); + Assert.assertEquals(filter2a.hashCode(), filter2a.hashCode()); + Assert.assertEquals(filter2b.hashCode(), filter2b2.hashCode()); + } + + public void testOrEqualsHashCode() { + Filter filter0 = new Or(); + Filter filter0b = new Or(); + Filter filter1a = new Or(new SameItemFilter(item1)); + Filter filter1a2 = new Or(new SameItemFilter(item1)); + Filter filter1b = new Or(new SameItemFilter(item2)); + Filter filter2a = new Or(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2b = new Or(new SameItemFilter(item1), new SameItemFilter( + item2)); + Filter filter2b2 = new Or(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter other0 = new And(); + Filter other1 = new And(new SameItemFilter(item1)); + + Assert.assertEquals(filter0, filter0); + Assert.assertEquals(filter0, filter0b); + Assert.assertFalse(filter0.equals(filter1a)); + Assert.assertFalse(filter0.equals(other0)); + Assert.assertFalse(filter0.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter1b)); + Assert.assertFalse(filter1a.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter2a)); + Assert.assertFalse(filter2a.equals(filter1a)); + + Assert.assertFalse(filter2a.equals(filter2b)); + Assert.assertEquals(filter2b, filter2b2); + + // hashCode() + Assert.assertEquals(filter0.hashCode(), filter0.hashCode()); + Assert.assertEquals(filter0.hashCode(), filter0b.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a2.hashCode()); + Assert.assertEquals(filter2a.hashCode(), filter2a.hashCode()); + Assert.assertEquals(filter2b.hashCode(), filter2b2.hashCode()); + } + + public void testAndAppliesToProperty() { + Filter filter0 = new And(); + Filter filter1a = new And(new SameItemFilter(item1, "a")); + Filter filter1b = new And(new SameItemFilter(item1, "b")); + Filter filter2aa = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "a")); + Filter filter2ab = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b")); + Filter filter3abc = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b"), new SameItemFilter(item1, "c")); + + // empty And does not filter out anything + Assert.assertFalse(filter0.appliesToProperty("a")); + Assert.assertFalse(filter0.appliesToProperty("d")); + + Assert.assertTrue(filter1a.appliesToProperty("a")); + Assert.assertFalse(filter1a.appliesToProperty("b")); + Assert.assertFalse(filter1b.appliesToProperty("a")); + Assert.assertTrue(filter1b.appliesToProperty("b")); + + Assert.assertTrue(filter2aa.appliesToProperty("a")); + Assert.assertFalse(filter2aa.appliesToProperty("b")); + Assert.assertTrue(filter2ab.appliesToProperty("a")); + Assert.assertTrue(filter2ab.appliesToProperty("b")); + + Assert.assertTrue(filter3abc.appliesToProperty("a")); + Assert.assertTrue(filter3abc.appliesToProperty("b")); + Assert.assertTrue(filter3abc.appliesToProperty("c")); + Assert.assertFalse(filter3abc.appliesToProperty("d")); + } + + public void testOrAppliesToProperty() { + Filter filter0 = new Or(); + Filter filter1a = new Or(new SameItemFilter(item1, "a")); + Filter filter1b = new Or(new SameItemFilter(item1, "b")); + Filter filter2aa = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "a")); + Filter filter2ab = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b")); + Filter filter3abc = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b"), new SameItemFilter(item1, "c")); + + // empty Or filters out everything + Assert.assertTrue(filter0.appliesToProperty("a")); + Assert.assertTrue(filter0.appliesToProperty("d")); + + Assert.assertTrue(filter1a.appliesToProperty("a")); + Assert.assertFalse(filter1a.appliesToProperty("b")); + Assert.assertFalse(filter1b.appliesToProperty("a")); + Assert.assertTrue(filter1b.appliesToProperty("b")); + + Assert.assertTrue(filter2aa.appliesToProperty("a")); + Assert.assertFalse(filter2aa.appliesToProperty("b")); + Assert.assertTrue(filter2ab.appliesToProperty("a")); + Assert.assertTrue(filter2ab.appliesToProperty("b")); + + Assert.assertTrue(filter3abc.appliesToProperty("a")); + Assert.assertTrue(filter3abc.appliesToProperty("b")); + Assert.assertTrue(filter3abc.appliesToProperty("c")); + Assert.assertFalse(filter3abc.appliesToProperty("d")); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java new file mode 100644 index 0000000000..99e8429a51 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java @@ -0,0 +1,260 @@ +package com.vaadin.data.util.filter; + +import java.util.Date; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Compare.Greater; +import com.vaadin.data.util.filter.Compare.GreaterOrEqual; +import com.vaadin.data.util.filter.Compare.Less; +import com.vaadin.data.util.filter.Compare.LessOrEqual; + +public class CompareFilterTest extends AbstractFilterTest<Compare> { + + protected Item itemNull; + protected Item itemEmpty; + protected Item itemA; + protected Item itemB; + protected Item itemC; + + protected final Filter equalB = new Equal(PROPERTY1, "b"); + protected final Filter greaterB = new Greater(PROPERTY1, "b"); + protected final Filter lessB = new Less(PROPERTY1, "b"); + protected final Filter greaterEqualB = new GreaterOrEqual(PROPERTY1, "b"); + protected final Filter lessEqualB = new LessOrEqual(PROPERTY1, "b"); + + protected final Filter equalNull = new Equal(PROPERTY1, null); + protected final Filter greaterNull = new Greater(PROPERTY1, null); + protected final Filter lessNull = new Less(PROPERTY1, null); + protected final Filter greaterEqualNull = new GreaterOrEqual(PROPERTY1, + null); + protected final Filter lessEqualNull = new LessOrEqual(PROPERTY1, null); + + @Override + protected void setUp() throws Exception { + super.setUp(); + itemNull = new PropertysetItem(); + itemNull.addItemProperty(PROPERTY1, new ObjectProperty<String>(null, + String.class)); + itemEmpty = new PropertysetItem(); + itemEmpty.addItemProperty(PROPERTY1, new ObjectProperty<String>("", + String.class)); + itemA = new PropertysetItem(); + itemA.addItemProperty(PROPERTY1, new ObjectProperty<String>("a", + String.class)); + itemB = new PropertysetItem(); + itemB.addItemProperty(PROPERTY1, new ObjectProperty<String>("b", + String.class)); + itemC = new PropertysetItem(); + itemC.addItemProperty(PROPERTY1, new ObjectProperty<String>("c", + String.class)); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + itemNull = null; + itemEmpty = null; + itemA = null; + itemB = null; + } + + public void testCompareString() { + Assert.assertFalse(equalB.passesFilter(null, itemEmpty)); + Assert.assertFalse(equalB.passesFilter(null, itemA)); + Assert.assertTrue(equalB.passesFilter(null, itemB)); + Assert.assertFalse(equalB.passesFilter(null, itemC)); + + Assert.assertFalse(greaterB.passesFilter(null, itemEmpty)); + Assert.assertFalse(greaterB.passesFilter(null, itemA)); + Assert.assertFalse(greaterB.passesFilter(null, itemB)); + Assert.assertTrue(greaterB.passesFilter(null, itemC)); + + Assert.assertTrue(lessB.passesFilter(null, itemEmpty)); + Assert.assertTrue(lessB.passesFilter(null, itemA)); + Assert.assertFalse(lessB.passesFilter(null, itemB)); + Assert.assertFalse(lessB.passesFilter(null, itemC)); + + Assert.assertFalse(greaterEqualB.passesFilter(null, itemEmpty)); + Assert.assertFalse(greaterEqualB.passesFilter(null, itemA)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemB)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemC)); + + Assert.assertTrue(lessEqualB.passesFilter(null, itemEmpty)); + Assert.assertTrue(lessEqualB.passesFilter(null, itemA)); + Assert.assertTrue(lessEqualB.passesFilter(null, itemB)); + Assert.assertFalse(lessEqualB.passesFilter(null, itemC)); + } + + public void testCompareWithNull() { + // null comparisons: null is less than any other value + Assert.assertFalse(equalB.passesFilter(null, itemNull)); + Assert.assertTrue(greaterB.passesFilter(null, itemNull)); + Assert.assertFalse(lessB.passesFilter(null, itemNull)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemNull)); + Assert.assertFalse(lessEqualB.passesFilter(null, itemNull)); + + Assert.assertTrue(equalNull.passesFilter(null, itemNull)); + Assert.assertFalse(greaterNull.passesFilter(null, itemNull)); + Assert.assertFalse(lessNull.passesFilter(null, itemNull)); + Assert.assertTrue(greaterEqualNull.passesFilter(null, itemNull)); + Assert.assertTrue(lessEqualNull.passesFilter(null, itemNull)); + + Assert.assertFalse(equalNull.passesFilter(null, itemA)); + Assert.assertFalse(greaterNull.passesFilter(null, itemA)); + Assert.assertTrue(lessNull.passesFilter(null, itemA)); + Assert.assertFalse(greaterEqualNull.passesFilter(null, itemA)); + Assert.assertTrue(lessEqualNull.passesFilter(null, itemA)); + } + + public void testCompareInteger() { + int negative = -1; + int zero = 0; + int positive = 1; + + Item itemNegative = new PropertysetItem(); + itemNegative.addItemProperty(PROPERTY1, new ObjectProperty<Integer>( + negative, Integer.class)); + Item itemZero = new PropertysetItem(); + itemZero.addItemProperty(PROPERTY1, new ObjectProperty<Integer>(zero, + Integer.class)); + Item itemPositive = new PropertysetItem(); + itemPositive.addItemProperty(PROPERTY1, new ObjectProperty<Integer>( + positive, Integer.class)); + + Filter equalZero = new Equal(PROPERTY1, zero); + Assert.assertFalse(equalZero.passesFilter(null, itemNegative)); + Assert.assertTrue(equalZero.passesFilter(null, itemZero)); + Assert.assertFalse(equalZero.passesFilter(null, itemPositive)); + + Filter isPositive = new Greater(PROPERTY1, zero); + Assert.assertFalse(isPositive.passesFilter(null, itemNegative)); + Assert.assertFalse(isPositive.passesFilter(null, itemZero)); + Assert.assertTrue(isPositive.passesFilter(null, itemPositive)); + + Filter isNegative = new Less(PROPERTY1, zero); + Assert.assertTrue(isNegative.passesFilter(null, itemNegative)); + Assert.assertFalse(isNegative.passesFilter(null, itemZero)); + Assert.assertFalse(isNegative.passesFilter(null, itemPositive)); + + Filter isNonNegative = new GreaterOrEqual(PROPERTY1, zero); + Assert.assertFalse(isNonNegative.passesFilter(null, itemNegative)); + Assert.assertTrue(isNonNegative.passesFilter(null, itemZero)); + Assert.assertTrue(isNonNegative.passesFilter(null, itemPositive)); + + Filter isNonPositive = new LessOrEqual(PROPERTY1, zero); + Assert.assertTrue(isNonPositive.passesFilter(null, itemNegative)); + Assert.assertTrue(isNonPositive.passesFilter(null, itemZero)); + Assert.assertFalse(isNonPositive.passesFilter(null, itemPositive)); + } + + public void testCompareDate() { + Date now = new Date(); + // new Date() is only accurate to the millisecond, so repeating it gives + // the same date + Date earlier = new Date(now.getTime() - 1); + Date later = new Date(now.getTime() + 1); + + Item itemEarlier = new PropertysetItem(); + itemEarlier.addItemProperty(PROPERTY1, new ObjectProperty<Date>( + earlier, Date.class)); + Item itemNow = new PropertysetItem(); + itemNow.addItemProperty(PROPERTY1, new ObjectProperty<Date>(now, + Date.class)); + Item itemLater = new PropertysetItem(); + itemLater.addItemProperty(PROPERTY1, new ObjectProperty<Date>(later, + Date.class)); + + Filter equalNow = new Equal(PROPERTY1, now); + Assert.assertFalse(equalNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(equalNow.passesFilter(null, itemNow)); + Assert.assertFalse(equalNow.passesFilter(null, itemLater)); + + Filter after = new Greater(PROPERTY1, now); + Assert.assertFalse(after.passesFilter(null, itemEarlier)); + Assert.assertFalse(after.passesFilter(null, itemNow)); + Assert.assertTrue(after.passesFilter(null, itemLater)); + + Filter before = new Less(PROPERTY1, now); + Assert.assertTrue(before.passesFilter(null, itemEarlier)); + Assert.assertFalse(before.passesFilter(null, itemNow)); + Assert.assertFalse(before.passesFilter(null, itemLater)); + + Filter afterOrNow = new GreaterOrEqual(PROPERTY1, now); + Assert.assertFalse(afterOrNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(afterOrNow.passesFilter(null, itemNow)); + Assert.assertTrue(afterOrNow.passesFilter(null, itemLater)); + + Filter beforeOrNow = new LessOrEqual(PROPERTY1, now); + Assert.assertTrue(beforeOrNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(beforeOrNow.passesFilter(null, itemNow)); + Assert.assertFalse(beforeOrNow.passesFilter(null, itemLater)); + } + + public void testCompareAppliesToProperty() { + Filter filterA = new Equal("a", 1); + Filter filterB = new Equal("b", 1); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testCompareEqualsHashCode() { + // most checks with Equal filter, then only some with others + Filter equalNull2 = new Equal(PROPERTY1, null); + Filter equalNullProperty2 = new Equal(PROPERTY2, null); + Filter equalEmpty = new Equal(PROPERTY1, ""); + Filter equalEmpty2 = new Equal(PROPERTY1, ""); + Filter equalEmptyProperty2 = new Equal(PROPERTY2, ""); + Filter equalA = new Equal(PROPERTY1, "a"); + Filter equalB2 = new Equal(PROPERTY1, "b"); + Filter equalBProperty2 = new Equal(PROPERTY2, "b"); + + Filter greaterEmpty = new Greater(PROPERTY1, ""); + + // equals() + Assert.assertEquals(equalNull, equalNull); + Assert.assertEquals(equalNull, equalNull2); + Assert.assertFalse(equalNull.equals(equalNullProperty2)); + Assert.assertFalse(equalNull.equals(equalEmpty)); + Assert.assertFalse(equalNull.equals(equalB)); + + Assert.assertEquals(equalEmpty, equalEmpty); + Assert.assertFalse(equalEmpty.equals(equalNull)); + Assert.assertEquals(equalEmpty, equalEmpty2); + Assert.assertFalse(equalEmpty.equals(equalEmptyProperty2)); + Assert.assertFalse(equalEmpty.equals(equalB)); + + Assert.assertEquals(equalB, equalB); + Assert.assertFalse(equalB.equals(equalNull)); + Assert.assertFalse(equalB.equals(equalEmpty)); + Assert.assertEquals(equalB, equalB2); + Assert.assertFalse(equalB.equals(equalBProperty2)); + Assert.assertFalse(equalB.equals(equalA)); + + Assert.assertEquals(greaterB, greaterB); + Assert.assertFalse(greaterB.equals(lessB)); + Assert.assertFalse(greaterB.equals(greaterEqualB)); + Assert.assertFalse(greaterB.equals(lessEqualB)); + + Assert.assertFalse(greaterNull.equals(greaterEmpty)); + Assert.assertFalse(greaterNull.equals(greaterB)); + Assert.assertFalse(greaterEmpty.equals(greaterNull)); + Assert.assertFalse(greaterEmpty.equals(greaterB)); + Assert.assertFalse(greaterB.equals(greaterNull)); + Assert.assertFalse(greaterB.equals(greaterEmpty)); + + // hashCode() + Assert.assertEquals(equalNull.hashCode(), equalNull2.hashCode()); + Assert.assertEquals(equalEmpty.hashCode(), equalEmpty2.hashCode()); + Assert.assertEquals(equalB.hashCode(), equalB2.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java new file mode 100644 index 0000000000..6f90273de1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java @@ -0,0 +1,57 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; + +public class IsNullFilterTest extends AbstractFilterTest<IsNull> { + + public void testIsNull() { + Item item1 = new PropertysetItem(); + item1.addItemProperty("a", new ObjectProperty<String>(null, + String.class)); + item1.addItemProperty("b", + new ObjectProperty<String>("b", String.class)); + Item item2 = new PropertysetItem(); + item2.addItemProperty("a", + new ObjectProperty<String>("a", String.class)); + item2.addItemProperty("b", new ObjectProperty<String>(null, + String.class)); + + Filter filter1 = new IsNull("a"); + Filter filter2 = new IsNull("b"); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testIsNullAppliesToProperty() { + Filter filterA = new IsNull("a"); + Filter filterB = new IsNull("b"); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testIsNullEqualsHashCode() { + Filter filter1 = new IsNull("a"); + Filter filter1b = new IsNull("a"); + Filter filter2 = new IsNull("b"); + + // equals() + Assert.assertEquals(filter1, filter1b); + Assert.assertFalse(filter1.equals(filter2)); + Assert.assertFalse(filter1.equals(new And())); + + // hashCode() + Assert.assertEquals(filter1.hashCode(), filter1b.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java new file mode 100644 index 0000000000..c3b666e6f7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java @@ -0,0 +1,50 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; + +public class NotFilterTest extends AbstractFilterTest<Not> { + + protected Item item1 = new BeanItem<Integer>(1); + protected Item item2 = new BeanItem<Integer>(2); + + public void testNot() { + Filter origFilter = new SameItemFilter(item1); + Filter filter = new Not(origFilter); + + Assert.assertTrue(origFilter.passesFilter(null, item1)); + Assert.assertFalse(origFilter.passesFilter(null, item2)); + Assert.assertFalse(filter.passesFilter(null, item1)); + Assert.assertTrue(filter.passesFilter(null, item2)); + } + + public void testANotAppliesToProperty() { + Filter filterA = new Not(new SameItemFilter(item1, "a")); + Filter filterB = new Not(new SameItemFilter(item1, "b")); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testNotEqualsHashCode() { + Filter origFilter = new SameItemFilter(item1); + Filter filter1 = new Not(origFilter); + Filter filter1b = new Not(new SameItemFilter(item1)); + Filter filter2 = new Not(new SameItemFilter(item2)); + + // equals() + Assert.assertEquals(filter1, filter1b); + Assert.assertFalse(filter1.equals(filter2)); + Assert.assertFalse(filter1.equals(origFilter)); + Assert.assertFalse(filter1.equals(new And())); + + // hashCode() + Assert.assertEquals(filter1.hashCode(), filter1b.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java new file mode 100644 index 0000000000..bc63d57752 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java @@ -0,0 +1,130 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +public class SimpleStringFilterTest extends + AbstractFilterTest<SimpleStringFilter> { + + protected static TestItem<String, String> createTestItem() { + return new TestItem<String, String>("abcde", "TeSt"); + } + + protected TestItem<String, String> getTestItem() { + return createTestItem(); + } + + protected SimpleStringFilter f(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix) { + return new SimpleStringFilter(propertyId, filterString, ignoreCase, + onlyMatchPrefix); + } + + protected boolean passes(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix) { + return f(propertyId, filterString, ignoreCase, onlyMatchPrefix) + .passesFilter(null, getTestItem()); + } + + public void testStartsWithCaseSensitive() { + Assert.assertTrue(passes(PROPERTY1, "ab", false, true)); + Assert.assertTrue(passes(PROPERTY1, "", false, true)); + + Assert.assertFalse(passes(PROPERTY2, "ab", false, true)); + Assert.assertFalse(passes(PROPERTY1, "AB", false, true)); + } + + public void testStartsWithCaseInsensitive() { + Assert.assertTrue(passes(PROPERTY1, "AB", true, true)); + Assert.assertTrue(passes(PROPERTY2, "te", true, true)); + Assert.assertFalse(passes(PROPERTY2, "AB", true, true)); + } + + public void testContainsCaseSensitive() { + Assert.assertTrue(passes(PROPERTY1, "ab", false, false)); + Assert.assertTrue(passes(PROPERTY1, "abcde", false, false)); + Assert.assertTrue(passes(PROPERTY1, "cd", false, false)); + Assert.assertTrue(passes(PROPERTY1, "e", false, false)); + Assert.assertTrue(passes(PROPERTY1, "", false, false)); + + Assert.assertFalse(passes(PROPERTY2, "ab", false, false)); + Assert.assertFalse(passes(PROPERTY1, "es", false, false)); + } + + public void testContainsCaseInsensitive() { + Assert.assertTrue(passes(PROPERTY1, "AB", true, false)); + Assert.assertTrue(passes(PROPERTY1, "aBcDe", true, false)); + Assert.assertTrue(passes(PROPERTY1, "CD", true, false)); + Assert.assertTrue(passes(PROPERTY1, "", true, false)); + + Assert.assertTrue(passes(PROPERTY2, "es", true, false)); + + Assert.assertFalse(passes(PROPERTY2, "ab", true, false)); + } + + public void testAppliesToProperty() { + SimpleStringFilter filter = f(PROPERTY1, "ab", false, true); + Assert.assertTrue(filter.appliesToProperty(PROPERTY1)); + Assert.assertFalse(filter.appliesToProperty(PROPERTY2)); + Assert.assertFalse(filter.appliesToProperty("other")); + } + + public void testEqualsHashCode() { + SimpleStringFilter filter = f(PROPERTY1, "ab", false, true); + + SimpleStringFilter f1 = f(PROPERTY2, "ab", false, true); + SimpleStringFilter f1b = f(PROPERTY2, "ab", false, true); + SimpleStringFilter f2 = f(PROPERTY1, "cd", false, true); + SimpleStringFilter f2b = f(PROPERTY1, "cd", false, true); + SimpleStringFilter f3 = f(PROPERTY1, "ab", true, true); + SimpleStringFilter f3b = f(PROPERTY1, "ab", true, true); + SimpleStringFilter f4 = f(PROPERTY1, "ab", false, false); + SimpleStringFilter f4b = f(PROPERTY1, "ab", false, false); + + // equal but not same instance + Assert.assertEquals(f1, f1b); + Assert.assertEquals(f2, f2b); + Assert.assertEquals(f3, f3b); + Assert.assertEquals(f4, f4b); + + // more than one property differ + Assert.assertFalse(f1.equals(f2)); + Assert.assertFalse(f1.equals(f3)); + Assert.assertFalse(f1.equals(f4)); + Assert.assertFalse(f2.equals(f1)); + Assert.assertFalse(f2.equals(f3)); + Assert.assertFalse(f2.equals(f4)); + Assert.assertFalse(f3.equals(f1)); + Assert.assertFalse(f3.equals(f2)); + Assert.assertFalse(f3.equals(f4)); + Assert.assertFalse(f4.equals(f1)); + Assert.assertFalse(f4.equals(f2)); + Assert.assertFalse(f4.equals(f3)); + + // only one property differs + Assert.assertFalse(filter.equals(f1)); + Assert.assertFalse(filter.equals(f2)); + Assert.assertFalse(filter.equals(f3)); + Assert.assertFalse(filter.equals(f4)); + + Assert.assertFalse(f1.equals(null)); + Assert.assertFalse(f1.equals(new Object())); + + Assert.assertEquals(f1.hashCode(), f1b.hashCode()); + Assert.assertEquals(f2.hashCode(), f2b.hashCode()); + Assert.assertEquals(f3.hashCode(), f3b.hashCode()); + Assert.assertEquals(f4.hashCode(), f4b.hashCode()); + } + + public void testNonExistentProperty() { + Assert.assertFalse(passes("other1", "ab", false, true)); + } + + public void testNullValueForProperty() { + TestItem<String, String> item = createTestItem(); + item.addItemProperty("other1", new NullProperty()); + + Assert.assertFalse(f("other1", "ab", false, true).passesFilter(null, + item)); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java new file mode 100644 index 0000000000..057527307f --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java @@ -0,0 +1,145 @@ +package com.vaadin.data.util.sqlcontainer; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import com.vaadin.data.util.sqlcontainer.connection.J2EEConnectionPoolTest; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPoolTest; +import com.vaadin.data.util.sqlcontainer.filters.BetweenTest; +import com.vaadin.data.util.sqlcontainer.filters.LikeTest; +import com.vaadin.data.util.sqlcontainer.generator.SQLGeneratorsTest; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryTest; +import com.vaadin.data.util.sqlcontainer.query.QueryBuilderTest; +import com.vaadin.data.util.sqlcontainer.query.TableQueryTest; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; + +@RunWith(Suite.class) +@SuiteClasses({ SimpleJDBCConnectionPoolTest.class, + J2EEConnectionPoolTest.class, LikeTest.class, QueryBuilderTest.class, + FreeformQueryTest.class, RowIdTest.class, SQLContainerTest.class, + SQLContainerTableQueryTest.class, ColumnPropertyTest.class, + TableQueryTest.class, SQLGeneratorsTest.class, UtilTest.class, + TicketTests.class, BetweenTest.class, ReadOnlyRowIdTest.class }) +public class AllTests { + /* Set the DB used for testing here! */ + public enum DB { + HSQLDB, MYSQL, POSTGRESQL, MSSQL, ORACLE; + } + + /* 0 = HSQLDB, 1 = MYSQL, 2 = POSTGRESQL, 3 = MSSQL, 4 = ORACLE */ + public static final DB db = DB.HSQLDB; + + /* Auto-increment column offset (HSQLDB = 0, MYSQL = 1, POSTGRES = 1) */ + public static int offset; + /* Garbage table creation query (=three queries for oracle) */ + public static String createGarbage; + public static String createGarbageSecond; + public static String createGarbageThird; + /* DB Drivers, urls, usernames and passwords */ + public static String dbDriver; + public static String dbURL; + public static String dbUser; + public static String dbPwd; + /* People -test table creation statement(s) */ + public static String peopleFirst; + public static String peopleSecond; + public static String peopleThird; + /* Versioned -test table createion statement(s) */ + public static String[] versionStatements; + /* SQL Generator used during the testing */ + public static SQLGenerator sqlGen; + + /* Set DB-specific settings based on selected DB */ + static { + sqlGen = new DefaultSQLGenerator(); + switch (db) { + case HSQLDB: + offset = 0; + createGarbage = "create table garbage (id integer generated always as identity, type varchar(32), PRIMARY KEY(id))"; + dbDriver = "org.hsqldb.jdbc.JDBCDriver"; + dbURL = "jdbc:hsqldb:mem:sqlcontainer"; + dbUser = "SA"; + dbPwd = ""; + peopleFirst = "create table people (id integer generated always as identity, name varchar(32), AGE INTEGER)"; + peopleSecond = "alter table people add primary key (id)"; + versionStatements = new String[] { + "create table versioned (id integer generated always as identity, text varchar(255), version tinyint default 0)", + "alter table versioned add primary key (id)" }; + break; + case MYSQL: + offset = 1; + createGarbage = "create table GARBAGE (ID integer auto_increment, type varchar(32), PRIMARY KEY(ID))"; + dbDriver = "com.mysql.jdbc.Driver"; + dbURL = "jdbc:mysql:///sqlcontainer"; + dbUser = "sqlcontainer"; + dbPwd = "sqlcontainer"; + peopleFirst = "create table PEOPLE (ID integer auto_increment not null, NAME varchar(32), AGE INTEGER, primary key(ID))"; + peopleSecond = null; + versionStatements = new String[] { + "create table VERSIONED (ID integer auto_increment not null, TEXT varchar(255), VERSION tinyint default 0, primary key(ID))", + "CREATE TRIGGER upd_version BEFORE UPDATE ON VERSIONED" + + " FOR EACH ROW SET NEW.VERSION = OLD.VERSION+1" }; + break; + case POSTGRESQL: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" serial PRIMARY KEY, \"TYPE\" varchar(32))"; + dbDriver = "org.postgresql.Driver"; + dbURL = "jdbc:postgresql://localhost:5432/test"; + dbUser = "postgres"; + dbPwd = "postgres"; + peopleFirst = "create table PEOPLE (\"ID\" serial primary key, \"NAME\" VARCHAR(32), \"AGE\" INTEGER)"; + peopleSecond = null; + versionStatements = new String[] { + "create table VERSIONED (\"ID\" serial primary key, \"TEXT\" VARCHAR(255), \"VERSION\" INTEGER DEFAULT 0)", + "CREATE OR REPLACE FUNCTION zz_row_version() RETURNS TRIGGER AS $$" + + "BEGIN" + + " IF TG_OP = 'UPDATE'" + + " AND NEW.\"VERSION\" = old.\"VERSION\"" + + " AND ROW(NEW.*) IS DISTINCT FROM ROW (old.*)" + + " THEN" + + " NEW.\"VERSION\" := NEW.\"VERSION\" + 1;" + + " END IF;" + " RETURN NEW;" + "END;" + + "$$ LANGUAGE plpgsql;", + "CREATE TRIGGER \"mytable_modify_dt_tr\" BEFORE UPDATE" + + " ON VERSIONED FOR EACH ROW" + + " EXECUTE PROCEDURE \"public\".\"zz_row_version\"();" }; + break; + case MSSQL: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" int identity(1,1) primary key, \"TYPE\" varchar(32))"; + dbDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + dbURL = "jdbc:sqlserver://localhost:1433;databaseName=tempdb;"; + dbUser = "sa"; + dbPwd = "sa"; + peopleFirst = "create table PEOPLE (\"ID\" int identity(1,1) primary key, \"NAME\" VARCHAR(32), \"AGE\" INTEGER)"; + peopleSecond = null; + versionStatements = new String[] { "create table VERSIONED (\"ID\" int identity(1,1) primary key, \"TEXT\" VARCHAR(255), \"VERSION\" rowversion not null)" }; + sqlGen = new MSSQLGenerator(); + break; + case ORACLE: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" integer primary key, \"TYPE\" varchar2(32))"; + createGarbageSecond = "create sequence garbage_seq start with 1 increment by 1 nomaxvalue"; + createGarbageThird = "create trigger garbage_trigger before insert on GARBAGE for each row begin select garbage_seq.nextval into :new.ID from dual; end;"; + dbDriver = "oracle.jdbc.OracleDriver"; + dbURL = "jdbc:oracle:thin:test/test@localhost:1521:XE"; + dbUser = "test"; + dbPwd = "test"; + peopleFirst = "create table PEOPLE (\"ID\" integer primary key, \"NAME\" VARCHAR2(32), \"AGE\" INTEGER)"; + peopleSecond = "create sequence people_seq start with 1 increment by 1 nomaxvalue"; + peopleThird = "create trigger people_trigger before insert on PEOPLE for each row begin select people_seq.nextval into :new.ID from dual; end;"; + versionStatements = new String[] { + "create table VERSIONED (\"ID\" integer primary key, \"TEXT\" VARCHAR(255), \"VERSION\" INTEGER DEFAULT 0)", + "create sequence versioned_seq start with 1 increment by 1 nomaxvalue", + "create trigger versioned_trigger before insert on VERSIONED for each row begin select versioned_seq.nextval into :new.ID from dual; end;", + "create sequence versioned_version start with 1 increment by 1 nomaxvalue", + "create trigger versioned_version_trigger before insert or update on VERSIONED for each row begin select versioned_version.nextval into :new.VERSION from dual; end;" }; + sqlGen = new OracleGenerator(); + break; + } + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java new file mode 100644 index 0000000000..7cad310d37 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java @@ -0,0 +1,315 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; + +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Property.ReadOnlyException; +import com.vaadin.data.util.sqlcontainer.ColumnProperty.NotNullableException; +import com.vaadin.data.util.sqlcontainer.query.QueryDelegate; + +public class ColumnPropertyTest { + + @Test + public void constructor_legalParameters_shouldSucceed() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertNotNull(cp); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_missingPropertyId_shouldFail() { + new ColumnProperty(null, false, true, true, false, "Ville", + String.class); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_missingType_shouldFail() { + new ColumnProperty("NAME", false, true, true, false, "Ville", null); + } + + @Test + public void getValue_defaultValue_returnsVille() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertEquals("Ville", cp.getValue()); + } + + @Test + public void setValue_readWriteNullable_returnsKalle() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue("Kalle"); + Assert.assertEquals("Kalle", cp.getValue()); + EasyMock.verify(container); + } + + @Test(expected = ReadOnlyException.class) + public void setValue_readOnlyNullable_shouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", true, true, true, false, + "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + EasyMock.replay(container); + cp.setValue("Kalle"); + EasyMock.verify(container); + } + + @Test + public void setValue_readWriteNullable_nullShouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + EasyMock.verify(container); + } + + @Test(expected = NotNullableException.class) + public void setValue_readWriteNotNullable_nullShouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, false, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue(null); + Assert.assertNotNull(cp.getValue()); + EasyMock.verify(container); + } + + @Test + public void getType_normal_returnsStringClass() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertSame(String.class, cp.getType()); + } + + @Test + public void isReadOnly_readWriteNullable_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertFalse(cp.isReadOnly()); + } + + @Test + public void isReadOnly_readOnlyNullable_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", true, true, true, false, + "Ville", String.class); + Assert.assertTrue(cp.isReadOnly()); + } + + @Test + public void setReadOnly_readOnlyChangeAllowed_shouldSucceed() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + cp.setReadOnly(true); + Assert.assertTrue(cp.isReadOnly()); + } + + @Test + public void setReadOnly_readOnlyChangeDisallowed_shouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + cp.setReadOnly(true); + Assert.assertFalse(cp.isReadOnly()); + } + + @Test + public void getPropertyId_normal_returnsNAME() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + Assert.assertEquals("NAME", cp.getPropertyId()); + } + + @Test + public void isModified_valueModified_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue("Kalle"); + Assert.assertEquals("Kalle", cp.getValue()); + Assert.assertTrue(cp.isModified()); + EasyMock.verify(container); + } + + @Test + public void isModified_valueNotModified_returnsFalse() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + Assert.assertFalse(cp.isModified()); + } + + @Test + public void setValue_nullOnNullable_shouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "asdf", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + } + + @Test + public void setValue_resetTonullOnNullable_shouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, null, String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + cp.setValue("asdf"); + Assert.assertEquals("asdf", cp.getValue()); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + } + + @Test + public void setValue_sendsItemChangeNotification() throws SQLException { + + class TestContainer extends SQLContainer { + Object value = null; + boolean modified = false; + + public TestContainer(QueryDelegate delegate) throws SQLException { + super(delegate); + } + + @Override + public void itemChangeNotification(RowItem changedItem) { + ColumnProperty cp = (ColumnProperty) changedItem + .getItemProperty("NAME"); + value = cp.getValue(); + modified = cp.isModified(); + } + } + + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Statement statement = EasyMock.createNiceMock(Statement.class); + EasyMock.replay(statement); + + ResultSetMetaData metadata = EasyMock + .createNiceMock(ResultSetMetaData.class); + EasyMock.replay(metadata); + + ResultSet resultSet = EasyMock.createNiceMock(ResultSet.class); + EasyMock.expect(resultSet.getStatement()).andReturn(statement); + EasyMock.expect(resultSet.getMetaData()).andReturn(metadata); + EasyMock.replay(resultSet); + + QueryDelegate delegate = EasyMock.createNiceMock(QueryDelegate.class); + EasyMock.expect(delegate.getResults(0, 1)).andReturn(resultSet); + EasyMock.replay(delegate); + + TestContainer container = new TestContainer(delegate); + + new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(property)); + + property.setValue("Kalle"); + Assert.assertEquals("Kalle", container.value); + Assert.assertTrue(container.modified); + } + + @Test + public void versionColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + property.setVersionColumn(true); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void neverWritableColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", true, false, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void writableColumnsShouldBeInValueMap_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Assert.assertTrue(property.isPersistent()); + } + + @Test + public void writableButReadOnlyColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", true, true, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void primKeysShouldBeRowIdentifiers_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + true, "Ville", String.class); + + Assert.assertTrue(property.isRowIdentifier()); + } + + @Test + public void versionColumnsShouldBeRowIdentifiers_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + property.setVersionColumn(true); + + Assert.assertTrue(property.isRowIdentifier()); + } + + @Test + public void nonPrimKeyOrVersionColumnsShouldBeNotRowIdentifiers_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isRowIdentifier()); + } + + @Test + public void getOldValueShouldReturnPreviousValue_shouldReturnVille() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + // Here we really don't care about the container management, but in + // order to set the value for a column the owner (RowItem) must be set + // and to create the owner we must have a container... + ArrayList<ColumnProperty> properties = new ArrayList<ColumnProperty>(); + properties.add(property); + + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + RowItem rowItem = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(property)); + + property.setValue("Kalle"); + // Just check that the new value was actually set... + Assert.assertEquals("Kalle", property.getValue()); + // Assert that old value is the original value... + Assert.assertEquals("Ville", property.getOldValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java new file mode 100644 index 0000000000..489f780d61 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java @@ -0,0 +1,139 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; + +public class DataGenerator { + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static void addPeopleToDatabase(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("drop table PEOPLE"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence people_seq"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + statement.execute(AllTests.peopleFirst); + if (AllTests.peopleSecond != null) { + statement.execute(AllTests.peopleSecond); + } + if (AllTests.db == DB.ORACLE) { + statement.execute(AllTests.peopleThird); + } + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Ville', '23')"); + statement.executeUpdate("insert into people values('Kalle', '7')"); + statement.executeUpdate("insert into people values('Pelle', '18')"); + statement.executeUpdate("insert into people values('Börje', '64')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Ville', '23')"); + statement + .executeUpdate("insert into people values(default, 'Kalle', '7')"); + statement + .executeUpdate("insert into people values(default, 'Pelle', '18')"); + statement + .executeUpdate("insert into people values(default, 'Börje', '64')"); + } + statement.close(); + statement = conn.createStatement(); + ResultSet rs = statement.executeQuery("select * from PEOPLE"); + Assert.assertTrue(rs.next()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void addFiveThousandPeople(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + for (int i = 4; i < 5000; i++) { + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Person " + + i + "', '" + i % 99 + "')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Person " + + i + "', '" + i % 99 + "')"); + } + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void addVersionedData(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("DROP TABLE VERSIONED"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence versioned_seq"); + statement.execute("drop sequence versioned_version"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + for (String stmtString : AllTests.versionStatements) { + statement.execute(stmtString); + } + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into VERSIONED values('Junk', default)"); + } else { + statement + .executeUpdate("insert into VERSIONED values(default, 'Junk', default)"); + } + statement.close(); + statement = conn.createStatement(); + ResultSet rs = statement.executeQuery("select * from VERSIONED"); + Assert.assertTrue(rs.next()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void createGarbage(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("drop table GARBAGE"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence garbage_seq"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + statement.execute(AllTests.createGarbage); + if (AllTests.db == DB.ORACLE) { + statement.execute(AllTests.createGarbageSecond); + statement.execute(AllTests.createGarbageThird); + } + conn.commit(); + connectionPool.releaseConnection(conn); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java new file mode 100644 index 0000000000..b0e2a232ca --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java @@ -0,0 +1,71 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; + +public class FreeformQueryUtil { + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static StatementHelper getQueryWithFilters(List<Filter> filters, + int offset, int limit) { + StatementHelper sh = new StatementHelper(); + if (AllTests.db == DB.MSSQL) { + if (limit > 1) { + offset++; + limit--; + } + StringBuilder query = new StringBuilder(); + query.append("SELECT * FROM (SELECT row_number() OVER ("); + query.append("ORDER BY \"ID\" ASC"); + query.append(") AS rownum, * FROM \"PEOPLE\""); + + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + query.append(") AS a WHERE a.rownum BETWEEN ").append(offset) + .append(" AND ").append(Integer.toString(offset + limit)); + sh.setQueryString(query.toString()); + return sh; + } else if (AllTests.db == DB.ORACLE) { + if (limit > 1) { + offset++; + limit--; + } + StringBuilder query = new StringBuilder(); + query.append("SELECT * FROM (SELECT x.*, ROWNUM AS " + + "\"rownum\" FROM (SELECT * FROM \"PEOPLE\""); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + query.append(") x) WHERE \"rownum\" BETWEEN ? AND ?"); + sh.addParameterValue(offset); + sh.addParameterValue(offset + limit); + sh.setQueryString(query.toString()); + return sh; + } else { + StringBuilder query = new StringBuilder("SELECT * FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + if (limit != 0 || offset != 0) { + query.append(" LIMIT ? OFFSET ?"); + sh.addParameterValue(limit); + sh.addParameterValue(offset); + } + sh.setQueryString(query.toString()); + return sh; + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java new file mode 100644 index 0000000000..d2b6ee2555 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java @@ -0,0 +1,50 @@ +package com.vaadin.data.util.sqlcontainer; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.ReadOnlyRowId; + +public class ReadOnlyRowIdTest { + + @Test + public void getRowNum_shouldReturnRowNumGivenInConstructor() { + int rowNum = 1337; + ReadOnlyRowId rid = new ReadOnlyRowId(rowNum); + Assert.assertEquals(rowNum, rid.getRowNum()); + } + + @Test + public void hashCode_shouldBeEqualToHashCodeOfRowNum() { + int rowNum = 1337; + ReadOnlyRowId rid = new ReadOnlyRowId(rowNum); + Assert.assertEquals(Integer.valueOf(rowNum).hashCode(), rid.hashCode()); + } + + @Test + public void equals_compareWithNull_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + Assert.assertFalse(rid.equals(null)); + } + + @Test + public void equals_compareWithSameInstance_shouldBeTrue() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + ReadOnlyRowId rid2 = rid; + Assert.assertTrue(rid.equals(rid2)); + } + + @Test + public void equals_compareWithOtherType_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + Assert.assertFalse(rid.equals(new Object())); + } + + @Test + public void equals_compareWithOtherRowId_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + ReadOnlyRowId rid2 = new ReadOnlyRowId(42); + Assert.assertFalse(rid.equals(rid2)); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java new file mode 100644 index 0000000000..399db06869 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java @@ -0,0 +1,55 @@ +package com.vaadin.data.util.sqlcontainer; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.RowId; + +public class RowIdTest { + + @Test + public void constructor_withArrayOfPrimaryKeyColumns_shouldSucceed() { + RowId id = new RowId(new Object[] { "id", "name" }); + Assert.assertArrayEquals(new Object[] { "id", "name" }, id.getId()); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_withNullParameter_shouldFail() { + new RowId(null); + } + + @Test + public void hashCode_samePrimaryKeys_sameResult() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id", "name" }); + Assert.assertEquals(id.hashCode(), id2.hashCode()); + } + + @Test + public void hashCode_differentPrimaryKeys_differentResult() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id" }); + Assert.assertFalse(id.hashCode() == id2.hashCode()); + } + + @Test + public void equals_samePrimaryKeys_returnsTrue() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id", "name" }); + Assert.assertEquals(id, id2); + } + + @Test + public void equals_differentPrimaryKeys_returnsFalse() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id" }); + Assert.assertFalse(id.equals(id2.hashCode())); + } + + @Test + public void equals_differentDataType_returnsFalse() { + RowId id = new RowId(new Object[] { "id", "name" }); + Assert.assertFalse(id.equals("Tudiluu")); + Assert.assertFalse(id.equals(new Integer(1337))); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java new file mode 100644 index 0000000000..438c40823d --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java @@ -0,0 +1,1519 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; + +public class SQLContainerTableQueryTest { + + private static final int offset = AllTests.offset; + private static final String createGarbage = AllTests.createGarbage; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void constructor_withTableQuery_shouldSucceed() throws SQLException { + new SQLContainer(new TableQuery("people", connectionPool, + AllTests.sqlGen)); + } + + @Test + public void containsId_withTableQueryAndExistingId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertTrue(container.containsId(new RowId( + new Object[] { 1 + offset }))); + } + + @Test + public void containsId_withTableQueryAndNonexistingId_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.containsId(new RowId( + new Object[] { 1337 + offset }))); + } + + @Test + public void getContainerProperty_tableExistingItemIdAndPropertyId_returnsProperty() + throws SQLException { + TableQuery t = new TableQuery("people", connectionPool, AllTests.sqlGen); + SQLContainer container = new SQLContainer(t); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + "Ville", + container + .getContainerProperty( + new RowId(new Object[] { new BigDecimal( + 0 + offset) }), "NAME").getValue()); + } else { + Assert.assertEquals( + "Ville", + container.getContainerProperty( + new RowId(new Object[] { 0 + offset }), "NAME") + .getValue()); + } + } + + @Test + public void getContainerProperty_tableExistingItemIdAndNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1 + offset }), "asdf")); + } + + @Test + public void getContainerProperty_tableNonexistingItemId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1337 + offset }), "NAME")); + } + + @Test + public void getContainerPropertyIds_table_returnsIDAndNAME() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> propertyIds = container.getContainerPropertyIds(); + Assert.assertEquals(3, propertyIds.size()); + Assert.assertArrayEquals(new String[] { "ID", "NAME", "AGE" }, + propertyIds.toArray()); + } + + @Test + public void getItem_tableExistingItemId_returnsItem() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 0 + offset) })); + } else { + item = container.getItem(new RowId(new Object[] { 0 + offset })); + } + Assert.assertNotNull(item); + Assert.assertEquals("Ville", item.getItemProperty("NAME").getValue()); + } + + @Test + public void getItem_commitedModifiedAndRefreshed() throws SQLException { + String OLD_VALUE = "SomeValue"; //$NON-NLS-1$ + String NEW_VALUE = "OtherValue"; //$NON-NLS-1$ + + SQLContainer container = new SQLContainer(new TableQuery("people", //$NON-NLS-1$ + connectionPool, AllTests.sqlGen)); + Object itemID = container.addItem(); + Item item = container.getItem(itemID); + item.getItemProperty("NAME").setValue(OLD_VALUE); //$NON-NLS-1$ + container.commit(); + + itemID = container.getIdByIndex(container.size() - 1); + item = container.getItem(itemID); + Assert.assertEquals(OLD_VALUE, item.getItemProperty("NAME") //$NON-NLS-1$ + .getValue()); + item.getItemProperty("NAME").setValue(NEW_VALUE); //$NON-NLS-1$ + + // refresh the container which free's the caches + // and the modified cache keeps untouched which is a really powerful + // feature + container.refresh(); + + // access the item again will use the item from the modified cache. + item = container.getItem(itemID); + Assert.assertEquals(NEW_VALUE, item.getItemProperty("NAME") //$NON-NLS-1$ + .getValue()); + } + + @Test + public void getItem_table5000RowsWithParameter1337_returnsItemWithId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertNotNull(item); + Assert.assertEquals(new BigDecimal(1337 + offset), item + .getItemProperty("ID").getValue()); + } else { + item = container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertNotNull(item); + Assert.assertEquals(1337 + offset, item.getItemProperty("ID") + .getValue()); + } + Assert.assertEquals("Person 1337", item.getItemProperty("NAME") + .getValue()); + } + + @Test + public void getItemIds_table_returnsItemIdsWithKeys0through3() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> itemIds = container.getItemIds(); + Assert.assertEquals(4, itemIds.size()); + RowId zero = new RowId(new Object[] { 0 + offset }); + RowId one = new RowId(new Object[] { 1 + offset }); + RowId two = new RowId(new Object[] { 2 + offset }); + RowId three = new RowId(new Object[] { 3 + offset }); + if (AllTests.db == DB.ORACLE) { + String[] correct = new String[] { "1", "2", "3", "4" }; + List<String> oracle = new ArrayList<String>(); + for (Object o : itemIds) { + oracle.add(o.toString()); + } + Assert.assertArrayEquals(correct, oracle.toArray()); + } else { + Assert.assertArrayEquals(new Object[] { zero, one, two, three }, + itemIds.toArray()); + } + } + + @Test + public void getType_tableNAMEPropertyId_returnsString() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(String.class, container.getType("NAME")); + } + + @Test + public void getType_tableIDPropertyId_returnsInteger() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(BigDecimal.class, container.getType("ID")); + } else { + Assert.assertEquals(Integer.class, container.getType("ID")); + } + } + + @Test + public void getType_tableNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getType("asdf")); + } + + @Test + public void size_table_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + } + + @Test + public void size_tableOneAddedItem_returnsFive() throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(5, container.size()); + } + + @Test + public void indexOfId_tableWithParameterThree_returnsThree() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(3, container.indexOfId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertEquals(3, + container.indexOfId(new RowId(new Object[] { 3 + offset }))); + } + } + + @Test + public void indexOfId_table5000RowsWithParameter1337_returns1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery q = new TableQuery("people", connectionPool, AllTests.sqlGen); + SQLContainer container = new SQLContainer(q); + if (AllTests.db == DB.ORACLE) { + container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { new BigDecimal(1337 + offset) }))); + } else { + container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { 1337 + offset }))); + } + } + + @Test + public void getIdByIndex_table5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void getIdByIndex_tableWithPaging5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void nextItemId_tableCurrentItem1337_returnsItem1338() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1338 + offset }).toString(), + container.nextItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1338 + offset }), + container.nextItemId(itemId)); + } + } + + @Test + public void prevItemId_tableCurrentItem1337_returns1336() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1336 + offset }).toString(), + container.prevItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1336 + offset }), + container.prevItemId(itemId)); + } + } + + @Test + public void firstItemId_table_returnsItemId0() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 0 + offset }).toString(), + container.firstItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 0 + offset }), + container.firstItemId()); + } + } + + @Test + public void lastItemId_table5000Rows_returnsItemId4999() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 4999 + offset }).toString(), + container.lastItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 4999 + offset }), + container.lastItemId()); + } + } + + @Test + public void isFirstId_tableActualFirstId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { new BigDecimal(0 + offset) }))); + } else { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { 0 + offset }))); + } + } + + @Test + public void isFirstId_tableSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_tableSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_tableLastId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 3 + offset }))); + } + } + + @Test + public void isLastId_table5000RowsLastId_returnsTrue() throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(4999 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 4999 + offset }))); + } + } + + @Test + public void allIdsFound_table5000RowsLastId_shouldSucceed() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + } + } + + @Test + public void allIdsFound_table5000RowsLastId_autoCommit_shouldSucceed() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setAutoCommit(true); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + } + } + + @Test + public void refresh_table_sizeShouldUpdate() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + container.refresh(); + Assert.assertEquals(5000, container.size()); + } + + @Test + public void refresh_tableWithoutCallingRefresh_sizeShouldNotUpdate() + throws SQLException { + // Yeah, this is a weird one. We're testing that the size doesn't update + // after adding lots of items unless we call refresh inbetween. This to + // make sure that the refresh method actually refreshes stuff and isn't + // a NOP. + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + Assert.assertEquals(4, container.size()); + } + + @Test + public void setAutoCommit_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setAutoCommit(true); + Assert.assertTrue(container.isAutoCommit()); + container.setAutoCommit(false); + Assert.assertFalse(container.isAutoCommit()); + } + + @Test + public void getPageLength_table_returnsDefault100() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(100, container.getPageLength()); + } + + @Test + public void setPageLength_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setPageLength(20); + Assert.assertEquals(20, container.getPageLength()); + container.setPageLength(200); + Assert.assertEquals(200, container.getPageLength()); + } + + @Test(expected = UnsupportedOperationException.class) + public void addContainerProperty_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addContainerProperty("asdf", String.class, ""); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeContainerProperty_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.removeContainerProperty("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObjectObject_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAfter("asdf", "foo"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtIntObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAt(2, "asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtInt_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAt(2); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAfter("asdf"); + } + + @Test + public void addItem_tableAddOneNewItem_returnsItemId() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + } + + @Test + public void addItem_tableAddOneNewItem_autoCommit_returnsFinalItemId() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + container.setAutoCommit(true); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + Assert.assertTrue(itemId instanceof RowId); + Assert.assertFalse(itemId instanceof TemporaryRowId); + } + + @Test + public void addItem_tableAddOneNewItem_autoCommit_sizeIsIncreased() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + container.setAutoCommit(true); + int originalSize = container.size(); + container.addItem(); + Assert.assertEquals(originalSize + 1, container.size()); + } + + @Test + public void addItem_tableAddOneNewItem_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + container.addItem(); + Assert.assertEquals(size + 1, container.size()); + } + + @Test + public void addItem_tableAddTwoNewItems_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(size + 2, container.size()); + Assert.assertNotSame(id1, id2); + Assert.assertFalse(id1.equals(id2)); + } + + @Test + public void nextItemId_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.nextItemId(lastId)); + } + + @Test + public void lastItemId_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.lastItemId()); + Assert.assertNotSame(lastId, container.lastItemId()); + } + + @Test + public void indexOfId_tableNewlyAddedItem_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertEquals(4, container.indexOfId(id)); + } + + @Test + public void getItem_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + } + + @Test + public void getItemIds_tableNewlyAddedItem_containsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + } + + @Test + public void getContainerProperty_tableNewlyAddedItem_returnsPropertyOfNewlyAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Item item = container.getItem(id); + item.getItemProperty("NAME").setValue("asdf"); + Assert.assertEquals("asdf", container.getContainerProperty(id, "NAME") + .getValue()); + } + + @Test + public void containsId_tableNewlyAddedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + } + + @Test + public void prevItemId_tableTwoNewlyAddedItems_returnsFirstAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(id1, container.prevItemId(id2)); + } + + @Test + public void firstItemId_tableEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertSame(id, container.firstItemId()); + } + + @Test + public void isFirstId_tableEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.isFirstId(id)); + } + + @Test + public void isLastId_tableOneItemAdded_returnsTrueForAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.isLastId(id)); + } + + @Test + public void isLastId_tableTwoItemsAdded_returnsTrueForLastAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem(); + Object id2 = container.addItem(); + Assert.assertTrue(container.isLastId(id2)); + } + + @Test + public void getIdByIndex_tableOneItemAddedLastIndexInContainer_returnsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertEquals(id, container.getIdByIndex(container.size() - 1)); + } + + @Test + public void removeItem_tableNoAddedItems_removesItemFromContainer() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.firstItemId()); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void containsId_tableRemovedItem_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void removeItem_tableOneAddedItem_removesTheAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + int size = container.size(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void getItem_tableItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItem_tableAddedItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemIds_tableItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void getItemIds_tableAddedItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void containsId_tableItemRemoved_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_tableAddedItemRemoved_returnsFalse() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void nextItemId_tableItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void nextItemId_tableAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void prevItemId_tableItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void prevItemId_tableAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void firstItemId_tableFirstItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertNotSame(first, container.firstItemId()); + } + + @Test + public void firstItemId_tableNewlyAddedFirstItemRemoved_resultChanges() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object first = container.addItem(); + Object second = container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertSame(second, container.firstItemId()); + } + + @Test + public void lastItemId_tableLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void lastItemId_tableAddedLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void isFirstId_tableFirstItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isFirstId_tableAddedFirstItemRemoved_returnsFalse() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object first = container.addItem(); + container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isLastId_tableLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void isLastId_tableAddedLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void indexOfId_tableItemRemoved_returnsNegOne() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void indexOfId_tableAddedItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.indexOfId(id) != -1); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void getIdByIndex_tableItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(2)); + } + + @Test + public void getIdByIndex_tableAddedItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + container.addItem(); + int index = container.indexOfId(id); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(index)); + } + + @Test + public void removeAllItems_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void removeAllItems_tableAddedItems_shouldSucceed() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem(); + container.addItem(); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void commit_tableAddedItem_shouldBeWrittenToDB() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("New Name"); + Assert.assertTrue(id instanceof TemporaryRowId); + Assert.assertSame(id, container.lastItemId()); + container.commit(); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("New Name", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void commit_tableTwoAddedItems_shouldBeWrittenToDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Object id2 = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("Herbert"); + container.getContainerProperty(id2, "NAME").setValue("Larry"); + Assert.assertTrue(id2 instanceof TemporaryRowId); + Assert.assertSame(id2, container.lastItemId()); + container.commit(); + Object nextToLast = container.getIdByIndex(container.size() - 2); + Assert.assertFalse(nextToLast instanceof TemporaryRowId); + Assert.assertEquals("Herbert", + container.getContainerProperty(nextToLast, "NAME").getValue()); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("Larry", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void commit_tableRemovedItem_shouldBeRemovedFromDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.removeItem(last); + container.commit(); + Assert.assertFalse(last.equals(container.lastItemId())); + } + + @Test + public void commit_tableLastItemUpdated_shouldUpdateRowInDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("Donald"); + container.commit(); + Assert.assertEquals("Donald", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void rollback_tableItemAdded_discardsAddedItem() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("foo"); + Assert.assertEquals(size + 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void rollback_tableItemRemoved_restoresRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object last = container.lastItemId(); + container.removeItem(last); + Assert.assertEquals(size - 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertEquals(last, container.lastItemId()); + } + + @Test + public void rollback_tableItemChanged_discardsChanges() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("foo"); + container.rollback(); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void itemChangeNotification_table_isModifiedReturnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + RowItem last = (RowItem) container.getItem(container.lastItemId()); + container.itemChangeNotification(last); + Assert.assertTrue(container.isModified()); + } + + @Test + public void itemSetChangeListeners_table_shouldFire() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.replay(listener); + + container.addListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void itemSetChangeListeners_tableItemRemoved_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeItem(container.lastItemId()); + + EasyMock.verify(listener); + } + + @Test + public void removeListener_table_shouldNotFire() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void isModified_tableRemovedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.removeItem(container.lastItemId()); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_tableAddedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.addItem(); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_tableChangedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.getContainerProperty(container.lastItemId(), "NAME") + .setValue("foo"); + Assert.assertTrue(container.isModified()); + } + + @Test + public void getSortableContainerPropertyIds_table_returnsAllPropertyIds() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> sortableIds = container.getSortableContainerPropertyIds(); + Assert.assertTrue(sortableIds.contains("ID")); + Assert.assertTrue(sortableIds.contains("NAME")); + Assert.assertTrue(sortableIds.contains("AGE")); + Assert.assertEquals(3, sortableIds.size()); + if (AllTests.db == DB.MSSQL || AllTests.db == DB.ORACLE) { + Assert.assertFalse(sortableIds.contains("rownum")); + } + } + + @Test + public void addOrderBy_table_shouldReorderResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addOrderBy(new OrderBy("NAME", true)); + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test(expected = IllegalArgumentException.class) + public void addOrderBy_tableIllegalColumn_shouldFail() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addOrderBy(new OrderBy("asdf", true)); + } + + @Test + public void sort_table_sortsByName() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addFilter_table_filtersResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Like("NAME", "%lle")); + // Ville, Kalle, Pelle + Assert.assertEquals(3, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addContainerFilter_filtersResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addContainerFilter_ignoreCase_filtersResults() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "vi", true, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void removeAllContainerFilters_table_noFiltering() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeAllContainerFilters(); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void removeContainerFilters_table_noFiltering() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeContainerFilters("NAME"); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addFilter_tableBufferedItems_alsoFiltersBufferedItems() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Palle"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Bengt"); + + container.addContainerFilter(new Like("NAME", "%lle")); + + // Ville, Kalle, Pelle, Palle + Assert.assertEquals(4, container.size()); + Assert.assertEquals( + "Ville", + container.getContainerProperty(container.getIdByIndex(0), + "NAME").getValue()); + Assert.assertEquals( + "Kalle", + container.getContainerProperty(container.getIdByIndex(1), + "NAME").getValue()); + Assert.assertEquals( + "Pelle", + container.getContainerProperty(container.getIdByIndex(2), + "NAME").getValue()); + Assert.assertEquals( + "Palle", + container.getContainerProperty(container.getIdByIndex(3), + "NAME").getValue()); + + Assert.assertNull(container.getIdByIndex(4)); + Assert.assertNull(container.nextItemId(container.getIdByIndex(3))); + + Assert.assertFalse(container.containsId(id2)); + Assert.assertFalse(container.getItemIds().contains(id2)); + + Assert.assertNull(container.getItem(id2)); + Assert.assertEquals(-1, container.indexOfId(id2)); + + Assert.assertNotSame(id2, container.lastItemId()); + Assert.assertSame(id1, container.lastItemId()); + } + + @Test + public void sort_tableBufferedItems_sortsBufferedItemsLastInOrderAdded() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Wilbert"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Albert"); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville, Wilbert, Albert + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals( + "Wilbert", + container.getContainerProperty( + container.getIdByIndex(container.size() - 2), "NAME") + .getValue()); + Assert.assertEquals("Albert", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java new file mode 100644 index 0000000000..6649bc16e8 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java @@ -0,0 +1,2458 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryDelegate; +import com.vaadin.data.util.sqlcontainer.query.FreeformStatementDelegate; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; + +public class SQLContainerTest { + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void constructor_withFreeformQuery_shouldSucceed() + throws SQLException { + new SQLContainer(new FreeformQuery("SELECT * FROM people", + connectionPool, "ID")); + } + + @Test(expected = SQLException.class) + public void constructor_withIllegalFreeformQuery_shouldFail() + throws SQLException { + SQLContainer c = new SQLContainer(new FreeformQuery( + "SELECT * FROM asdf", connectionPool, "ID")); + c.getItem(c.firstItemId()); + } + + @Test + public void containsId_withFreeformQueryAndExistingId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertTrue(container.containsId(new RowId(new Object[] { 1 }))); + } + + @Test + public void containsId_withFreeformQueryAndNonexistingId_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container + .containsId(new RowId(new Object[] { 1337 }))); + } + + @Test + public void getContainerProperty_freeformExistingItemIdAndPropertyId_returnsProperty() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + "Ville", + container + .getContainerProperty( + new RowId(new Object[] { new BigDecimal( + 0 + offset) }), "NAME").getValue()); + } else { + Assert.assertEquals( + "Ville", + container.getContainerProperty( + new RowId(new Object[] { 0 + offset }), "NAME") + .getValue()); + } + } + + @Test + public void getContainerProperty_freeformExistingItemIdAndNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1 + offset }), "asdf")); + } + + @Test + public void getContainerProperty_freeformNonexistingItemId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1337 + offset }), "NAME")); + } + + @Test + public void getContainerPropertyIds_freeform_returnsIDAndNAME() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> propertyIds = container.getContainerPropertyIds(); + Assert.assertEquals(3, propertyIds.size()); + Assert.assertArrayEquals(new String[] { "ID", "NAME", "AGE" }, + propertyIds.toArray()); + } + + @Test + public void getItem_freeformExistingItemId_returnsItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 0 + offset) })); + } else { + item = container.getItem(new RowId(new Object[] { 0 + offset })); + } + Assert.assertNotNull(item); + Assert.assertEquals("Ville", item.getItemProperty("NAME").getValue()); + } + + @Test + public void getItem_freeform5000RowsWithParameter1337_returnsItemWithId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertNotNull(item); + Assert.assertEquals(new BigDecimal(1337 + offset), item + .getItemProperty("ID").getValue()); + } else { + item = container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertNotNull(item); + Assert.assertEquals(1337 + offset, item.getItemProperty("ID") + .getValue()); + } + Assert.assertEquals("Person 1337", item.getItemProperty("NAME") + .getValue()); + } + + @Test + public void getItemIds_freeform_returnsItemIdsWithKeys0through3() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> itemIds = container.getItemIds(); + Assert.assertEquals(4, itemIds.size()); + RowId zero = new RowId(new Object[] { 0 + offset }); + RowId one = new RowId(new Object[] { 1 + offset }); + RowId two = new RowId(new Object[] { 2 + offset }); + RowId three = new RowId(new Object[] { 3 + offset }); + if (AllTests.db == DB.ORACLE) { + String[] correct = new String[] { "1", "2", "3", "4" }; + List<String> oracle = new ArrayList<String>(); + for (Object o : itemIds) { + oracle.add(o.toString()); + } + Assert.assertArrayEquals(correct, oracle.toArray()); + } else { + Assert.assertArrayEquals(new Object[] { zero, one, two, three }, + itemIds.toArray()); + } + } + + @Test + public void getType_freeformNAMEPropertyId_returnsString() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(String.class, container.getType("NAME")); + } + + @Test + public void getType_freeformIDPropertyId_returnsInteger() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(BigDecimal.class, container.getType("ID")); + } else { + Assert.assertEquals(Integer.class, container.getType("ID")); + } + } + + @Test + public void getType_freeformNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getType("asdf")); + } + + @Test + public void size_freeform_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + } + + @Test + public void size_freeformOneAddedItem_returnsFive() throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', '42')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', '42')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(5, container.size()); + } + + @Test + public void indexOfId_freeformWithParameterThree_returnsThree() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(3, container.indexOfId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertEquals(3, + container.indexOfId(new RowId(new Object[] { 3 + offset }))); + } + } + + @Test + public void indexOfId_freeform5000RowsWithParameter1337_returns1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { new BigDecimal(1337 + offset) }))); + } else { + container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { 1337 + offset }))); + } + } + + @Test + public void getIdByIndex_freeform5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new RowId(new Object[] { new BigDecimal( + 1337 + offset) }), itemId); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @SuppressWarnings("unchecked") + @Test + public void getIdByIndex_freeformWithPaging5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void nextItemId_freeformCurrentItem1337_returnsItem1338() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1338 + offset }).toString(), + container.nextItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1338 + offset }), + container.nextItemId(itemId)); + } + } + + @Test + public void prevItemId_freeformCurrentItem1337_returns1336() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1336 + offset }).toString(), + container.prevItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1336 + offset }), + container.prevItemId(itemId)); + } + } + + @Test + public void firstItemId_freeform_returnsItemId0() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 0 + offset }).toString(), + container.firstItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 0 + offset }), + container.firstItemId()); + } + } + + @Test + public void lastItemId_freeform5000Rows_returnsItemId4999() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 4999 + offset }).toString(), + container.lastItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 4999 + offset }), + container.lastItemId()); + } + } + + @Test + public void isFirstId_freeformActualFirstId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { new BigDecimal(0 + offset) }))); + } else { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { 0 + offset }))); + } + } + + @Test + public void isFirstId_freeformSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_freeformSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_freeformLastId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 3 + offset }))); + } + } + + @Test + public void isLastId_freeform5000RowsLastId_returnsTrue() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(4999 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 4999 + offset }))); + } + } + + @Test + public void refresh_freeform_sizeShouldUpdate() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + container.refresh(); + Assert.assertEquals(5000, container.size()); + } + + @Test + public void refresh_freeformWithoutCallingRefresh_sizeShouldNotUpdate() + throws SQLException { + // Yeah, this is a weird one. We're testing that the size doesn't update + // after adding lots of items unless we call refresh inbetween. This to + // make sure that the refresh method actually refreshes stuff and isn't + // a NOP. + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + Assert.assertEquals(4, container.size()); + } + + @Test + public void setAutoCommit_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.setAutoCommit(true); + Assert.assertTrue(container.isAutoCommit()); + container.setAutoCommit(false); + Assert.assertFalse(container.isAutoCommit()); + } + + @Test + public void getPageLength_freeform_returnsDefault100() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(100, container.getPageLength()); + } + + @Test + public void setPageLength_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.setPageLength(20); + Assert.assertEquals(20, container.getPageLength()); + container.setPageLength(200); + Assert.assertEquals(200, container.getPageLength()); + } + + @Test(expected = UnsupportedOperationException.class) + public void addContainerProperty_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerProperty("asdf", String.class, ""); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeContainerProperty_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.removeContainerProperty("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObjectObject_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAfter("asdf", "foo"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtIntObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAt(2, "asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtInt_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAt(2); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAfter("asdf"); + } + + @Test + public void addItem_freeformAddOneNewItem_returnsItemId() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + } + + @Test + public void addItem_freeformAddOneNewItem_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + container.addItem(); + Assert.assertEquals(size + 1, container.size()); + } + + @Test + public void addItem_freeformAddTwoNewItems_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(size + 2, container.size()); + Assert.assertNotSame(id1, id2); + Assert.assertFalse(id1.equals(id2)); + } + + @Test + public void nextItemId_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.nextItemId(lastId)); + } + + @Test + public void lastItemId_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.lastItemId()); + Assert.assertNotSame(lastId, container.lastItemId()); + } + + @Test + public void indexOfId_freeformNewlyAddedItem_returnsFour() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertEquals(4, container.indexOfId(id)); + } + + @Test + public void getItem_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + } + + @Test + public void getItem_freeformNewlyAddedItemAndFiltered_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerFilter(new Equal("NAME", "asdf")); + Object id = container.addItem(); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemUnfiltered_freeformNewlyAddedItemAndFiltered_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerFilter(new Equal("NAME", "asdf")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItemUnfiltered(id)); + } + + @Test + public void getItemIds_freeformNewlyAddedItem_containsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + } + + @Test + public void getContainerProperty_freeformNewlyAddedItem_returnsPropertyOfNewlyAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Item item = container.getItem(id); + item.getItemProperty("NAME").setValue("asdf"); + Assert.assertEquals("asdf", container.getContainerProperty(id, "NAME") + .getValue()); + } + + @Test + public void containsId_freeformNewlyAddedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + } + + @Test + public void prevItemId_freeformTwoNewlyAddedItems_returnsFirstAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(id1, container.prevItemId(id2)); + } + + @Test + public void firstItemId_freeformEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertSame(id, container.firstItemId()); + } + + @Test + public void isFirstId_freeformEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.isFirstId(id)); + } + + @Test + public void isLastId_freeformOneItemAdded_returnsTrueForAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.isLastId(id)); + } + + @Test + public void isLastId_freeformTwoItemsAdded_returnsTrueForLastAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem(); + Object id2 = container.addItem(); + Assert.assertTrue(container.isLastId(id2)); + } + + @Test + public void getIdByIndex_freeformOneItemAddedLastIndexInContainer_returnsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertEquals(id, container.getIdByIndex(container.size() - 1)); + } + + @Test + public void removeItem_freeformNoAddedItems_removesItemFromContainer() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.firstItemId()); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void containsId_freeformRemovedItem_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_unknownObject() throws SQLException { + + Handler ensureNoLogging = new Handler() { + + @Override + public void publish(LogRecord record) { + Assert.fail("No messages should be logged"); + + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }; + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Logger logger = Logger.getLogger(SQLContainer.class.getName()); + + logger.addHandler(ensureNoLogging); + try { + Assert.assertFalse(container.containsId(new Object())); + } finally { + logger.removeHandler(ensureNoLogging); + } + } + + @Test + public void removeItem_freeformOneAddedItem_removesTheAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + int size = container.size(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void getItem_freeformItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItem_freeformAddedItemRemoved_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemIds_freeformItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void getItemIds_freeformAddedItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void containsId_freeformItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_freeformAddedItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void nextItemId_freeformItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void nextItemId_freeformAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void prevItemId_freeformItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void prevItemId_freeformAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void firstItemId_freeformFirstItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertNotSame(first, container.firstItemId()); + } + + @Test + public void firstItemId_freeformNewlyAddedFirstItemRemoved_resultChanges() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object first = container.addItem(); + Object second = container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertSame(second, container.firstItemId()); + } + + @Test + public void lastItemId_freeformLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void lastItemId_freeformAddedLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void isFirstId_freeformFirstItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isFirstId_freeformAddedFirstItemRemoved_returnsFalse() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object first = container.addItem(); + container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isLastId_freeformLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void isLastId_freeformAddedLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void indexOfId_freeformItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void indexOfId_freeformAddedItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.indexOfId(id) != -1); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void getIdByIndex_freeformItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(2)); + } + + @Test + public void getIdByIndex_freeformAddedItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + container.addItem(); + int index = container.indexOfId(id); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(index)); + } + + @Test + public void removeAllItems_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void removeAllItems_freeformAddedItems_shouldSucceed() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem(); + container.addItem(); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformAddedItem_shouldBeWrittenToDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into people values('" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } else { + statement + .executeUpdate("insert into people values(default, '" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("New Name"); + container.getContainerProperty(id, "AGE").setValue(30); + Assert.assertTrue(id instanceof TemporaryRowId); + Assert.assertSame(id, container.lastItemId()); + container.commit(); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("New Name", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformTwoAddedItems_shouldBeWrittenToDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into people values('" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } else { + statement + .executeUpdate("insert into people values(default, '" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Object id2 = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("Herbert"); + container.getContainerProperty(id, "AGE").setValue(30); + container.getContainerProperty(id2, "NAME").setValue("Larry"); + container.getContainerProperty(id2, "AGE").setValue(50); + Assert.assertTrue(id2 instanceof TemporaryRowId); + Assert.assertSame(id2, container.lastItemId()); + container.commit(); + Object nextToLast = container.getIdByIndex(container.size() - 2); + Assert.assertFalse(nextToLast instanceof TemporaryRowId); + Assert.assertEquals("Herbert", + container.getContainerProperty(nextToLast, "NAME").getValue()); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("Larry", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformRemovedItem_shouldBeRemovedFromDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Boolean>() { + @Override + public Boolean answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + statement + .executeUpdate("DELETE FROM people WHERE \"ID\"=" + + item.getItemProperty("ID").getValue()); + statement.close(); + return true; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.removeItem(last); + container.commit(); + Assert.assertFalse(last.equals(container.lastItemId())); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformLastItemUpdated_shouldUpdateRowInDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + statement.executeUpdate("UPDATE people SET \"NAME\"='" + + item.getItemProperty("NAME").getValue() + + "' WHERE \"ID\"=" + + item.getItemProperty("ID").getValue()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("Donald"); + container.commit(); + Assert.assertEquals("Donald", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @Test + public void rollback_freeformItemAdded_discardsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("foo"); + Assert.assertEquals(size + 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void rollback_freeformItemRemoved_restoresRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object last = container.lastItemId(); + container.removeItem(last); + Assert.assertEquals(size - 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertEquals(last, container.lastItemId()); + } + + @Test + public void rollback_freeformItemChanged_discardsChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("foo"); + container.rollback(); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void itemChangeNotification_freeform_isModifiedReturnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + RowItem last = (RowItem) container.getItem(container.lastItemId()); + container.itemChangeNotification(last); + Assert.assertTrue(container.isModified()); + } + + @Test + public void itemSetChangeListeners_freeform_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.replay(listener); + + container.addListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void itemSetChangeListeners_freeformItemRemoved_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeItem(container.lastItemId()); + + EasyMock.verify(listener); + } + + @Test + public void removeListener_freeform_shouldNotFire() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void isModified_freeformRemovedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.removeItem(container.lastItemId()); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_freeformAddedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.addItem(); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_freeformChangedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.getContainerProperty(container.lastItemId(), "NAME") + .setValue("foo"); + Assert.assertTrue(container.isModified()); + } + + @Test + public void getSortableContainerPropertyIds_freeform_returnsAllPropertyIds() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> sortableIds = container.getSortableContainerPropertyIds(); + Assert.assertTrue(sortableIds.contains("ID")); + Assert.assertTrue(sortableIds.contains("NAME")); + Assert.assertTrue(sortableIds.contains("AGE")); + Assert.assertEquals(3, sortableIds.size()); + } + + @SuppressWarnings("unchecked") + @Test + public void addOrderBy_freeform_shouldReorderResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addOrderBy(new OrderBy("NAME", true)); + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @Test(expected = IllegalArgumentException.class) + public void addOrderBy_freeformIllegalColumn_shouldFail() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addOrderBy(new OrderBy("asdf", true)); + } + + @SuppressWarnings("unchecked") + @Test + public void sort_freeform_sortsByName() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addFilter_freeform_filtersResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Like("NAME", "%lle")); + // Ville, Kalle, Pelle + Assert.assertEquals(3, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addContainerFilter_filtersResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addContainerFilter_ignoreCase_filtersResults() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + // FIXME LIKE %asdf% doesn't match a string that begins with asdf + container.addContainerFilter("NAME", "vi", true, true); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void removeAllContainerFilters_freeform_noFiltering() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeAllContainerFilters(); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void removeContainerFilters_freeform_noFiltering() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, true); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeContainerFilters("NAME"); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addFilter_freeformBufferedItems_alsoFiltersBufferedItems() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Palle"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Bengt"); + + container.addContainerFilter(new Like("NAME", "%lle")); + + // Ville, Kalle, Pelle, Palle + Assert.assertEquals(4, container.size()); + Assert.assertEquals( + "Ville", + container.getContainerProperty(container.getIdByIndex(0), + "NAME").getValue()); + Assert.assertEquals( + "Kalle", + container.getContainerProperty(container.getIdByIndex(1), + "NAME").getValue()); + Assert.assertEquals( + "Pelle", + container.getContainerProperty(container.getIdByIndex(2), + "NAME").getValue()); + Assert.assertEquals( + "Palle", + container.getContainerProperty(container.getIdByIndex(3), + "NAME").getValue()); + + Assert.assertNull(container.getIdByIndex(4)); + Assert.assertNull(container.nextItemId(container.getIdByIndex(3))); + + Assert.assertFalse(container.containsId(id2)); + Assert.assertFalse(container.getItemIds().contains(id2)); + + Assert.assertNull(container.getItem(id2)); + Assert.assertEquals(-1, container.indexOfId(id2)); + + Assert.assertNotSame(id2, container.lastItemId()); + Assert.assertSame(id1, container.lastItemId()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void sort_freeformBufferedItems_sortsBufferedItemsLastInOrderAdded() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Wilbert"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Albert"); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville, Wilbert, Albert + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals( + "Wilbert", + container.getContainerProperty( + container.getIdByIndex(container.size() - 2), "NAME") + .getValue()); + Assert.assertEquals("Albert", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java new file mode 100644 index 0000000000..a12786f13a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java @@ -0,0 +1,186 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformStatementDelegate; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; +import com.vaadin.ui.Table; +import com.vaadin.ui.Window; + +public class TicketTests { + + private SimpleJDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @Test + public void ticket5867_throwsIllegalState_transactionAlreadyActive() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", Arrays.asList("ID"), connectionPool)); + Table table = new Table(); + Window w = new Window(); + w.addComponent(table); + table.setContainerDataSource(container); + } + + @SuppressWarnings("unchecked") + @Test + public void ticket6136_freeform_ageIs18() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Equal("AGE", 18)); + // Pelle + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new BigDecimal(18), container + .getContainerProperty(container.firstItemId(), "AGE") + .getValue()); + } else { + Assert.assertEquals( + 18, + container.getContainerProperty(container.firstItemId(), + "AGE").getValue()); + } + + EasyMock.verify(delegate); + } + + @Test + public void ticket6136_table_ageIs18() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter(new Equal("AGE", 18)); + + // Pelle + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new BigDecimal(18), container + .getContainerProperty(container.firstItemId(), "AGE") + .getValue()); + } else { + Assert.assertEquals( + 18, + container.getContainerProperty(container.firstItemId(), + "AGE").getValue()); + } + } + + @Test + public void ticket7434_getItem_Modified_Changed_Unchanged() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + + Object id = container.firstItemId(); + Item item = container.getItem(id); + String name = (String) item.getItemProperty("NAME").getValue(); + + // set a different name + item.getItemProperty("NAME").setValue("otherName"); + Assert.assertEquals("otherName", item.getItemProperty("NAME") + .getValue()); + + // access the item and reset the name to its old value + Item item2 = container.getItem(id); + item2.getItemProperty("NAME").setValue(name); + Assert.assertEquals(name, item2.getItemProperty("NAME").getValue()); + + Item item3 = container.getItem(id); + String name3 = (String) item3.getItemProperty("NAME").getValue(); + + Assert.assertEquals(name, name3); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java new file mode 100644 index 0000000000..31bdf2b81b --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java @@ -0,0 +1,53 @@ +package com.vaadin.data.util.sqlcontainer; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.SQLUtil; + +public class UtilTest { + + @Test + public void escapeSQL_noQuotes_returnsSameString() { + Assert.assertEquals("asdf", SQLUtil.escapeSQL("asdf")); + } + + @Test + public void escapeSQL_singleQuotes_returnsEscapedString() { + Assert.assertEquals("O''Brien", SQLUtil.escapeSQL("O'Brien")); + } + + @Test + public void escapeSQL_severalQuotes_returnsEscapedString() { + Assert.assertEquals("asdf''ghjk''qwerty", + SQLUtil.escapeSQL("asdf'ghjk'qwerty")); + } + + @Test + public void escapeSQL_doubleQuotes_returnsEscapedString() { + Assert.assertEquals("asdf\\\"foo", SQLUtil.escapeSQL("asdf\"foo")); + } + + @Test + public void escapeSQL_multipleDoubleQuotes_returnsEscapedString() { + Assert.assertEquals("asdf\\\"foo\\\"bar", + SQLUtil.escapeSQL("asdf\"foo\"bar")); + } + + @Test + public void escapeSQL_backslashes_returnsEscapedString() { + Assert.assertEquals("foo\\\\nbar\\\\r", + SQLUtil.escapeSQL("foo\\nbar\\r")); + } + + @Test + public void escapeSQL_x00_removesX00() { + Assert.assertEquals("foobar", SQLUtil.escapeSQL("foo\\x00bar")); + } + + @Test + public void escapeSQL_x1a_removesX1a() { + Assert.assertEquals("foobar", SQLUtil.escapeSQL("foo\\x1abar")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java new file mode 100644 index 0000000000..65a995120e --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java @@ -0,0 +1,108 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.sql.DataSource; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +public class J2EEConnectionPoolTest { + + @Test + public void reserveConnection_dataSourceSpecified_shouldReturnValidConnection() + throws SQLException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + EasyMock.replay(connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + EasyMock.verify(connection, ds); + } + + @Test + public void releaseConnection_shouldCloseConnection() throws SQLException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + connection.close(); + EasyMock.expectLastCall(); + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + EasyMock.replay(connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + pool.releaseConnection(c); + EasyMock.verify(connection, ds); + } + + @Test + public void reserveConnection_dataSourceLookedUp_shouldReturnValidConnection() + throws SQLException, NamingException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + connection.close(); + EasyMock.expectLastCall(); + + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + + System.setProperty("java.naming.factory.initial", + "com.vaadin.data.util.sqlcontainer.connection.MockInitialContextFactory"); + Context context = EasyMock.createMock(Context.class); + context.lookup("testDataSource"); + EasyMock.expectLastCall().andReturn(ds); + MockInitialContextFactory.setMockContext(context); + + EasyMock.replay(context, connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool("testDataSource"); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + pool.releaseConnection(c); + EasyMock.verify(context, connection, ds); + } + + @Test(expected = SQLException.class) + public void reserveConnection_nonExistantDataSourceLookedUp_shouldFail() + throws SQLException, NamingException { + System.setProperty("java.naming.factory.initial", + "com.vaadin.addon.sqlcontainer.connection.MockInitialContextFactory"); + Context context = EasyMock.createMock(Context.class); + context.lookup("foo"); + EasyMock.expectLastCall().andThrow(new NamingException("fail")); + MockInitialContextFactory.setMockContext(context); + + EasyMock.replay(context); + + J2EEConnectionPool pool = new J2EEConnectionPool("foo"); + pool.reserveConnection(); + EasyMock.verify(context); + } + + @Test + public void releaseConnection_null_shouldSucceed() throws SQLException { + DataSource ds = EasyMock.createMock(DataSource.class); + EasyMock.replay(ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + pool.releaseConnection(null); + EasyMock.verify(ds); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java new file mode 100644 index 0000000000..324899e373 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java @@ -0,0 +1,33 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + +import org.junit.Test; + +/** + * Provides a JNDI initial context factory for the MockContext. + */ +public class MockInitialContextFactory implements InitialContextFactory { + private static Context mockCtx = null; + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static void setMockContext(Context ctx) { + mockCtx = ctx; + } + + @Override + public Context getInitialContext(java.util.Hashtable<?, ?> environment) + throws NamingException { + if (mockCtx == null) { + throw new IllegalStateException("mock context was not set."); + } + return mockCtx; + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java new file mode 100644 index 0000000000..147319643d --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java @@ -0,0 +1,172 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import java.sql.Connection; +import java.sql.SQLException; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; + +public class SimpleJDBCConnectionPoolTest { + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } + + @Test + public void reserveConnection_reserveNewConnection_returnsConnection() + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Assert.assertNotNull(conn); + } + + @Test + public void releaseConnection_releaseUnused_shouldNotThrowException() + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + connectionPool.releaseConnection(conn); + Assert.assertFalse(conn.isClosed()); + } + + @Test(expected = SQLException.class) + public void reserveConnection_noConnectionsLeft_shouldFail() + throws SQLException { + try { + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + connectionPool.reserveConnection(); + Assert.fail("Reserving connection didn't fail even though no connections are available!"); + } + + @Test + public void reserveConnection_oneConnectionLeft_returnsConnection() + throws SQLException { + try { + connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + Connection conn = connectionPool.reserveConnection(); + Assert.assertNotNull(conn); + } + + @Test + public void reserveConnection_oneConnectionJustReleased_returnsConnection() + throws SQLException { + Connection conn2 = null; + try { + connectionPool.reserveConnection(); + conn2 = connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + connectionPool.releaseConnection(conn2); + + connectionPool.reserveConnection(); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_allParametersNull_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool(null, null, + null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameGiven_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, null, null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameAndUrlGiven_shouldFail() + throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, AllTests.dbURL, null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameAndUrlAndUserGiven_shouldFail() + throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, AllTests.dbURL, AllTests.dbUser, null); + } + + @Test(expected = RuntimeException.class) + public void construct_nonExistingDriver_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool("foo", + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd); + } + + @Test + public void reserveConnection_newConnectionOpened_shouldSucceed() + throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 0, 2); + Connection c = connectionPool.reserveConnection(); + Assert.assertNotNull(c); + } + + @Test + public void releaseConnection_nullConnection_shouldDoNothing() { + connectionPool.releaseConnection(null); + } + + @Test + public void releaseConnection_failingRollback_shouldCallClose() + throws SQLException { + Connection c = EasyMock.createMock(Connection.class); + c.getAutoCommit(); + EasyMock.expectLastCall().andReturn(false); + c.rollback(); + EasyMock.expectLastCall().andThrow(new SQLException("Rollback failed")); + c.close(); + EasyMock.expectLastCall().atLeastOnce(); + EasyMock.replay(c); + // make sure the connection pool is initialized + connectionPool.reserveConnection(); + connectionPool.releaseConnection(c); + EasyMock.verify(c); + } + + @Test + public void destroy_shouldCloseAllConnections() throws SQLException { + Connection c1 = connectionPool.reserveConnection(); + Connection c2 = connectionPool.reserveConnection(); + connectionPool.destroy(); + Assert.assertTrue(c1.isClosed()); + Assert.assertTrue(c2.isClosed()); + } + + @Test + public void destroy_shouldCloseAllConnections2() throws SQLException { + Connection c1 = connectionPool.reserveConnection(); + Connection c2 = connectionPool.reserveConnection(); + connectionPool.releaseConnection(c1); + connectionPool.releaseConnection(c2); + connectionPool.destroy(); + Assert.assertTrue(c1.isClosed()); + Assert.assertTrue(c2.isClosed()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java new file mode 100644 index 0000000000..da4cfe4522 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java @@ -0,0 +1,122 @@ +package com.vaadin.data.util.sqlcontainer.filters; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.filter.Between; + +public class BetweenTest { + + private Item itemWithPropertyValue(Object propertyId, Object value) { + Property<?> property = EasyMock.createMock(Property.class); + property.getValue(); + EasyMock.expectLastCall().andReturn(value).anyTimes(); + EasyMock.replay(property); + + Item item = EasyMock.createMock(Item.class); + item.getItemProperty(propertyId); + EasyMock.expectLastCall().andReturn(property).anyTimes(); + EasyMock.replay(item); + return item; + } + + @Test + public void passesFilter_valueIsInRange_shouldBeTrue() { + Item item = itemWithPropertyValue("foo", 15); + Between between = new Between("foo", 1, 30); + Assert.assertTrue(between.passesFilter("foo", item)); + } + + @Test + public void passesFilter_valueIsOutOfRange_shouldBeFalse() { + Item item = itemWithPropertyValue("foo", 15); + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.passesFilter("foo", item)); + } + + @Test + public void passesFilter_valueNotComparable_shouldBeFalse() { + Item item = itemWithPropertyValue("foo", new Object()); + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.passesFilter("foo", item)); + } + + @Test + public void appliesToProperty_differentProperties_shoudlBeFalse() { + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.appliesToProperty("bar")); + } + + @Test + public void appliesToProperty_sameProperties_shouldBeTrue() { + Between between = new Between("foo", 0, 2); + Assert.assertTrue(between.appliesToProperty("foo")); + } + + @Test + public void hashCode_equalInstances_shouldBeEqual() { + Between b1 = new Between("foo", 0, 2); + Between b2 = new Between("foo", 0, 2); + Assert.assertEquals(b1.hashCode(), b2.hashCode()); + } + + @Test + public void equals_differentObjects_shouldBeFalse() { + Between b1 = new Between("foo", 0, 2); + Object obj = new Object(); + Assert.assertFalse(b1.equals(obj)); + } + + @Test + public void equals_sameInstance_shouldBeTrue() { + Between b1 = new Between("foo", 0, 2); + Between b2 = b1; + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_equalInstances_shouldBeTrue() { + Between b1 = new Between("foo", 0, 2); + Between b2 = new Between("foo", 0, 2); + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_equalInstances2_shouldBeTrue() { + Between b1 = new Between(null, null, null); + Between b2 = new Between(null, null, null); + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_secondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", 0, 1); + Between b2 = new Between("foo", 0, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_firstAndSecondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", 0, null); + Between b2 = new Between("foo", 1, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_propertyAndFirstAndSecondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", null, 1); + Between b2 = new Between("bar", 1, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_propertiesDiffer_shouldBeFalse() { + Between b1 = new Between(null, 0, 1); + Between b2 = new Between("bar", 0, 1); + Assert.assertFalse(b1.equals(b2)); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java new file mode 100644 index 0000000000..f1130aad80 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java @@ -0,0 +1,229 @@ +package com.vaadin.data.util.sqlcontainer.filters; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.data.util.filter.Like; + +public class LikeTest { + + @Test + public void passesFilter_valueIsNotStringType_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<Integer>(5)); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValue_shouldSucceed() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfooghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValueCaseInsensitive_shouldSucceed() { + Like like = new Like("test", "%foo%"); + like.setCaseSensitive(false); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfOOghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValueConstructedCaseInsensitive_shouldSucceed() { + Like like = new Like("test", "%foo%", false); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfOOghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringNotContainingValue_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdbarghij")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringExactlyEqualToValue_shouldSucceed() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foo")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringEqualToValueMinusOneCharAtTheEnd_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("fo")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_beginsWithLikeQueryOnStringBeginningWithValue_shouldSucceed() { + Like like = new Like("test", "foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foobar")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_beginsWithLikeQueryOnStringNotBeginningWithValue_shouldFail() { + Like like = new Like("test", "foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("barfoo")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_endsWithLikeQueryOnStringEndingWithValue_shouldSucceed() { + Like like = new Like("test", "%foo"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("barfoo")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_endsWithLikeQueryOnStringNotEndingWithValue_shouldFail() { + Like like = new Like("test", "%foo"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foobar")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_startsWithAndEndsWithOnMatchingValue_shouldSucceed() { + Like like = new Like("test", "foo%bar"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("fooASDFbar")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void appliesToProperty_valueIsProperty_shouldBeTrue() { + Like like = new Like("test", "%foo"); + Assert.assertTrue(like.appliesToProperty("test")); + } + + @Test + public void appliesToProperty_valueIsNotProperty_shouldBeFalse() { + Like like = new Like("test", "%foo"); + Assert.assertFalse(like.appliesToProperty("bar")); + } + + @Test + public void equals_sameInstances_shouldBeTrue() { + Like like1 = new Like("test", "%foo"); + Like like2 = like1; + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_twoEqualInstances_shouldBeTrue() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "foo"); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_differentValues_shouldBeFalse() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "bar"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentProperties_shouldBeFalse() { + Like like1 = new Like("foo", "test"); + Like like2 = new Like("bar", "test"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentPropertiesAndValues_shouldBeFalse() { + Like like1 = new Like("foo", "bar"); + Like like2 = new Like("baz", "zomg"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentClasses_shouldBeFalse() { + Like like1 = new Like("foo", "bar"); + Object obj = new Object(); + Assert.assertFalse(like1.equals(obj)); + } + + @Test + public void equals_bothHaveNullProperties_shouldBeTrue() { + Like like1 = new Like(null, "foo"); + Like like2 = new Like(null, "foo"); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_bothHaveNullValues_shouldBeTrue() { + Like like1 = new Like("foo", null); + Like like2 = new Like("foo", null); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_onePropertyIsNull_shouldBeFalse() { + Like like1 = new Like(null, "bar"); + Like like2 = new Like("foo", "baz"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_oneValueIsNull_shouldBeFalse() { + Like like1 = new Like("foo", null); + Like like2 = new Like("baz", "bar"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void hashCode_equalInstances_shouldBeEqual() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "foo"); + Assert.assertEquals(like1.hashCode(), like2.hashCode()); + } + + @Test + public void hashCode_differentPropertiesAndValues_shouldNotEqual() { + Like like1 = new Like("foo", "bar"); + Like like2 = new Like("baz", "zomg"); + Assert.assertTrue(like1.hashCode() != like2.hashCode()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java new file mode 100644 index 0000000000..e62a06e6e1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java @@ -0,0 +1,241 @@ +package com.vaadin.data.util.sqlcontainer.generator; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.filter.Or; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; + +public class SQLGeneratorsTest { + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void generateSelectQuery_basicQuery_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + StatementHelper sh = sg.generateSelectQuery("TABLE", null, null, 0, 0, + null); + Assert.assertEquals(sh.getQueryString(), "SELECT * FROM TABLE"); + } + + @Test + public void generateSelectQuery_pagingAndColumnsSet_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + StatementHelper sh = sg.generateSelectQuery("TABLE", null, null, 4, 8, + "COL1, COL2, COL3"); + Assert.assertEquals(sh.getQueryString(), + "SELECT COL1, COL2, COL3 FROM TABLE LIMIT 8 OFFSET 4"); + } + + /** + * Note: Only tests one kind of filter and ordering. + */ + @Test + public void generateSelectQuery_filtersAndOrderingSet_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + List<com.vaadin.data.Container.Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 0, 0, null); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM TABLE WHERE \"name\" LIKE ? ORDER BY \"name\" ASC"); + } + + @Test + public void generateSelectQuery_filtersAndOrderingSet_exclusiveFilteringMode_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 0, 0, null); + // TODO + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM TABLE WHERE (\"name\" LIKE ? " + + "OR \"name\" LIKE ?) ORDER BY \"name\" ASC"); + } + + @Test + public void generateDeleteQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = AllTests.sqlGen; + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + + StatementHelper sh = sg.generateDeleteQuery( + "people", + query.getPrimaryKeyColumns(), + null, + (RowItem) container.getItem(container.getItemIds().iterator() + .next())); + Assert.assertEquals("DELETE FROM people WHERE \"ID\" = ?", + sh.getQueryString()); + } + + @Test + public void generateUpdateQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = new DefaultSQLGenerator(); + TableQuery query = new TableQuery("people", connectionPool); + SQLContainer container = new SQLContainer(query); + + RowItem ri = (RowItem) container.getItem(container.getItemIds() + .iterator().next()); + ri.getItemProperty("NAME").setValue("Viljami"); + + StatementHelper sh = sg.generateUpdateQuery("people", ri); + Assert.assertTrue("UPDATE people SET \"NAME\" = ?, \"AGE\" = ? WHERE \"ID\" = ?" + .equals(sh.getQueryString()) + || "UPDATE people SET \"AGE\" = ?, \"NAME\" = ? WHERE \"ID\" = ?" + .equals(sh.getQueryString())); + } + + @Test + public void generateInsertQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = new DefaultSQLGenerator(); + TableQuery query = new TableQuery("people", connectionPool); + SQLContainer container = new SQLContainer(query); + + RowItem ri = (RowItem) container.getItem(container.addItem()); + ri.getItemProperty("NAME").setValue("Viljami"); + + StatementHelper sh = sg.generateInsertQuery("people", ri); + + Assert.assertTrue("INSERT INTO people (\"NAME\", \"AGE\") VALUES (?, ?)" + .equals(sh.getQueryString()) + || "INSERT INTO people (\"AGE\", \"NAME\") VALUES (?, ?)" + .equals(sh.getQueryString())); + } + + @Test + public void generateComplexSelectQuery_forOracle_shouldSucceed() + throws SQLException { + SQLGenerator sg = new OracleGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals( + "SELECT * FROM (SELECT x.*, ROWNUM AS \"rownum\" FROM" + + " (SELECT NAME, ID FROM TABLE WHERE \"name\" LIKE ?" + + " ORDER BY \"name\" ASC) x) WHERE \"rownum\" BETWEEN 5 AND 12", + sh.getQueryString()); + } + + @Test + public void generateComplexSelectQuery_forMSSQL_shouldSucceed() + throws SQLException { + SQLGenerator sg = new MSSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM (SELECT row_number() OVER " + + "( ORDER BY \"name\" ASC) AS rownum, NAME, ID " + + "FROM TABLE WHERE \"name\" LIKE ?) " + + "AS a WHERE a.rownum BETWEEN 5 AND 12"); + } + + @Test + public void generateComplexSelectQuery_forOracle_exclusiveFilteringMode_shouldSucceed() + throws SQLException { + SQLGenerator sg = new OracleGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals( + sh.getQueryString(), + "SELECT * FROM (SELECT x.*, ROWNUM AS \"rownum\" FROM" + + " (SELECT NAME, ID FROM TABLE WHERE (\"name\" LIKE ?" + + " OR \"name\" LIKE ?) " + + "ORDER BY \"name\" ASC) x) WHERE \"rownum\" BETWEEN 5 AND 12"); + } + + @Test + public void generateComplexSelectQuery_forMSSQL_exclusiveFilteringMode_shouldSucceed() + throws SQLException { + SQLGenerator sg = new MSSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM (SELECT row_number() OVER " + + "( ORDER BY \"name\" ASC) AS rownum, NAME, ID " + + "FROM TABLE WHERE (\"name\" LIKE ? " + + "OR \"name\" LIKE ?)) " + + "AS a WHERE a.rownum BETWEEN 5 AND 12"); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java new file mode 100644 index 0000000000..9b38655186 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java @@ -0,0 +1,897 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.RowId; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryDelegate; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; + +public class FreeformQueryTest { + + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void construction_legalParameters_shouldSucceed() { + FreeformQuery ffQuery = new FreeformQuery("SELECT * FROM foo", + Arrays.asList("ID"), connectionPool); + Assert.assertArrayEquals(new Object[] { "ID" }, ffQuery + .getPrimaryKeyColumns().toArray()); + + Assert.assertEquals("SELECT * FROM foo", ffQuery.getQueryString()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyQueryString_shouldFail() { + new FreeformQuery("", Arrays.asList("ID"), connectionPool); + } + + @Test + public void construction_nullPrimaryKeys_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", null, connectionPool); + } + + @Test + public void construction_nullPrimaryKeys2_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", connectionPool); + } + + @Test + public void construction_emptyPrimaryKeys_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", connectionPool); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyStringsInPrimaryKeys_shouldFail() { + new FreeformQuery("SELECT * FROM foo", Arrays.asList(""), + connectionPool); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullConnectionPool_shouldFail() { + new FreeformQuery("SELECT * FROM foo", Arrays.asList("ID"), null); + } + + @Test + public void getCount_simpleQuery_returnsFour() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertEquals(4, query.getCount()); + } + + @Test(expected = SQLException.class) + public void getCount_illegalQuery_shouldThrowSQLException() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM asdf", + Arrays.asList("ID"), connectionPool); + query.getResults(0, 50); + } + + @Test + public void getCount_simpleQueryTwoMorePeopleAdded_returnsSix() + throws SQLException { + // Add some people + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + statement.executeUpdate("insert into people values('Ingvar', 50)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + statement + .executeUpdate("insert into people values(default, 'Ingvar', 50)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + + Assert.assertEquals(6, query.getCount()); + } + + @Test + public void getCount_moreComplexQuery_returnsThree() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + connectionPool, new String[] { "ID" }); + Assert.assertEquals(3, query.getCount()); + } + + @Test + public void getCount_normalState_releasesConnection() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + connectionPool, "ID"); + query.getCount(); + query.getCount(); + Assert.assertNotNull(connectionPool.reserveConnection()); + } + + @Test + public void getCount_delegateRegistered_shouldUseDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getCountQuery()).andReturn( + "SELECT COUNT(*) FROM people WHERE \"NAME\" LIKE '%lle'"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + Assert.assertEquals(3, query.getCount()); + EasyMock.verify(delegate); + } + + @Test + public void getCount_delegateRegisteredZeroRows_returnsZero() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM GARBAGE", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getCountQuery()).andReturn( + "SELECT COUNT(*) FROM GARBAGE"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + Assert.assertEquals(0, query.getCount()); + EasyMock.verify(delegate); + } + + @Test + public void getResults_simpleQuery_returnsFourRecords() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT \"ID\",\"NAME\" FROM people", Arrays.asList("ID"), + connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void getResults_moreComplexQuery_returnsThreeRecords() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void getResults_noDelegate5000Rows_returns5000rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(rs.next()); + } + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test(expected = UnsupportedOperationException.class) + public void setFilters_noDelegate_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + query.setFilters(filters); + } + + @Test(expected = UnsupportedOperationException.class) + public void setOrderBy_noDelegate_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setOrderBy(Arrays.asList(new OrderBy("name", true))); + } + + @Test(expected = IllegalStateException.class) + public void storeRow_noDelegateNoTransactionActive_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.storeRow(new RowItem(new SQLContainer(query), new RowId( + new Object[] { 1 }), null)); + } + + @Test(expected = UnsupportedOperationException.class) + public void storeRow_noDelegate_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(container); + query.beginTransaction(); + query.storeRow(new RowItem(container, new RowId(new Object[] { 1 }), + null)); + query.commit(); + EasyMock.verify(container); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeRow_noDelegate_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(container); + query.beginTransaction(); + query.removeRow(new RowItem(container, new RowId(new Object[] { 1 }), + null)); + query.commit(); + EasyMock.verify(container); + } + + @Test + public void beginTransaction_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + } + + @Test + public void commit_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + query.commit(); + } + + @Test + public void rollback_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_noActiveTransaction_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_noActiveTransaction_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.rollback(); + } + + @Test + public void containsRowWithKeys_simpleQueryWithExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_simpleQueryWithNonexistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertFalse(query.containsRowWithKey(1337)); + } + + // (expected = SQLException.class) + @Test + public void containsRowWithKeys_simpleQueryWithInvalidKeys_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertFalse(query.containsRowWithKey(38796)); + } + + @Test + public void containsRowWithKeys_queryContainingWhereClauseAndExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_queryContainingLowercaseWhereClauseAndExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "select * from people where \"NAME\" like '%lle'", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_nullKeys_shouldFailAndReleaseConnections() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "select * from people where \"NAME\" like '%lle'", + Arrays.asList("ID"), connectionPool); + try { + query.containsRowWithKey(new Object[] { null }); + } catch (SQLException e) { + // We should now be able to reserve two connections + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } + } + + /* + * -------- Tests with a delegate --------- + */ + + @Test + public void setDelegate_noExistingDelegate_shouldRegisterNewDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + query.setDelegate(delegate); + Assert.assertEquals(delegate, query.getDelegate()); + } + + @Test + public void getResults_hasDelegate_shouldCallDelegate() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 0 AND 2"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people) x) WHERE r BETWEEN 1 AND 2"); + } else { + EasyMock.expect(delegate.getQueryString(0, 2)).andReturn( + "SELECT * FROM people LIMIT 2 OFFSET 0"); + } + EasyMock.replay(delegate); + + query.setDelegate(delegate); + query.beginTransaction(); + query.getResults(0, 2); + EasyMock.verify(delegate); + query.commit(); + } + + @Test + public void getResults_delegateImplementsGetQueryString_shouldHonorOffsetAndPagelength() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 0 AND 2"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people) x) WHERE r BETWEEN 1 AND 2"); + } else { + EasyMock.expect(delegate.getQueryString(0, 2)).andReturn( + "SELECT * FROM people LIMIT 2 OFFSET 0"); + } + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + ResultSet rs = query.getResults(0, 2); + int rsoffset = 0; + if (AllTests.db == DB.MSSQL) { + rsoffset++; + } + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1 + rsoffset)); + Assert.assertEquals("Ville", rs.getString(2 + rsoffset)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1 + rsoffset)); + Assert.assertEquals("Kalle", rs.getString(2 + rsoffset)); + + Assert.assertFalse(rs.next()); + + EasyMock.verify(delegate); + query.commit(); + } + + @Test + public void getResults_delegateRegistered5000Rows_returns100rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(200, 100)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 201 AND 300"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(200, 100)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY ID ASC) x) WHERE r BETWEEN 201 AND 300"); + } else { + EasyMock.expect(delegate.getQueryString(200, 100)).andReturn( + "SELECT * FROM people LIMIT 100 OFFSET 200"); + } + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + ResultSet rs = query.getResults(200, 100); + for (int i = 0; i < 100; i++) { + Assert.assertTrue(rs.next()); + Assert.assertEquals(200 + i + offset, rs.getInt("ID")); + } + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void setFilters_delegateImplementsSetFilters_shouldPassFiltersToDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + delegate.setFilters(filters); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setFilters(filters); + + EasyMock.verify(delegate); + } + + @Test(expected = UnsupportedOperationException.class) + public void setFilters_delegateDoesNotImplementSetFilters_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + delegate.setFilters(filters); + EasyMock.expectLastCall().andThrow(new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setFilters(filters); + + EasyMock.verify(delegate); + } + + @Test + public void setOrderBy_delegateImplementsSetOrderBy_shouldPassArgumentsToDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<OrderBy> orderBys = Arrays.asList(new OrderBy("name", false)); + delegate.setOrderBy(orderBys); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setOrderBy(orderBys); + + EasyMock.verify(delegate); + } + + @Test(expected = UnsupportedOperationException.class) + public void setOrderBy_delegateDoesNotImplementSetOrderBy_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<OrderBy> orderBys = Arrays.asList(new OrderBy("name", false)); + delegate.setOrderBy(orderBys); + EasyMock.expectLastCall().andThrow(new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setOrderBy(orderBys); + + EasyMock.verify(delegate); + } + + @Test + public void setFilters_noDelegateAndNullParameter_shouldSucceed() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setFilters(null); + } + + @Test + public void setOrderBy_noDelegateAndNullParameter_shouldSucceed() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setOrderBy(null); + } + + @Test + public void storeRow_delegateImplementsStoreRow_shouldPassToDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andReturn(1); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.storeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test(expected = UnsupportedOperationException.class) + public void storeRow_delegateDoesNotImplementStoreRow_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andThrow( + new UnsupportedOperationException()); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.storeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test + public void removeRow_delegateImplementsRemoveRow_shouldPassToDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andReturn(true); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.removeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeRow_delegateDoesNotImplementRemoveRow_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andThrow( + new UnsupportedOperationException()); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.removeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test + public void beginTransaction_delegateRegistered_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + } + + @Test(expected = IllegalStateException.class) + public void beginTransaction_transactionAlreadyActive_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + + query.beginTransaction(); + query.beginTransaction(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredNoActiveTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.commit(); + } + + @Test + public void commit_delegateRegisteredActiveTransaction_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredActiveTransactionDoubleCommit_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredNoActiveTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.rollback(); + } + + @Test + public void rollback_delegateRegisteredActiveTransaction_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredActiveTransactionDoubleRollback_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredCommittedTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredRollbackedTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void containsRowWithKeys_delegateRegistered_shouldCallGetContainsRowQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE name LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getContainsRowQueryString(1)).andReturn(""); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.containsRowWithKey(1); + + EasyMock.verify(delegate); + } + + @Test + public void containsRowWithKeys_delegateRegistered_shouldUseResultFromGetContainsRowQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + // In order to test that this is the query that is actually used, we use + // a non-existing id in place of the existing one. + EasyMock.expect(delegate.getContainsRowQueryString(1)) + .andReturn( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle' AND \"ID\" = 1337"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + // The id (key) used should be 1337 as above, for the call with key = 1 + Assert.assertFalse(query.containsRowWithKey(1)); + + EasyMock.verify(delegate); + } + + @Test + public void containsRowWithKeys_delegateRegisteredGetContainsRowQueryStringNotImplemented_shouldBuildQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getContainsRowQueryString(1)).andThrow( + new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + Assert.assertTrue(query.containsRowWithKey(1)); + + EasyMock.verify(delegate); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java new file mode 100644 index 0000000000..f635b23ebd --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java @@ -0,0 +1,311 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.util.ArrayList; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.And; +import com.vaadin.data.util.filter.Between; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Compare.Greater; +import com.vaadin.data.util.filter.Compare.GreaterOrEqual; +import com.vaadin.data.util.filter.Compare.Less; +import com.vaadin.data.util.filter.Compare.LessOrEqual; +import com.vaadin.data.util.filter.IsNull; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.filter.Not; +import com.vaadin.data.util.filter.Or; +import com.vaadin.data.util.filter.SimpleStringFilter; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.StringDecorator; + +public class QueryBuilderTest { + + private StatementHelper mockedStatementHelper(Object... values) { + StatementHelper sh = EasyMock.createMock(StatementHelper.class); + for (Object val : values) { + sh.addParameterValue(val); + EasyMock.expectLastCall(); + } + EasyMock.replay(sh); + return sh; + } + + // escape bad characters and wildcards + + @Test + public void getWhereStringForFilter_equals() { + StatementHelper sh = mockedStatementHelper("Fido"); + Equal f = new Equal("NAME", "Fido"); + Assert.assertEquals("\"NAME\" = ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_greater() { + StatementHelper sh = mockedStatementHelper(18); + Greater f = new Greater("AGE", 18); + Assert.assertEquals("\"AGE\" > ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_less() { + StatementHelper sh = mockedStatementHelper(65); + Less f = new Less("AGE", 65); + Assert.assertEquals("\"AGE\" < ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_greaterOrEqual() { + StatementHelper sh = mockedStatementHelper(18); + GreaterOrEqual f = new GreaterOrEqual("AGE", 18); + Assert.assertEquals("\"AGE\" >= ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_lessOrEqual() { + StatementHelper sh = mockedStatementHelper(65); + LessOrEqual f = new LessOrEqual("AGE", 65); + Assert.assertEquals("\"AGE\" <= ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilter() { + StatementHelper sh = mockedStatementHelper("Vi%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", false, true); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilterMatchAnywhere() { + StatementHelper sh = mockedStatementHelper("%Vi%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", false, + false); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilterMatchAnywhereIgnoreCase() { + StatementHelper sh = mockedStatementHelper("%VI%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", true, false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_startsWith() { + StatementHelper sh = mockedStatementHelper("Vi%"); + Like f = new Like("NAME", "Vi%"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_startsWithNumber() { + StatementHelper sh = mockedStatementHelper("1%"); + Like f = new Like("AGE", "1%"); + Assert.assertEquals("\"AGE\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_endsWith() { + StatementHelper sh = mockedStatementHelper("%lle"); + Like f = new Like("NAME", "%lle"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_contains() { + StatementHelper sh = mockedStatementHelper("%ill%"); + Like f = new Like("NAME", "%ill%"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_between() { + StatementHelper sh = mockedStatementHelper(18, 65); + Between f = new Between("AGE", 18, 65); + Assert.assertEquals("\"AGE\" BETWEEN ? AND ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_equals() { + StatementHelper sh = mockedStatementHelper("FIDO"); + Like f = new Like("NAME", "Fido"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_startsWith() { + StatementHelper sh = mockedStatementHelper("VI%"); + Like f = new Like("NAME", "Vi%"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_endsWith() { + StatementHelper sh = mockedStatementHelper("%LLE"); + Like f = new Like("NAME", "%lle"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_contains() { + StatementHelper sh = mockedStatementHelper("%ILL%"); + Like f = new Like("NAME", "%ill%"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_listOfFilters() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("NAME", "%lle")); + filters.add(new Greater("AGE", 18)); + Assert.assertEquals(" WHERE \"NAME\" LIKE ? AND \"AGE\" > ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_oneAndFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new And(new Like("NAME", "%lle"), new Greater("AGE", 18))); + Assert.assertEquals(" WHERE (\"NAME\" LIKE ? AND \"AGE\" > ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_oneOrFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new Like("NAME", "%lle"), new Greater("AGE", 18))); + Assert.assertEquals(" WHERE (\"NAME\" LIKE ? OR \"AGE\" > ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexCompoundFilters() { + StatementHelper sh = mockedStatementHelper("%lle", 18, 65, "Pelle"); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new And(new Like("NAME", "%lle"), new Or(new Less( + "AGE", 18), new Greater("AGE", 65))), + new Equal("NAME", "Pelle"))); + Assert.assertEquals( + " WHERE ((\"NAME\" LIKE ? AND (\"AGE\" < ? OR \"AGE\" > ?)) OR \"NAME\" = ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexCompoundFiltersAndSingleFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18, 65, "Pelle", + "Virtanen"); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new And(new Like("NAME", "%lle"), new Or(new Less( + "AGE", 18), new Greater("AGE", 65))), + new Equal("NAME", "Pelle"))); + filters.add(new Equal("LASTNAME", "Virtanen")); + Assert.assertEquals( + " WHERE ((\"NAME\" LIKE ? AND (\"AGE\" < ? OR \"AGE\" > ?)) OR \"NAME\" = ?) AND \"LASTNAME\" = ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_emptyList_shouldReturnEmptyString() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + Assert.assertEquals("", QueryBuilder.getWhereStringForFilters(filters, + new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_NotFilter() { + StatementHelper sh = mockedStatementHelper(18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new Equal("AGE", 18))); + Assert.assertEquals(" WHERE NOT \"AGE\" = ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexNegatedFilter() { + StatementHelper sh = mockedStatementHelper(65, 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new Or(new Equal("AGE", 65), new Equal("AGE", 18)))); + Assert.assertEquals(" WHERE NOT (\"AGE\" = ? OR \"AGE\" = ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_isNull() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new IsNull("NAME")); + Assert.assertEquals(" WHERE \"NAME\" IS NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_isNotNull() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new IsNull("NAME"))); + Assert.assertEquals(" WHERE \"NAME\" IS NOT NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_customStringDecorator() { + QueryBuilder.setStringDecorator(new StringDecorator("[", "]")); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new IsNull("NAME"))); + Assert.assertEquals(" WHERE [NAME] IS NOT NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + // Reset the default string decorator + QueryBuilder.setStringDecorator(new StringDecorator("\"", "\"")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java new file mode 100644 index 0000000000..e135894013 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java @@ -0,0 +1,663 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.OptimisticLockException; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; + +public class TableQueryTest { + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + /********************************************************************** + * TableQuery construction tests + **********************************************************************/ + @Test + public void construction_legalParameters_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + new DefaultSQLGenerator()); + Assert.assertArrayEquals(new Object[] { "ID" }, tQuery + .getPrimaryKeyColumns().toArray()); + boolean correctTableName = "people".equalsIgnoreCase(tQuery + .getTableName()); + Assert.assertTrue(correctTableName); + } + + @Test + public void construction_legalParameters_defaultGenerator_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertArrayEquals(new Object[] { "ID" }, tQuery + .getPrimaryKeyColumns().toArray()); + boolean correctTableName = "people".equalsIgnoreCase(tQuery + .getTableName()); + Assert.assertTrue(correctTableName); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nonExistingTableName_shouldFail() { + new TableQuery("skgwaguhsd", connectionPool, new DefaultSQLGenerator()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyTableName_shouldFail() { + new TableQuery("", connectionPool, new DefaultSQLGenerator()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullSqlGenerator_shouldFail() { + new TableQuery("people", connectionPool, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullConnectionPool_shouldFail() { + new TableQuery("people", null, new DefaultSQLGenerator()); + } + + /********************************************************************** + * TableQuery row count tests + **********************************************************************/ + @Test + public void getCount_simpleQuery_returnsFour() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertEquals(4, tQuery.getCount()); + } + + @Test + public void getCount_simpleQueryTwoMorePeopleAdded_returnsSix() + throws SQLException { + // Add some people + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + statement.executeUpdate("insert into people values('Ingvar', 50)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + statement + .executeUpdate("insert into people values(default, 'Ingvar', 50)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + Assert.assertEquals(6, tQuery.getCount()); + } + + @Test + public void getCount_normalState_releasesConnection() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.getCount(); + tQuery.getCount(); + Assert.assertNotNull(connectionPool.reserveConnection()); + } + + /********************************************************************** + * TableQuery get results tests + **********************************************************************/ + @Test + public void getResults_simpleQuery_returnsFourRecords() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + ResultSet rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void getResults_noDelegate5000Rows_returns5000rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + tQuery.beginTransaction(); + ResultSet rs = tQuery.getResults(0, 0); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(rs.next()); + } + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + /********************************************************************** + * TableQuery transaction management tests + **********************************************************************/ + @Test + public void beginTransaction_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + } + + @Test(expected = IllegalStateException.class) + public void beginTransaction_transactionAlreadyActive_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + tQuery.beginTransaction(); + tQuery.beginTransaction(); + } + + @Test + public void commit_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + tQuery.commit(); + } + + @Test + public void rollback_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + tQuery.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_noActiveTransaction_shouldFail() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_noActiveTransaction_shouldFail() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.rollback(); + } + + /********************************************************************** + * TableQuery row query with given keys tests + **********************************************************************/ + @Test + public void containsRowWithKeys_existingKeys_returnsTrue() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertTrue(tQuery.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_nonexistingKeys_returnsTrue() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + Assert.assertFalse(tQuery.containsRowWithKey(1337)); + } + + @Test + public void containsRowWithKeys_invalidKeys_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + boolean b = true; + try { + b = tQuery.containsRowWithKey("foo"); + } catch (SQLException se) { + return; + } + Assert.assertFalse(b); + } + + @Test + public void containsRowWithKeys_nullKeys_shouldFailAndReleaseConnections() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + try { + tQuery.containsRowWithKey(new Object[] { null }); + org.junit.Assert + .fail("null should throw an IllegalArgumentException from StatementHelper"); + } catch (IllegalArgumentException e) { + // We should now be able to reserve two connections + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } + } + + /********************************************************************** + * TableQuery filtering and ordering tests + **********************************************************************/ + @Test + public void setFilters_shouldReturnCorrectCount() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("NAME", "%lle")); + tQuery.setFilters(filters); + Assert.assertEquals(3, tQuery.getCount()); + } + + @Test + public void setOrderByNameAscending_shouldReturnCorrectOrder() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + List<OrderBy> orderBys = Arrays.asList(new OrderBy("NAME", true)); + tQuery.setOrderBy(orderBys); + + tQuery.beginTransaction(); + ResultSet rs; + rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void setOrderByNameDescending_shouldReturnCorrectOrder() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + List<OrderBy> orderBys = Arrays.asList(new OrderBy("NAME", false)); + tQuery.setOrderBy(orderBys); + + tQuery.beginTransaction(); + ResultSet rs; + rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void setFilters_nullParameter_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setFilters(null); + } + + @Test + public void setOrderBy_nullParameter_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setOrderBy(null); + } + + /********************************************************************** + * TableQuery row removal tests + **********************************************************************/ + @Test + public void removeRowThroughContainer_legalRowItem_shouldSucceed() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + Assert.assertTrue(container.removeItem(container.getItemIds() + .iterator().next())); + + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(3, container.size()); + container.commit(); + + Assert.assertEquals(3, tQuery.getCount()); + Assert.assertEquals(3, container.size()); + } + + @Test + public void removeRowThroughContainer_nonexistingRowId_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(true); + Assert.assertFalse(container.removeItem("foo")); + } + + /********************************************************************** + * TableQuery row adding / modification tests + **********************************************************************/ + @Test + public void insertRowThroughContainer_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("ID"); + + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + + Object item = container.addItem(); + Assert.assertNotNull(item); + + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(5, container.size()); + container.commit(); + + Assert.assertEquals(5, tQuery.getCount()); + Assert.assertEquals(5, container.size()); + } + + @Test + public void modifyRowThroughContainer_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + // In this test the primary key is used as a version column + tQuery.setVersionColumn("ID"); + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + + /* Check that the container size is correct and there is no 'Viljami' */ + Assert.assertEquals(4, container.size()); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Equal("NAME", "Viljami")); + tQuery.setFilters(filters); + Assert.assertEquals(0, tQuery.getCount()); + tQuery.setFilters(null); + + /* Fetch first item, modify and commit */ + Object item = container.getItem(container.getItemIds().iterator() + .next()); + Assert.assertNotNull(item); + + RowItem ri = (RowItem) item; + Assert.assertNotNull(ri.getItemProperty("NAME")); + ri.getItemProperty("NAME").setValue("Viljami"); + + container.commit(); + + // Check that the size is still correct and only 1 'Viljami' is found + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(4, container.size()); + tQuery.setFilters(filters); + Assert.assertEquals(1, tQuery.getCount()); + } + + @Test + public void storeRow_noVersionColumn_shouldSucceed() + throws UnsupportedOperationException, SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(tQuery); + Object id = container.addItem(); + RowItem row = (RowItem) container.getItem(id); + row.getItemProperty("NAME").setValue("R2D2"); + row.getItemProperty("AGE").setValue(123); + tQuery.beginTransaction(); + tQuery.storeRow(row); + tQuery.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM PEOPLE WHERE \"NAME\" = ?"); + stmt.setString(1, "R2D2"); + ResultSet rs = stmt.executeQuery(); + Assert.assertTrue(rs.next()); + rs.close(); + stmt.close(); + connectionPool.releaseConnection(conn); + } + + @Test + public void storeRow_versionSetAndEqualToDBValue_shouldSucceed() + throws SQLException { + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + row.getItemProperty("TEXT").setValue("asdf"); + container.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM VERSIONED WHERE \"TEXT\" = ?"); + stmt.setString(1, "asdf"); + ResultSet rs = stmt.executeQuery(); + Assert.assertTrue(rs.next()); + rs.close(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + @Test(expected = OptimisticLockException.class) + public void storeRow_versionSetAndLessThanDBValue_shouldThrowException() + throws SQLException { + if (AllTests.db == DB.HSQLDB) { + throw new OptimisticLockException( + "HSQLDB doesn't support row versioning for optimistic locking - don't run this test.", + null); + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + row.getItemProperty("TEXT").setValue("asdf"); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "foo"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + container.commit(); + } + + @Test + public void removeRow_versionSetAndEqualToDBValue_shouldSucceed() + throws SQLException { + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + container.removeItem(container.firstItemId()); + container.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM VERSIONED WHERE \"TEXT\" = ?"); + stmt.setString(1, "Junk"); + ResultSet rs = stmt.executeQuery(); + Assert.assertFalse(rs.next()); + rs.close(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + @Test(expected = OptimisticLockException.class) + public void removeRow_versionSetAndLessThanDBValue_shouldThrowException() + throws SQLException { + if (AllTests.db == AllTests.DB.HSQLDB) { + // HSQLDB doesn't support versioning, so this is to make the test + // green. + throw new OptimisticLockException(null); + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "asdf"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + container.removeItem(container.firstItemId()); + container.commit(); + } + + @Test + public void removeRow_throwsOptimisticLockException_shouldStillWork() + throws SQLException { + if (AllTests.db == AllTests.DB.HSQLDB) { + // HSQLDB doesn't support versioning, so this is to make the test + // green. + return; + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "asdf"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + Object itemToRemove = container.firstItemId(); + try { + container.removeItem(itemToRemove); + container.commit(); + } catch (OptimisticLockException e) { + // This is expected, refresh and try again. + container.rollback(); + container.removeItem(itemToRemove); + container.commit(); + } + Object id = container.addItem(); + RowItem item = (RowItem) container.getItem(id); + item.getItemProperty("TEXT").setValue("foo"); + container.commit(); + } + +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/server/JSONSerializerTest.java b/server/tests/src/com/vaadin/server/JSONSerializerTest.java new file mode 100644 index 0000000000..05139e6f1a --- /dev/null +++ b/server/tests/src/com/vaadin/server/JSONSerializerTest.java @@ -0,0 +1,140 @@ +package com.vaadin.server; + +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import com.vaadin.server.JsonCodec.BeanProperty; +import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState; + +/** + * Tests for {@link JsonCodec} + * + * @author Vaadin Ltd + * @since 7.0 + * + */ +public class JSONSerializerTest extends TestCase { + HashMap<String, AbstractSplitPanelState> stringToStateMap; + HashMap<AbstractSplitPanelState, String> stateToStringMap; + + public void testStringToBeanMapSerialization() throws Exception { + Type mapType = getClass().getDeclaredField("stringToStateMap") + .getGenericType(); + stringToStateMap = new HashMap<String, AbstractSplitPanelState>(); + AbstractSplitPanelState s = new AbstractSplitPanelState(); + AbstractSplitPanelState s2 = new AbstractSplitPanelState(); + s.setCaption("State 1"); + s.setId("foo"); + s2.setCaption("State 2"); + s2.setId("bar"); + stringToStateMap.put("string - state 1", s); + stringToStateMap.put("String - state 2", s2); + + Object encodedMap = JsonCodec.encode(stringToStateMap, null, mapType, + null).getEncodedValue(); + + ensureDecodedCorrectly(stringToStateMap, encodedMap, mapType); + } + + public void testBeanToStringMapSerialization() throws Exception { + Type mapType = getClass().getDeclaredField("stateToStringMap") + .getGenericType(); + stateToStringMap = new HashMap<AbstractSplitPanelState, String>(); + AbstractSplitPanelState s = new AbstractSplitPanelState(); + AbstractSplitPanelState s2 = new AbstractSplitPanelState(); + s.setCaption("State 1"); + s2.setCaption("State 2"); + stateToStringMap.put(s, "string - state 1"); + stateToStringMap.put(s2, "String - state 2"); + + Object encodedMap = JsonCodec.encode(stateToStringMap, null, mapType, + null).getEncodedValue(); + + ensureDecodedCorrectly(stateToStringMap, encodedMap, mapType); + } + + private void ensureDecodedCorrectly(Object original, Object encoded, + Type type) throws Exception { + Object serverSideDecoded = JsonCodec.decodeInternalOrCustomType(type, + encoded, null); + assertTrue("Server decoded", equals(original, serverSideDecoded)); + + } + + private boolean equals(Object o1, Object o2) throws Exception { + if (o1 == null) { + return (o2 == null); + } + if (o2 == null) { + return false; + } + + if (o1 instanceof Map) { + if (!(o2 instanceof Map)) { + return false; + } + return equalsMap((Map) o1, (Map) o2); + } + + if (o1.getClass() != o2.getClass()) { + return false; + } + + if (o1 instanceof Collection || o1 instanceof Number + || o1 instanceof String) { + return o1.equals(o2); + } + + return equalsBean(o1, o2); + } + + private boolean equalsBean(Object o1, Object o2) throws Exception { + for (BeanProperty property : JsonCodec.getProperties(o1.getClass())) { + Object c1 = property.getValue(o1); + Object c2 = property.getValue(o2); + if (!equals(c1, c2)) { + return false; + } + } + return true; + } + + private boolean equalsMap(Map o1, Map o2) throws Exception { + for (Object key1 : o1.keySet()) { + Object key2 = key1; + if (!(o2.containsKey(key2))) { + // Try to fins a key that is equal + for (Object k2 : o2.keySet()) { + if (equals(key1, k2)) { + key2 = k2; + break; + } + } + } + if (!equals(o1.get(key1), o2.get(key2))) { + return false; + } + + } + return true; + } +} diff --git a/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java new file mode 100644 index 0000000000..df16e98bba --- /dev/null +++ b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java @@ -0,0 +1,205 @@ +package com.vaadin.server; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + +import com.vaadin.server.AbstractApplicationServlet; +import com.vaadin.server.ApplicationServlet; + +import junit.framework.TestCase; + +public class TestAbstractApplicationServletStaticFilesLocation extends TestCase { + + ApplicationServlet servlet; + + private Method getStaticFilesLocationMethod; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + servlet = new ApplicationServlet(); + + // Workaround to avoid calling init and creating servlet config + Field f = AbstractApplicationServlet.class + .getDeclaredField("applicationProperties"); + f.setAccessible(true); + f.set(servlet, new Properties()); + + getStaticFilesLocationMethod = AbstractApplicationServlet.class + .getDeclaredMethod( + "getStaticFilesLocation", + new Class[] { javax.servlet.http.HttpServletRequest.class }); + getStaticFilesLocationMethod.setAccessible(true); + + } + + public class DummyServletConfig implements ServletConfig { + + // public DummyServletConfig(Map<String,String> initParameters, ) + @Override + public String getInitParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration<Object> getInitParameterNames() { + return new Enumeration<Object>() { + + @Override + public boolean hasMoreElements() { + return false; + } + + @Override + public Object nextElement() { + return null; + } + }; + } + + @Override + public ServletContext getServletContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletName() { + // TODO Auto-generated method stub + return null; + } + + } + + public void testWidgetSetLocation() throws Exception { + String location; + + /* SERVLETS */ + // http://dummy.host:8080/contextpath/servlet + // should return /contextpath + location = testLocation("http://dummy.host:8080", "/contextpath", + "/servlet", ""); + assertEquals("/contextpath", location); + + // http://dummy.host:8080/servlet + // should return "" + location = testLocation("http://dummy.host:8080", "", "/servlet", ""); + assertEquals("", location); + + // http://dummy.host/contextpath/servlet/extra/stuff + // should return /contextpath + location = testLocation("http://dummy.host", "/contextpath", + "/servlet", "/extra/stuff"); + assertEquals("/contextpath", location); + + // http://dummy.host/context/path/servlet/extra/stuff + // should return /context/path + location = testLocation("http://dummy.host", "/context/path", + "/servlet", "/extra/stuff"); + assertEquals("/context/path", location); + + /* Include requests */ + location = testIncludedLocation("http://my.portlet.server", "/user", + "/tmpservletlocation1", ""); + assertEquals("Wrong widgetset location", "/user", location); + + } + + private String testLocation(String base, String contextPath, + String servletPath, String pathInfo) throws Exception { + + HttpServletRequest request = createNonIncludeRequest(base, contextPath, + servletPath, pathInfo); + // Set request into replay mode + replay(request); + + String location = (String) getStaticFilesLocationMethod.invoke(servlet, + request); + return location; + } + + private String testIncludedLocation(String base, String portletContextPath, + String servletPath, String pathInfo) throws Exception { + + HttpServletRequest request = createIncludeRequest(base, + portletContextPath, servletPath, pathInfo); + // Set request into replay mode + replay(request); + + String location = (String) getStaticFilesLocationMethod.invoke(servlet, + request); + return location; + } + + private HttpServletRequest createIncludeRequest(String base, + String realContextPath, String realServletPath, String pathInfo) + throws Exception { + HttpServletRequest request = createRequest(base, "", "", pathInfo); + expect(request.getAttribute("javax.servlet.include.context_path")) + .andReturn(realContextPath).anyTimes(); + expect(request.getAttribute("javax.servlet.include.servlet_path")) + .andReturn(realServletPath).anyTimes(); + + return request; + } + + private HttpServletRequest createNonIncludeRequest(String base, + String realContextPath, String realServletPath, String pathInfo) + throws Exception { + HttpServletRequest request = createRequest(base, realContextPath, + realServletPath, pathInfo); + expect(request.getAttribute("javax.servlet.include.context_path")) + .andReturn(null).anyTimes(); + expect(request.getAttribute("javax.servlet.include.servlet_path")) + .andReturn(null).anyTimes(); + + return request; + } + + /** + * Creates a HttpServletRequest mock using the supplied parameters. + * + * @param base + * The base url, e.g. http://localhost:8080 + * @param contextPath + * The context path where the application is deployed, e.g. + * /mycontext + * @param servletPath + * The servlet path to the servlet we are testing, e.g. /myapp + * @param pathInfo + * Any text following the servlet path in the request, not + * including query parameters, e.g. /UIDL/ + * @return A mock HttpServletRequest object useful for testing + * @throws MalformedURLException + */ + private HttpServletRequest createRequest(String base, String contextPath, + String servletPath, String pathInfo) throws MalformedURLException { + URL url = new URL(base + contextPath + pathInfo); + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.isSecure()).andReturn( + url.getProtocol().equalsIgnoreCase("https")).anyTimes(); + expect(request.getServerName()).andReturn(url.getHost()).anyTimes(); + expect(request.getServerPort()).andReturn(url.getPort()).anyTimes(); + expect(request.getRequestURI()).andReturn(url.getPath()).anyTimes(); + expect(request.getContextPath()).andReturn(contextPath).anyTimes(); + expect(request.getPathInfo()).andReturn(pathInfo).anyTimes(); + expect(request.getServletPath()).andReturn(servletPath).anyTimes(); + + return request; + } + +} diff --git a/server/tests/src/com/vaadin/tests/VaadinClasses.java b/server/tests/src/com/vaadin/tests/VaadinClasses.java new file mode 100644 index 0000000000..15e1283e47 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/VaadinClasses.java @@ -0,0 +1,257 @@ +package com.vaadin.tests; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.JarURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; + +import com.vaadin.Application; +import com.vaadin.ui.Component; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.Field; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.LoginForm; +import com.vaadin.ui.PopupView; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalSplitPanel; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.BaseTheme; + +import org.junit.Test; + +@SuppressWarnings("deprecation") +public class VaadinClasses { + + public static void main(String[] args) { + System.out.println("ComponentContainers"); + System.out.println("==================="); + for (Class<? extends ComponentContainer> c : getComponentContainers()) { + System.out.println(c.getName()); + } + System.out.println(); + System.out.println("Components"); + System.out.println("=========="); + for (Class<? extends Component> c : getComponents()) { + System.out.println(c.getName()); + } + System.out.println(); + System.out.println("Server side classes"); + System.out.println("==================="); + for (Class<?> c : getAllServerSideClasses()) { + System.out.println(c.getName()); + } + } + + public static List<Class<? extends Component>> getComponents() { + try { + return findClasses(Component.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends Field>> getFields() { + try { + return findClasses(Field.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends BaseTheme>> getThemeClasses() { + try { + return findClasses(BaseTheme.class, "com.vaadin.ui.themes"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends Object>> getAllServerSideClasses() { + try { + return findClassesNoTests(Object.class, "com.vaadin", new String[] { + "com.vaadin.tests", "com.vaadin.client" }); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends ComponentContainer>> getComponentContainers() { + try { + return findClasses(ComponentContainer.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingAddRemoveComponent() { + List<Class<? extends ComponentContainer>> classes = getComponentContainers(); + classes.remove(PopupView.class); + classes.remove(CustomComponent.class); + classes.remove(DragAndDropWrapper.class); + classes.remove(CustomComponent.class); + classes.remove(LoginForm.class); + classes.remove(UI.class); + + return classes; + } + + public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingUnlimitedNumberOfComponents() { + List<Class<? extends ComponentContainer>> classes = getComponentContainersSupportingAddRemoveComponent(); + classes.remove(VerticalSplitPanel.class); + classes.remove(HorizontalSplitPanel.class); + classes.remove(Window.class); + + return classes; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static List<Class<?>> getBasicComponentTests() { + try { + // Given as name to avoid dependencies on testbench source folder + return (List) findClasses( + Class.forName("com.vaadin.tests.components.AbstractComponentTest"), + "com.vaadin.tests.components"); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass, + String basePackage) throws IOException { + return findClasses(baseClass, basePackage, new String[] {}); + } + + private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass, + String basePackage, String[] ignoredPackages) throws IOException { + List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>(); + String basePackageDirName = "/" + basePackage.replace('.', '/'); + URL location = Application.class.getResource(basePackageDirName); + if (location.getProtocol().equals("file")) { + try { + File f = new File(location.toURI()); + if (!f.exists()) { + throw new IOException("Directory " + f.toString() + + " does not exist"); + } + findPackages(f, basePackage, baseClass, classes, + ignoredPackages); + } catch (URISyntaxException e) { + throw new IOException(e.getMessage()); + } + } else if (location.getProtocol().equals("jar")) { + JarURLConnection juc = (JarURLConnection) location.openConnection(); + findPackages(juc, basePackage, baseClass, classes); + } + + Collections.sort(classes, new Comparator<Class<? extends T>>() { + + @Override + public int compare(Class<? extends T> o1, Class<? extends T> o2) { + return o1.getName().compareTo(o2.getName()); + } + + }); + return classes; + } + + private static <T> List<Class<? extends T>> findClassesNoTests( + Class<T> baseClass, String basePackage, String[] ignoredPackages) + throws IOException { + List<Class<? extends T>> classes = findClasses(baseClass, basePackage, + ignoredPackages); + List<Class<? extends T>> classesNoTests = new ArrayList<Class<? extends T>>(); + for (Class<? extends T> clazz : classes) { + if (!clazz.getName().contains("Test")) { + boolean testPresent = false; + for (Method method : clazz.getMethods()) { + if (method.isAnnotationPresent(Test.class)) { + testPresent = true; + break; + } + } + if (!testPresent) { + classesNoTests.add(clazz); + } + } + } + return classesNoTests; + } + + private static <T> void findPackages(JarURLConnection juc, + String javaPackage, Class<T> baseClass, + Collection<Class<? extends T>> result) throws IOException { + String prefix = "com/vaadin/ui"; + Enumeration<JarEntry> ent = juc.getJarFile().entries(); + while (ent.hasMoreElements()) { + JarEntry e = ent.nextElement(); + if (e.getName().endsWith(".class") + && e.getName().startsWith(prefix)) { + String fullyQualifiedClassName = e.getName().replace('/', '.') + .replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + } + + private static <T> void findPackages(File parent, String javaPackage, + Class<T> baseClass, Collection<Class<? extends T>> result, + String[] ignoredPackages) { + for (String ignoredPackage : ignoredPackages) { + if (javaPackage.equals(ignoredPackage)) { + return; + } + } + + for (File file : parent.listFiles()) { + if (file.isDirectory()) { + findPackages(file, javaPackage + "." + file.getName(), + baseClass, result, ignoredPackages); + } else if (file.getName().endsWith(".class")) { + String fullyQualifiedClassName = javaPackage + "." + + file.getName().replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + + } + + @SuppressWarnings("unchecked") + private static <T> void addClassIfMatches( + Collection<Class<? extends T>> result, + String fullyQualifiedClassName, Class<T> baseClass) { + try { + // Try to load the class + + Class<?> c = Class.forName(fullyQualifiedClassName); + if (baseClass.isAssignableFrom(c) + && !Modifier.isAbstract(c.getModifiers())) { + result.add((Class<? extends T>) c); + } + } catch (Exception e) { + // Could ignore that class cannot be loaded + e.printStackTrace(); + } catch (LinkageError e) { + // Ignore. Client side classes will at least throw LinkageErrors + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Address.java b/server/tests/src/com/vaadin/tests/data/bean/Address.java new file mode 100644 index 0000000000..15cdf34ae5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Address.java @@ -0,0 +1,63 @@ +package com.vaadin.tests.data.bean; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class Address implements Serializable { + + private String streetAddress = ""; + private Integer postalCode = null; + private String city = ""; + private Country country = null; + + public Address() { + + } + + public Address(String streetAddress, int postalCode, String city, + Country country) { + setStreetAddress(streetAddress); + setPostalCode(postalCode); + setCity(city); + setCountry(country); + } + + @Override + public String toString() { + return "Address [streetAddress=" + streetAddress + ", postalCode=" + + postalCode + ", city=" + city + ", country=" + country + "]"; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public Integer getPostalCode() { + return postalCode; + } + + public void setPostalCode(Integer postalCode) { + this.postalCode = postalCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Country getCountry() { + return country; + } + + public void setCountry(Country country) { + this.country = country; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java b/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java new file mode 100644 index 0000000000..416563baba --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java @@ -0,0 +1,56 @@ +package com.vaadin.tests.data.bean; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class BeanToValidate { + @NotNull + @Size(min = 3, max = 16) + private String firstname; + + @NotNull(message = "Last name must not be empty") + private String lastname; + + @Min(value = 18, message = "Must be 18 or above") + @Max(150) + private int age; + + @Digits(integer = 3, fraction = 2) + private String decimals; + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getDecimals() { + return decimals; + } + + public void setDecimals(String decimals) { + this.decimals = decimals; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Country.java b/server/tests/src/com/vaadin/tests/data/bean/Country.java new file mode 100644 index 0000000000..afdf8dcfa1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Country.java @@ -0,0 +1,18 @@ +package com.vaadin.tests.data.bean; + +public enum Country { + + FINLAND("Finland"), SWEDEN("Sweden"), USA("USA"), RUSSIA("Russia"), NETHERLANDS( + "Netherlands"), SOUTH_AFRICA("South Africa"); + + private String name; + + private Country(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Person.java b/server/tests/src/com/vaadin/tests/data/bean/Person.java new file mode 100644 index 0000000000..f7bad31d0e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Person.java @@ -0,0 +1,143 @@ +package com.vaadin.tests.data.bean; + +import java.math.BigDecimal; +import java.util.Date; + +public class Person { + private String firstName; + private String lastName; + private String email; + private int age; + private Sex sex; + private Address address; + private boolean deceased; + private Date birthDate; + + private Integer salary; // null if unknown + private Double salaryDouble; // null if unknown + + private BigDecimal rent; + + public Person() { + + } + + @Override + public String toString() { + return "Person [firstName=" + firstName + ", lastName=" + lastName + + ", email=" + email + ", age=" + age + ", sex=" + sex + + ", address=" + address + ", deceased=" + deceased + + ", salary=" + salary + ", salaryDouble=" + salaryDouble + + ", rent=" + rent + "]"; + } + + public Person(String firstName, String lastName, String email, int age, + Sex sex, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean getDeceased() { + return deceased; + } + + public void setDeceased(boolean deceased) { + this.deceased = deceased; + } + + public Integer getSalary() { + return salary; + } + + public void setSalary(Integer salary) { + this.salary = salary; + } + + public BigDecimal getRent() { + return rent; + } + + public void setRent(BigDecimal rent) { + this.rent = rent; + } + + public Double getSalaryDouble() { + return salaryDouble; + } + + public void setSalaryDouble(Double salaryDouble) { + this.salaryDouble = salaryDouble; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public static Person createTestPerson1() { + return new Person("Foo", "Bar", "yeah@cool.com", 46, Sex.MALE, + new Address("Street", 1123, "Turku", Country.FINLAND)); + } + + public static Person createTestPerson2() { + return new Person("Maya", "Dinkelstein", "maya@foo.bar", 18, + Sex.FEMALE, new Address("Red street", 12, "Amsterdam", + Country.NETHERLANDS)); + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java b/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java new file mode 100644 index 0000000000..93b2273263 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java @@ -0,0 +1,156 @@ +package com.vaadin.tests.data.bean; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; +import javax.validation.constraints.Size; + +public class PersonWithBeanValidationAnnotations { + @NotNull + @Size(min = 5, max = 20) + private String firstName; + @NotNull + private String lastName; + + private String email; + + @Min(0) + @Max(100) + private int age; + + @NotNull + private Sex sex; + + private Address address; + private boolean deceased; + + @NotNull + @Past + private Date birthDate; + + @Min(0) + private Integer salary; // null if unknown + + @Digits(integer = 6, fraction = 2) + private Double salaryDouble; // null if unknown + + private BigDecimal rent; + + public PersonWithBeanValidationAnnotations() { + + } + + @Override + public String toString() { + return "Person [firstName=" + firstName + ", lastName=" + lastName + + ", email=" + email + ", age=" + age + ", sex=" + sex + + ", address=" + address + ", deceased=" + deceased + + ", salary=" + salary + ", salaryDouble=" + salaryDouble + + ", rent=" + rent + "]"; + } + + public PersonWithBeanValidationAnnotations(String firstName, + String lastName, String email, int age, Sex sex, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean getDeceased() { + return deceased; + } + + public void setDeceased(boolean deceased) { + this.deceased = deceased; + } + + public Integer getSalary() { + return salary; + } + + public void setSalary(Integer salary) { + this.salary = salary; + } + + public BigDecimal getRent() { + return rent; + } + + public void setRent(BigDecimal rent) { + this.rent = rent; + } + + public Double getSalaryDouble() { + return salaryDouble; + } + + public void setSalaryDouble(Double salaryDouble) { + this.salaryDouble = salaryDouble; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Sex.java b/server/tests/src/com/vaadin/tests/data/bean/Sex.java new file mode 100644 index 0000000000..a4e3f20a11 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Sex.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.data.bean; + +public enum Sex { + MALE("Male"), FEMALE("Female"), UNKNOWN("Unknown"); + + private String stringRepresentation; + + private Sex(String stringRepresentation) { + this.stringRepresentation = stringRepresentation; + } + + public String getStringRepresentation() { + return stringRepresentation; + } + + @Override + public String toString() { + return getStringRepresentation(); + } +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java new file mode 100644 index 0000000000..6393d61981 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java @@ -0,0 +1,116 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.data.converter; + +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.DefaultConverterFactory; +import com.vaadin.ui.TextField; + +public class ConverterFactory extends TestCase { + + public static class ConvertTo42 implements Converter<String, Integer> { + + @Override + public Integer convertToModel(String value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return 42; + } + + @Override + public String convertToPresentation(Integer value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return "42"; + } + + @Override + public Class<Integer> getModelType() { + return Integer.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + + } + + public static class ConverterFactory42 extends DefaultConverterFactory { + @Override + public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter( + Class<PRESENTATION> presentationType, Class<MODEL> modelType) { + if (modelType == Integer.class) { + return (Converter<PRESENTATION, MODEL>) new ConvertTo42(); + } + + return super.createConverter(presentationType, modelType); + } + } + + public void testApplicationConverterFactoryInBackgroundThread() { + Application.setCurrent(null); + final Application appWithCustomIntegerConverter = new Application(); + appWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + + TextField tf = new TextField("", "123") { + @Override + public Application getApplication() { + return appWithCustomIntegerConverter; + }; + }; + tf.setConverter(Integer.class); + // The application converter always returns 42. Current application is + // null + assertEquals(42, tf.getConvertedValue()); + } + + public void testApplicationConverterFactoryForDetachedComponent() { + final Application appWithCustomIntegerConverter = new Application(); + appWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + Application.setCurrent(appWithCustomIntegerConverter); + + TextField tf = new TextField("", "123"); + tf.setConverter(Integer.class); + // The application converter always returns 42. Current application is + // null + assertEquals(42, tf.getConvertedValue()); + } + + public void testApplicationConverterFactoryForDifferentThanCurrentApplication() { + final Application fieldAppWithCustomIntegerConverter = new Application(); + fieldAppWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + Application.setCurrent(new Application()); + + TextField tf = new TextField("", "123") { + @Override + public Application getApplication() { + return fieldAppWithCustomIntegerConverter; + } + }; + tf.setConverter(Integer.class); + + // The application converter always returns 42. Application.getCurrent() + // should not be used + assertEquals(42, tf.getConvertedValue()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java b/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java new file mode 100644 index 0000000000..8334c7f183 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class IndexedContainerListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ValueChangeEvent.class, ValueChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java b/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java new file mode 100644 index 0000000000..d493f22779 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Item.PropertySetChangeEvent; +import com.vaadin.data.Item.PropertySetChangeListener; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class PropertysetItemListeners extends AbstractListenerMethodsTest { + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(PropertysetItem.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java b/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java new file mode 100644 index 0000000000..1ab742427d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java @@ -0,0 +1,217 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.commons.io.IOUtils; + +public class SourceFileChecker extends TestCase { + + /** + * The tests are run in the build directory. + */ + public static String baseDirectory = null; + public static final String SRC_DIR = getBaseDir() + "src"; + public static final String TESTBENCH_SRC_DIR = getBaseDir() + + "tests/testbench"; + public static final String SERVERSIDE_SRC_DIR = getBaseDir() + + "tests/server-side"; + public static final String CLIENTSIDE_SRC_DIR = getBaseDir() + + "tests/client-side"; + private String externalJavaFiles = "com/vaadin/external"; + private String buildFiles = "build"; + private Set<String> alwaysIgnore = new HashSet<String>(); + { + alwaysIgnore.add(".settings"); + alwaysIgnore.add("eclipse"); + } + + public static String getBaseDir() { + if (baseDirectory != null) { + return baseDirectory; + } + // Run in the "build" directory by build, in the project root by Eclipse + for (File f : new File(".").listFiles()) { + if (f.getName().equals("buildhelpers")) { + // We are in "build" + baseDirectory = "../"; + return baseDirectory; + } + } + + baseDirectory = "./"; + return baseDirectory; + } + + private static final String[] ALL_SRC_DIRS = new String[] { SRC_DIR, + TESTBENCH_SRC_DIR, SERVERSIDE_SRC_DIR, CLIENTSIDE_SRC_DIR }; + + public void testJavaFilesContainsLicense() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + validateFiles(SRC_DIR, new LicenseChecker(), ignore, + "The following files are missing license information:\n{0}", + ".java"); + } + + public void testNonJavaFilesUseUnixNewline() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(buildFiles); + + for (String suffix : new String[] { ".html", ".css", ".xml" }) { + validateFiles(getBaseDir(), new DosNewlineDetector(), ignore, + "The following files contain CRLF instead of LF:\n{0}", + suffix); + } + } + + public void testJavaFilesUseUnixNewline() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + for (String dir : ALL_SRC_DIRS) { + validateFiles(dir, new DosNewlineDetector(), ignore, + "The following files contain CRLF instead of LF:\n{0}", + ".java"); + } + } + + public void testGwtFilesUsingEntry() { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + validateFiles( + SRC_DIR, + new GwtEntryChecker(), + ignore, + "The following files might export javscript callbacks without $entry:\n{0}", + ".java"); + } + + public interface FileValidator { + void validateFile(File f) throws Exception; + } + + private void validateFiles(String directory, FileValidator validator, + Set<String> ignore, String errorMessage, String ending) { + File srcDir = new File(directory); + HashSet<String> missing = new HashSet<String>(); + validateFiles(directory, srcDir, missing, validator, ending, ignore); + if (!missing.isEmpty()) { + throw new RuntimeException(errorMessage.replace("{0}", missing + .toString().replace(',', '\n'))); + } + + } + + private void validateFiles(String baseDirectory, File directory, + HashSet<String> missing, FileValidator validator, String suffix, + Set<String> ignores) { + Assert.assertTrue("Directory " + directory + " does not exist", + directory.exists()); + + File[] files = directory.listFiles(); + if (files == null) { + throw new RuntimeException("Listing of directory " + + directory.getPath() + " failed"); + } + for (File f : files) { + boolean ignoreThis = false; + for (String ignore : ignores) { + if (new File(baseDirectory, ignore).equals(f)) { + ignoreThis = true; + continue; + } + } + + if (ignoreThis) { + continue; + } + + if (f.isDirectory()) { + validateFiles(baseDirectory, f, missing, validator, suffix, + ignores); + } else if (f.getName().endsWith(suffix)) { + try { + validator.validateFile(f); + } catch (Throwable t) { + missing.add(f.getPath()); + } + } + } + } + + abstract class FileContentsValidator implements FileValidator { + @Override + public void validateFile(File f) throws Exception { + FileInputStream fis = new FileInputStream(f); + String contents = IOUtils.toString(fis); + fis.close(); + validateContents(f, contents); + } + + protected abstract void validateContents(File f, String contents) + throws Exception; + + } + + class DosNewlineDetector extends FileContentsValidator { + + @Override + protected void validateContents(File f, String contents) + throws Exception { + if (contents.contains("\r\n")) { + throw new IllegalArgumentException(); + } + + } + + } + + class LicenseChecker extends FileContentsValidator { + + @Override + protected void validateContents(File f, String contents) + throws Exception { + if (!contents.contains("@" + "VaadinApache2LicenseForJavaFiles" + + "@")) { + throw new IllegalArgumentException(); + } + } + } + + class GwtEntryChecker extends FileContentsValidator { + // Matches e.g. + // @com.vaadin.client.HistoryImplIEVaadin::escapeHtml( + private final Matcher matcher = Pattern.compile("@[\\w.]+::\\w+\\(") + .matcher(""); + + @Override + protected void validateContents(File f, String contents) + throws Exception { + matcher.reset(contents); + while (matcher.find()) { + int start = matcher.start(); + + // Search backwards to find index of native block start + int nativeBlockStart = contents.lastIndexOf("/*-{", start); + + // Get contents between block start and our match + String beforeMatchInBlock = contents.substring( + nativeBlockStart, start); + + // Fail if there's no $entry + if (!beforeMatchInBlock.contains("$entry")) { + throw new IllegalArgumentException(); + } + } + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java new file mode 100644 index 0000000000..0d8433d1c6 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java @@ -0,0 +1,16 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractBeanContainerListeners extends + AbstractListenerMethodsTest { + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(BeanItemContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class, + new BeanItemContainer<PropertySetChangeListener>( + PropertySetChangeListener.class)); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java new file mode 100644 index 0000000000..b63e4f809a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java @@ -0,0 +1,21 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractContainerListeners extends AbstractListenerMethodsTest { + + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ItemSetChangeEvent.class, ItemSetChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java new file mode 100644 index 0000000000..a8e2a4aa2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractInMemoryContainerListeners extends + AbstractListenerMethodsTest { + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ItemSetChangeEvent.class, ItemSetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java new file mode 100644 index 0000000000..a1d01d1930 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java @@ -0,0 +1,24 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Property.ReadOnlyStatusChangeEvent; +import com.vaadin.data.Property.ReadOnlyStatusChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.AbstractProperty; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractPropertyListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbstractProperty.class, + ValueChangeEvent.class, ValueChangeListener.class, + new ObjectProperty<String>("")); + } + + public void testReadOnlyStatusChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbstractProperty.class, + ReadOnlyStatusChangeEvent.class, + ReadOnlyStatusChangeListener.class, new ObjectProperty<String>( + "")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java new file mode 100644 index 0000000000..e98be99cbc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -0,0 +1,271 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import junit.framework.TestCase; + +import org.junit.Test; + +public class TestClassesSerializable extends TestCase { + + /** + * JARs that will be scanned for classes to test, in addition to classpath + * directories. + */ + private static String JAR_PATTERN = ".*vaadin.*\\.jar"; + + private static String[] BASE_PACKAGES = { "com.vaadin" }; + + private static String[] EXCLUDED_PATTERNS = { + "com\\.vaadin\\.demo\\..*", // + "com\\.vaadin\\.external\\.org\\.apache\\.commons\\.fileupload\\..*", // + "com\\.vaadin\\.launcher\\..*", // + "com\\.vaadin\\.client\\..*", // + "com\\.vaadin\\.server\\.widgetsetutils\\..*", // + "com\\.vaadin\\.tests\\..*", // exclude automated tests + "com\\.vaadin\\.tools\\..*", // + "com\\.vaadin\\.ui\\.themes\\..*", // + // exact class level filtering + "com\\.vaadin\\.event\\.FieldEvents", // + "com\\.vaadin\\.event\\.LayoutEvents", // + "com\\.vaadin\\.event\\.MouseEvents", // + "com\\.vaadin\\.server\\.AbstractApplicationPortlet", // + "com\\.vaadin\\.server\\.ApplicationPortlet2", // + "com\\.vaadin\\.server\\.Constants", // + "com\\.vaadin\\.util\\.SerializerHelper", // fully static + // class level filtering, also affecting nested classes and + // interfaces + "com\\.vaadin\\.server\\.AbstractCommunicationManager.*", // + "com\\.vaadin\\.server\\.CommunicationManager.*", // + "com\\.vaadin\\.server\\.PortletCommunicationManager.*", // + }; + + /** + * Tests that all the relevant classes and interfaces under + * {@link #BASE_PACKAGES} implement Serializable. + * + * @throws Exception + */ + public void testClassesSerializable() throws Exception { + List<String> rawClasspathEntries = getRawClasspathEntries(); + + List<String> classes = new ArrayList<String>(); + for (String location : rawClasspathEntries) { + classes.addAll(findServerClasses(location)); + } + + ArrayList<Class<?>> nonSerializableClasses = new ArrayList<Class<?>>(); + for (String className : classes) { + Class<?> cls = Class.forName(className); + // skip annotations and synthetic classes + if (cls.isAnnotation() || cls.isSynthetic()) { + continue; + } + // Don't add classes that have a @Test annotation on any methods + boolean testPresent = false; + for (Method method : cls.getMethods()) { + if (method.isAnnotationPresent(Test.class)) { + testPresent = true; + break; + } + } + if (testPresent) { + continue; + } + + // report non-serializable classes and interfaces + if (!Serializable.class.isAssignableFrom(cls)) { + nonSerializableClasses.add(cls); + // TODO easier to read when testing + // System.err.println(cls); + } + } + + // useful failure message including all non-serializable classes and + // interfaces + if (!nonSerializableClasses.isEmpty()) { + String nonSerializableString = ""; + Iterator<Class<?>> it = nonSerializableClasses.iterator(); + while (it.hasNext()) { + Class c = it.next(); + nonSerializableString += ", " + c.getName(); + if (c.isAnonymousClass()) { + nonSerializableString += "(super: "; + nonSerializableString += c.getSuperclass().getName(); + nonSerializableString += ", interfaces: "; + for (Class i : c.getInterfaces()) { + nonSerializableString += i.getName(); + nonSerializableString += ","; + } + nonSerializableString += ")"; + } + } + fail("Serializable not implemented by the following classes and interfaces: " + + nonSerializableString); + } + } + + /** + * Lists all class path entries by splitting the class path string. + * + * Adapted from ClassPathExplorer.getRawClasspathEntries(), but without + * filtering. + * + * @return List of class path segment strings + */ + // + private final static List<String> getRawClasspathEntries() { + // try to keep the order of the classpath + List<String> locations = new ArrayList<String>(); + + String pathSep = System.getProperty("path.separator"); + String classpath = System.getProperty("java.class.path"); + + if (classpath.startsWith("\"")) { + classpath = classpath.substring(1); + } + if (classpath.endsWith("\"")) { + classpath = classpath.substring(0, classpath.length() - 1); + } + + String[] split = classpath.split(pathSep); + for (int i = 0; i < split.length; i++) { + String classpathEntry = split[i]; + locations.add(classpathEntry); + } + + return locations; + } + + /** + * Finds the server side classes/interfaces under a class path entry - + * either a directory or a JAR that matches {@link #JAR_PATTERN}. + * + * Only classes under {@link #BASE_PACKAGES} are considered, and those + * matching {@link #EXCLUDED_PATTERNS} are filtered out. + * + * @param classpathEntry + * @return + * @throws IOException + */ + private List<String> findServerClasses(String classpathEntry) + throws IOException { + Collection<String> classes = new ArrayList<String>(); + + File file = new File(classpathEntry); + if (file.isDirectory()) { + classes = findClassesInDirectory(null, file); + } else if (file.getName().matches(JAR_PATTERN)) { + classes = findClassesInJar(file); + } else { + System.out.println("Ignoring " + classpathEntry); + return Collections.emptyList(); + } + + List<String> filteredClasses = new ArrayList<String>(); + for (String className : classes) { + boolean ok = false; + for (String basePackage : BASE_PACKAGES) { + if (className.startsWith(basePackage + ".")) { + ok = true; + break; + } + } + for (String excludedPrefix : EXCLUDED_PATTERNS) { + if (className.matches(excludedPrefix)) { + ok = false; + break; + } + } + + // Don't add test classes + if (className.contains("Test")) { + ok = false; + } + + if (ok) { + filteredClasses.add(className); + } + } + + return filteredClasses; + } + + /** + * Lists class names (based on .class files) in a JAR file. + * + * @param file + * a valid JAR file + * @return collection of fully qualified class names in the JAR + * @throws IOException + */ + private Collection<String> findClassesInJar(File file) throws IOException { + Collection<String> classes = new ArrayList<String>(); + + JarFile jar = new JarFile(file); + Enumeration<JarEntry> e = jar.entries(); + while (e.hasMoreElements()) { + JarEntry entry = e.nextElement(); + if (entry.getName().endsWith(".class")) { + String nameWithoutExtension = entry.getName().replaceAll( + "\\.class", ""); + String className = nameWithoutExtension.replace('/', '.'); + classes.add(className); + } + } + return classes; + } + + /** + * Lists class names (based on .class files) in a directory (a package path + * root). + * + * @param parentPackage + * parent package name or null at root of hierarchy, used by + * recursion + * @param parent + * File representing the directory to scan + * @return collection of fully qualified class names in the directory + */ + private final static Collection<String> findClassesInDirectory( + String parentPackage, File parent) { + if (parent.isHidden() + || parent.getPath().contains(File.separator + ".")) { + return Collections.emptyList(); + } + + if (parentPackage == null) { + parentPackage = ""; + } else { + parentPackage += "."; + } + + Collection<String> classNames = new ArrayList<String>(); + + // add all directories recursively + File[] files = parent.listFiles(); + for (File child : files) { + if (child.isDirectory()) { + classNames.addAll(findClassesInDirectory( + parentPackage + child.getName(), child)); + } else if (child.getName().endsWith(".class")) { + classNames.add(parentPackage.replace(File.separatorChar, '.') + + child.getName().replaceAll("\\.class", "")); + } + } + + return classNames; + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestEventRouter.java b/server/tests/src/com/vaadin/tests/server/TestEventRouter.java new file mode 100644 index 0000000000..a8f5039042 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestEventRouter.java @@ -0,0 +1,39 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.ui.TextField; + +public class TestEventRouter extends TestCase { + + int innerListenerCalls = 0; + + public void testAddInEventListener() { + final TextField tf = new TextField(); + + final ValueChangeListener outer = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + ValueChangeListener inner = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + innerListenerCalls++; + System.out.println("The inner listener was called"); + } + }; + + tf.addListener(inner); + } + }; + + tf.addListener(outer); + tf.setValue("abc"); // No inner listener calls, adds one inner + tf.setValue("def"); // One inner listener call, adds one inner + tf.setValue("ghi"); // Two inner listener calls, adds one inner + assert (innerListenerCalls == 3); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java b/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java new file mode 100644 index 0000000000..8a368ead53 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java @@ -0,0 +1,79 @@ +package com.vaadin.tests.server; + +import java.io.File; + +import junit.framework.TestCase; + +import com.vaadin.service.FileTypeResolver; + +public class TestFileTypeResolver extends TestCase { + + private static final String FLASH_MIME_TYPE = "application/x-shockwave-flash"; + private static final String TEXT_MIME_TYPE = "text/plain"; + private static final String HTML_MIME_TYPE = "text/html"; + + public void testMimeTypes() { + File plainFlash = new File("MyFlash.swf"); + File plainText = new File("/a/b/MyFlash.txt"); + File plainHtml = new File("c:\\MyFlash.html"); + + // Flash + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath()), + FLASH_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath() + + "?param1=value1"), FLASH_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath() + + "?param1=value1¶m2=value2"), FLASH_MIME_TYPE); + + // Plain text + assertEquals(FileTypeResolver.getMIMEType(plainText.getAbsolutePath()), + TEXT_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainText.getAbsolutePath() + + "?param1=value1"), TEXT_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainText.getAbsolutePath() + + "?param1=value1¶m2=value2"), TEXT_MIME_TYPE); + + // Plain text + assertEquals(FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath()), + HTML_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath() + + "?param1=value1"), HTML_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath() + + "?param1=value1¶m2=value2"), HTML_MIME_TYPE); + + // Filename missing + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("")); + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("?param1")); + + } + + public void testExtensionCase() { + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.jpg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.jPg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPG")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPEG")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.Jpeg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPE")); + } + + public void testCustomMimeType() { + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("vaadin.foo")); + + FileTypeResolver.addExtension("foo", "Vaadin Foo/Bar"); + FileTypeResolver.addExtension("FOO2", "Vaadin Foo/Bar2"); + assertEquals("Vaadin Foo/Bar", + FileTypeResolver.getMIMEType("vaadin.foo")); + assertEquals("Vaadin Foo/Bar2", + FileTypeResolver.getMIMEType("vaadin.Foo2")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java b/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java new file mode 100644 index 0000000000..1c1f9624c8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java @@ -0,0 +1,102 @@ +package com.vaadin.tests.server; + +import java.lang.reflect.Field; +import java.util.HashMap; + +import junit.framework.TestCase; + +import com.vaadin.server.KeyMapper; + +public class TestKeyMapper extends TestCase { + + public void testAdd() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + String key1 = mapper.key(o1); + String key2 = mapper.key(o2); + String key3 = mapper.key(o3); + + assertEquals(mapper.get(key1), o1); + assertEquals(mapper.get(key2), o2); + assertEquals(mapper.get(key3), o3); + assertNotSame(key1, key2); + assertNotSame(key1, key3); + assertNotSame(key2, key3); + + assertSize(mapper, 3); + + // Key should not add if there already is a mapping + assertEquals(mapper.key(o3), key3); + assertSize(mapper, 3); + + // Remove -> add should return a new key + mapper.remove(o1); + String newkey1 = mapper.key(o1); + assertNotSame(key1, newkey1); + + } + + public void testRemoveAll() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + mapper.key(o1); + mapper.key(o2); + mapper.key(o3); + + assertSize(mapper, 3); + mapper.removeAll(); + assertSize(mapper, 0); + + } + + public void testRemove() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + mapper.key(o1); + mapper.key(o2); + mapper.key(o3); + + assertSize(mapper, 3); + mapper.remove(o1); + assertSize(mapper, 2); + mapper.key(o1); + assertSize(mapper, 3); + mapper.remove(o1); + assertSize(mapper, 2); + + mapper.remove(o2); + mapper.remove(o3); + assertSize(mapper, 0); + + } + + private void assertSize(KeyMapper<?> mapper, int i) { + try { + Field f1 = KeyMapper.class.getDeclaredField("objectKeyMap"); + Field f2 = KeyMapper.class.getDeclaredField("keyObjectMap"); + f1.setAccessible(true); + f2.setAccessible(true); + + HashMap<?, ?> h1 = (HashMap<?, ?>) f1.get(mapper); + HashMap<?, ?> h2 = (HashMap<?, ?>) f2.get(mapper); + + assertEquals(i, h1.size()); + assertEquals(i, h2.size()); + } catch (Throwable t) { + t.printStackTrace(); + fail(); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java new file mode 100644 index 0000000000..dc730f6cc4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java @@ -0,0 +1,26 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.server.ClassResource; +import com.vaadin.ui.Embedded; + +public class TestMimeTypes extends TestCase { + + public void testEmbeddedPDF() { + Application app = new Application() { + + @Override + public void init() { + // TODO Auto-generated method stub + + } + }; + Embedded e = new Embedded("A pdf", new ClassResource("file.pddf")); + assertEquals("Invalid mimetype", "application/octet-stream", + e.getMimeType()); + e = new Embedded("A pdf", new ClassResource("file.pdf")); + assertEquals("Invalid mimetype", "application/pdf", e.getMimeType()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java b/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java new file mode 100644 index 0000000000..48c60c83c4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java @@ -0,0 +1,75 @@ +package com.vaadin.tests.server; + +import java.util.Date; + +import junit.framework.TestCase; + +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertyFormatter; + +@SuppressWarnings("unchecked") +public class TestPropertyFormatter extends TestCase { + + class TestFormatter extends PropertyFormatter { + + @Override + public String format(Object value) { + boolean isCorrectType = getExpectedClass().isAssignableFrom( + value.getClass()); + assertTrue(isCorrectType); + return "FOO"; + } + + @Override + public Object parse(String formattedValue) throws Exception { + return getExpectedClass().newInstance(); + } + }; + + @SuppressWarnings("rawtypes") + private Class expectedClass; + + @SuppressWarnings("rawtypes") + private Class getExpectedClass() { + return expectedClass; + } + + /** + * The object passed to format should be same as property's type. + * + * @throws IllegalAccessException + * @throws InstantiationException + */ + @Test + @SuppressWarnings({ "rawtypes" }) + public void testCorrectTypeForFormat() throws InstantiationException, + IllegalAccessException { + Class[] testedTypes = new Class[] { Integer.class, Boolean.class, + Double.class, String.class, Date.class }; + Object[] testValues = new Object[] { new Integer(3), Boolean.FALSE, + new Double(3.3), "bar", new Date() }; + + int i = 0; + for (Class class1 : testedTypes) { + expectedClass = class1; + + TestFormatter formatter = new TestFormatter(); + + // Should just return null, without formatting + Object value = formatter.getValue(); + + // test with property which value is null + formatter.setPropertyDataSource(new ObjectProperty(null, + expectedClass)); + formatter.getValue(); // calls format + + // test with a value + formatter.setPropertyDataSource(new ObjectProperty(testValues[i++], + expectedClass)); + formatter.getValue(); // calls format + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestSerialization.java b/server/tests/src/com/vaadin/tests/server/TestSerialization.java new file mode 100644 index 0000000000..84ff5ad6fa --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestSerialization.java @@ -0,0 +1,126 @@ +package com.vaadin.tests.server; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import junit.framework.TestCase; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.data.validator.RegexpValidator; +import com.vaadin.ui.Form; + +public class TestSerialization extends TestCase { + + public void testValidators() throws Exception { + RegexpValidator validator = new RegexpValidator(".*", "Error"); + validator.validate("aaa"); + RegexpValidator validator2 = (RegexpValidator) serializeAndDeserialize(validator); + validator2.validate("aaa"); + } + + public void testForm() throws Exception { + Form f = new Form(); + String propertyId = "My property"; + f.addItemProperty(propertyId, new MethodProperty<Object>(new Data(), + "dummyGetterAndSetter")); + f.replaceWithSelect(propertyId, new Object[] { "a", "b", null }, + new String[] { "Item a", "ITem b", "Null item" }); + + serializeAndDeserialize(f); + + } + + public void testIndedexContainerItemIds() throws Exception { + IndexedContainer ic = new IndexedContainer(); + ic.addContainerProperty("prop1", String.class, null); + Object id = ic.addItem(); + ic.getItem(id).getItemProperty("prop1").setValue("1"); + + Item item2 = ic.addItem("item2"); + item2.getItemProperty("prop1").setValue("2"); + + serializeAndDeserialize(ic); + } + + public void testMethodPropertyGetter() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyGetter"); + serializeAndDeserialize(mp); + } + + public void testMethodPropertyGetterAndSetter() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyGetterAndSetter"); + serializeAndDeserialize(mp); + } + + public void testMethodPropertyInt() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyInt"); + serializeAndDeserialize(mp); + } + + private static Serializable serializeAndDeserialize(Serializable s) + throws IOException, ClassNotFoundException { + // Serialize and deserialize + + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bs); + out.writeObject(s); + byte[] data = bs.toByteArray(); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream( + data)); + Serializable s2 = (Serializable) in.readObject(); + + // using special toString(Object) method to avoid calling + // Property.toString(), which will be temporarily disabled + if (s.equals(s2)) { + System.out.println(toString(s) + " equals " + toString(s2)); + } else { + System.out.println(toString(s) + " does NOT equal " + toString(s2)); + } + + return s2; + } + + private static String toString(Object o) { + if (o instanceof Property) { + return String.valueOf(((Property<?>) o).getValue()); + } else { + return String.valueOf(o); + } + } + + public static class Data implements Serializable { + private String dummyGetter; + private String dummyGetterAndSetter; + private int dummyInt; + + public String getDummyGetterAndSetter() { + return dummyGetterAndSetter; + } + + public void setDummyGetterAndSetter(String dummyGetterAndSetter) { + this.dummyGetterAndSetter = dummyGetterAndSetter; + } + + public int getDummyInt() { + return dummyInt; + } + + public void setDummyInt(int dummyInt) { + this.dummyInt = dummyInt; + } + + public String getDummyGetter() { + return dummyGetter; + } + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java b/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java new file mode 100644 index 0000000000..84247c81c1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java @@ -0,0 +1,138 @@ +package com.vaadin.tests.server; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import junit.framework.TestCase; + +import com.vaadin.server.AbstractCommunicationManager.SimpleMultiPartInputStream; + +public class TestSimpleMultiPartInputStream extends TestCase { + + /** + * Check that the output for a given stream until boundary is as expected. + * + * @param input + * @param boundary + * @param expected + * @throws Exception + */ + protected void checkBoundaryDetection(byte[] input, String boundary, + byte[] expected) throws Exception { + ByteArrayInputStream bais = new ByteArrayInputStream(input); + SimpleMultiPartInputStream smpis = new SimpleMultiPartInputStream(bais, + boundary); + ByteArrayOutputStream resultStream = new ByteArrayOutputStream(); + int outbyte; + try { + while ((outbyte = smpis.read()) != -1) { + resultStream.write(outbyte); + } + } catch (IOException e) { + throw new IOException(e.getMessage() + "; expected " + + new String(expected) + " but got " + + resultStream.toString()); + } + if (!Arrays.equals(expected, resultStream.toByteArray())) { + throw new Exception("Mismatch: expected " + new String(expected) + + " but got " + resultStream.toString()); + } + } + + protected void checkBoundaryDetection(String input, String boundary, + String expected) throws Exception { + checkBoundaryDetection(input.getBytes(), boundary, expected.getBytes()); + } + + public void testSingleByteBoundaryAtEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("a"), "a", "xyz123"); + } + + public void testSingleByteBoundaryInMiddle() throws Exception { + checkBoundaryDetection("xyz" + getFullBoundary("a") + "123", "a", "xyz"); + } + + public void testCorrectBoundaryAtEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("abc"), "abc", + "xyz123"); + } + + public void testCorrectBoundaryNearEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("abc") + "de", "abc", + "xyz123"); + } + + public void testCorrectBoundaryAtBeginning() throws Exception { + checkBoundaryDetection(getFullBoundary("abc") + "xyz123", "abc", ""); + } + + public void testRepeatingCharacterBoundary() throws Exception { + checkBoundaryDetection(getFullBoundary("aa") + "xyz123", "aa", ""); + checkBoundaryDetection("axyz" + getFullBoundary("aa") + "123", "aa", + "axyz"); + checkBoundaryDetection("xyz123" + getFullBoundary("aa"), "aa", "xyz123"); + } + + /** + * Note, the boundary in this test is invalid. Boundary strings don't + * contain CR/LF. + * + */ + // public void testRepeatingNewlineBoundary() throws Exception { + // checkBoundaryDetection("1234567890" + getFullBoundary("\n\n") + // + "1234567890", "\n\n", ""); + // } + + public void testRepeatingStringBoundary() throws Exception { + checkBoundaryDetection(getFullBoundary("abab") + "xyz123", "abab", ""); + checkBoundaryDetection("abaxyz" + getFullBoundary("abab") + "123", + "abab", "abaxyz"); + checkBoundaryDetection("xyz123" + getFullBoundary("abab"), "abab", + "xyz123"); + } + + public void testOverlappingBoundary() throws Exception { + checkBoundaryDetection("abc" + getFullBoundary("abcabd") + "xyz123", + "abcabd", "abc"); + checkBoundaryDetection("xyzabc" + getFullBoundary("abcabd") + "123", + "abcabd", "xyzabc"); + checkBoundaryDetection("xyz123abc" + getFullBoundary("abcabd"), + "abcabd", "xyz123abc"); + } + + /* + * TODO fix these tests, they don't do what their method name says. + */ + + // public void testNoBoundaryInInput() throws Exception { + // try { + // checkBoundaryDetection("xyz123", "abc", "xyz123"); + // fail(); + // } catch (IOException e) { + // } + // } + // + // public void testPartialBoundaryAtInputEnd() throws Exception { + // try { + // // This should lead to IOException (stream end), not AIOOBE + // checkBoundaryDetection("xyz123ab", "abc", "xyz123ab"); + // fail(); + // } catch (IOException e) { + // } + // } + // + // public void testPartialBoundaryAtInputBeginning() throws Exception { + // try { + // checkBoundaryDetection("abxyz123", "abc", "abxyz123"); + // fail(); + // } catch (IOException e) { + // } + // } + + public static String getFullBoundary(String str) { + return "\r\n--" + str + "--"; + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java new file mode 100644 index 0000000000..f3b367483a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java @@ -0,0 +1,77 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.Application; +import com.vaadin.server.CommunicationManager; +import com.vaadin.server.StreamVariable; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.UI; +import com.vaadin.ui.Upload; + +public class TestStreamVariableMapping extends TestCase { + private static final String variableName = "myName"; + + private Upload owner; + private StreamVariable streamVariable; + + private CommunicationManager cm; + + @Override + protected void setUp() throws Exception { + final Application application = new Application(); + final UI uI = new UI() { + @Override + protected void init(WrappedRequest request) { + // TODO Auto-generated method stub + + } + + @Override + public Application getApplication() { + return application; + } + }; + owner = new Upload() { + @Override + public UI getUI() { + return uI; + } + }; + streamVariable = EasyMock.createMock(StreamVariable.class); + cm = createCommunicationManager(); + + super.setUp(); + } + + public void testAddStreamVariable() { + String targetUrl = cm.getStreamVariableTargetUrl(owner, variableName, + streamVariable); + assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/1/myName/")); + + StreamVariable streamVariable2 = cm.getStreamVariable( + owner.getConnectorId(), variableName); + assertSame(streamVariable, streamVariable2); + } + + public void testRemoverVariable() { + cm.getStreamVariableTargetUrl(owner, variableName, streamVariable); + assertNotNull(cm + .getStreamVariable(owner.getConnectorId(), variableName)); + + cm.cleanStreamVariable(owner, variableName); + assertNull(cm.getStreamVariable(owner.getConnectorId(), variableName)); + } + + private CommunicationManager createCommunicationManager() { + return new CommunicationManager(new Application() { + @Override + public void init() { + // TODO Auto-generated method stub + } + }); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestThemeNames.java b/server/tests/src/com/vaadin/tests/server/TestThemeNames.java new file mode 100644 index 0000000000..22fe315730 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestThemeNames.java @@ -0,0 +1,38 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.themes.BaseTheme; + +public class TestThemeNames extends TestCase { + public void testThemeNames() { + File baseDir = new File(SourceFileChecker.getBaseDir() + + "WebContent/VAADIN/themes/"); + + List<Class<? extends BaseTheme>> themeClasses = VaadinClasses + .getThemeClasses(); + for (Class<? extends BaseTheme> themeClass : themeClasses) { + try { + Field field = themeClass.getField("THEME_NAME"); + String themeName = (String) field.get(null); + + File themeDir = new File(baseDir, themeName); + File styleFile = new File(themeDir, "styles.css"); + + assertTrue("Can't find " + styleFile + " for theme " + + themeClass.getName(), styleFile.exists()); + + // Test that casing matches + assertEquals(themeDir.getCanonicalFile().getName(), themeName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java b/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java new file mode 100644 index 0000000000..0cacccd08a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java @@ -0,0 +1,201 @@ +package com.vaadin.tests.server; + +import static org.easymock.EasyMock.createMock; + +import java.lang.Thread.UncaughtExceptionHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Random; + +import javax.servlet.http.HttpSession; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.Application.ApplicationStartEvent; +import com.vaadin.server.AbstractWebApplicationContext; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.WebApplicationContext; +import com.vaadin.service.ApplicationContext.TransactionListener; + +import org.easymock.EasyMock; + +public class TransactionListenersConcurrency extends TestCase { + + /** + * This test starts N threads concurrently. Each thread creates an + * application which adds a transaction listener to the context. A + * transaction is then started for each application. Some semi-random delays + * are included so that calls to addTransactionListener and + * WebApplicationContext.startTransaction are mixed. + * + */ + public void testTransactionListeners() throws Exception { + final List<Throwable> exceptions = new ArrayList<Throwable>(); + + HttpSession session = createSession(); + final WebApplicationContext context = WebApplicationContext + .getApplicationContext(session); + List<Thread> threads = new ArrayList<Thread>(); + + for (int i = 0; i < 5; i++) { + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + Application app = new Application() { + + @Override + public void init() { + // Sleep 0-1000ms so another transaction has time to + // start before we add the transaction listener. + try { + Thread.sleep((long) (1000 * new Random() + .nextDouble())); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + getContext().addTransactionListener( + new DelayTransactionListener(2000)); + } + + }; + + // Start the application so the transaction listener is + // called later on. + try { + DeploymentConfiguration dc = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(dc.isProductionMode()).andReturn(true); + EasyMock.expect(dc.getInitParameters()).andReturn( + new Properties()); + EasyMock.replay(dc); + + app.start(new ApplicationStartEvent(new URL( + "http://localhost/"), dc, context)); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + try { + // Call the transaction listener using reflection as + // startTransaction is protected. + + Method m = AbstractWebApplicationContext.class + .getDeclaredMethod("startTransaction", + Application.class, Object.class); + m.setAccessible(true); + m.invoke(context, app, null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + }); + + threads.add(t); + t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + + @Override + public void uncaughtException(Thread t, Throwable e) { + if (e.getCause() != null) { + e = e.getCause(); + } + exceptions.add(e); + } + }); + } + + // Start the threads and wait for all of them to finish + for (Thread t : threads) { + t.start(); + } + int running = threads.size(); + + while (running > 0) { + for (Iterator<Thread> i = threads.iterator(); i.hasNext();) { + Thread t = i.next(); + if (!t.isAlive()) { + running--; + i.remove(); + } + } + } + + for (Throwable t : exceptions) { + if (t instanceof InvocationTargetException) { + t = t.getCause(); + } + if (t != null) { + t.printStackTrace(System.err); + fail(t.getClass().getName()); + } + } + + System.out.println("Done, all ok"); + + } + + /** + * Creates a HttpSession mock + * + */ + private static HttpSession createSession() { + HttpSession session = createMock(HttpSession.class); + EasyMock.expect( + session.getAttribute(WebApplicationContext.class.getName())) + .andReturn(null).anyTimes(); + session.setAttribute( + EasyMock.eq(WebApplicationContext.class.getName()), + EasyMock.anyObject()); + + EasyMock.replay(session); + return session; + } + + /** + * A transaction listener that just sleeps for the given amount of time in + * transactionStart and transactionEnd. + * + */ + public static class DelayTransactionListener implements TransactionListener { + + private int delay; + + public DelayTransactionListener(int delay) { + this.delay = delay; + } + + @Override + public void transactionStart(Application application, + Object transactionData) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + + @Override + public void transactionEnd(Application application, + Object transactionData) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java b/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java new file mode 100644 index 0000000000..e189ffc77d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java @@ -0,0 +1,173 @@ +package com.vaadin.tests.server.component; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.junit.Assert; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.Component; + +public abstract class AbstractListenerMethodsTest extends TestCase { + + public static void main(String[] args) { + findAllListenerMethods(); + } + + private static void findAllListenerMethods() { + Set<Class<?>> classes = new HashSet<Class<?>>(); + for (Class<?> c : VaadinClasses.getAllServerSideClasses()) { + while (c != null && c.getName().startsWith("com.vaadin.")) { + classes.add(c); + c = c.getSuperclass(); + } + } + + for (Class<?> c : classes) { + boolean found = false; + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals("addListener")) { + if (m.getParameterTypes().length != 1) { + continue; + } + String packageName = "com.vaadin.tests.server"; + if (Component.class.isAssignableFrom(c)) { + packageName += ".component." + + c.getSimpleName().toLowerCase(); + continue; + } + + if (!found) { + found = true; + System.out.println("package " + packageName + ";"); + + System.out.println("import " + + AbstractListenerMethodsTest.class.getName() + + ";"); + System.out.println("import " + c.getName() + ";"); + System.out.println("public class " + + c.getSimpleName() + + "Listeners extends " + + AbstractListenerMethodsTest.class + .getSimpleName() + " {"); + } + + String listenerClassName = m.getParameterTypes()[0] + .getSimpleName(); + String eventClassName = listenerClassName.replaceFirst( + "Listener$", "Event"); + System.out.println("public void test" + listenerClassName + + "() throws Exception {"); + System.out.println(" testListener(" + c.getSimpleName() + + ".class, " + eventClassName + ".class, " + + listenerClassName + ".class);"); + System.out.println("}"); + } + } + if (found) { + System.out.println("}"); + System.out.println(); + } + } + } + + protected void testListenerAddGetRemove(Class<?> testClass, + Class<?> eventClass, Class<?> listenerClass) throws Exception { + // Create a component for testing + Object c = testClass.newInstance(); + testListenerAddGetRemove(testClass, eventClass, listenerClass, c); + + } + + protected void testListenerAddGetRemove(Class<?> cls, Class<?> eventClass, + Class<?> listenerClass, Object c) throws Exception { + + Object mockListener1 = EasyMock.createMock(listenerClass); + Object mockListener2 = EasyMock.createMock(listenerClass); + + // Verify we start from no listeners + verifyListeners(c, eventClass); + + // Add one listener and verify + addListener(c, mockListener1, listenerClass); + verifyListeners(c, eventClass, mockListener1); + + // Add another listener and verify + addListener(c, mockListener2, listenerClass); + verifyListeners(c, eventClass, mockListener1, mockListener2); + + // Ensure we can fetch using parent class also + if (eventClass.getSuperclass() != null) { + verifyListeners(c, eventClass.getSuperclass(), mockListener1, + mockListener2); + } + + // Remove the first and verify + removeListener(c, mockListener1, listenerClass); + verifyListeners(c, eventClass, mockListener2); + + // Remove the remaining and verify + removeListener(c, mockListener2, listenerClass); + verifyListeners(c, eventClass); + + } + + private void removeListener(Object c, Object listener, + Class<?> listenerClass) throws IllegalArgumentException, + IllegalAccessException, InvocationTargetException, + SecurityException, NoSuchMethodException { + Method method = getRemoveListenerMethod(c.getClass(), listenerClass); + method.invoke(c, listener); + + } + + private void addListener(Object c, Object listener1, Class<?> listenerClass) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, SecurityException, NoSuchMethodException { + Method method = getAddListenerMethod(c.getClass(), listenerClass); + method.invoke(c, listener1); + } + + private Collection<?> getListeners(Object c, Class<?> eventType) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, SecurityException, NoSuchMethodException { + Method method = getGetListenersMethod(c.getClass()); + return (Collection<?>) method.invoke(c, eventType); + } + + private Method getGetListenersMethod(Class<? extends Object> cls) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("getListeners", Class.class); + } + + private Method getAddListenerMethod(Class<?> cls, Class<?> listenerClass) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("addListener", listenerClass); + + } + + private Method getRemoveListenerMethod(Class<?> cls, Class<?> listenerClass) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("removeListener", listenerClass); + + } + + private void verifyListeners(Object c, Class<?> eventClass, + Object... expectedListeners) throws IllegalArgumentException, + SecurityException, IllegalAccessException, + InvocationTargetException, NoSuchMethodException { + Collection<?> registeredListeners = getListeners(c, eventClass); + assertEquals("Number of listeners", expectedListeners.length, + registeredListeners.size()); + + Assert.assertArrayEquals(expectedListeners, + registeredListeners.toArray()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java b/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java new file mode 100644 index 0000000000..ad80007882 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java @@ -0,0 +1,68 @@ +package com.vaadin.tests.server.component; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashSet; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.Component; + +public class FinalMethodTest extends TestCase { + + // public void testThatContainersHaveNoFinalMethods() { + // HashSet<Class<?>> tested = new HashSet<Class<?>>(); + // for (Class<?> c : VaadinClasses.getAllServerSideClasses()) { + // if (Container.class.isAssignableFrom(c)) { + // ensureNoFinalMethods(c, tested); + // } + // } + // } + + public void testThatComponentsHaveNoFinalMethods() { + HashSet<Class<?>> tested = new HashSet<Class<?>>(); + for (Class<? extends Component> c : VaadinClasses.getComponents()) { + ensureNoFinalMethods(c, tested); + } + } + + private void ensureNoFinalMethods(Class<?> c, HashSet<Class<?>> tested) { + if (tested.contains(c)) { + return; + } + + tested.add(c); + + if (c == Object.class) { + return; + } + System.out.println("Checking " + c.getName()); + for (Method m : c.getDeclaredMethods()) { + if (isPrivate(m)) { + continue; + } + if (isFinal(m)) { + String error = "Class " + c.getName() + " contains a " + + (isPublic(m) ? "public" : "non-public") + + " final method: " + m.getName(); + // System.err.println(error); + throw new RuntimeException(error); + } + } + ensureNoFinalMethods(c.getSuperclass(), tested); + + } + + private boolean isFinal(Method m) { + return Modifier.isFinal(m.getModifiers()); + } + + private boolean isPrivate(Method m) { + return Modifier.isPrivate(m.getModifiers()); + } + + private boolean isPublic(Method m) { + return Modifier.isPublic(m.getModifiers()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java new file mode 100644 index 0000000000..7d6db42d1a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.absolutelayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.AbsoluteLayout; + +public class AbsoluteLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbsoluteLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java new file mode 100644 index 0000000000..d76dcffa2f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java @@ -0,0 +1,204 @@ +package com.vaadin.tests.server.component.absolutelayout; + +import junit.framework.TestCase; + +import com.vaadin.server.Sizeable; +import com.vaadin.server.Sizeable.Unit; +import com.vaadin.ui.AbsoluteLayout; +import com.vaadin.ui.Button; + +public class ComponentPosition extends TestCase { + + private static final String CSS = "top:7.0px;right:7.0%;bottom:7.0pc;left:7.0em;z-index:7;"; + private static final String PARTIAL_CSS = "top:7.0px;left:7.0em;"; + private static final Float CSS_VALUE = Float.valueOf(7); + + private static final Unit UNIT_UNSET = Sizeable.Unit.PIXELS; + + /** + * Add component w/o giving positions, assert that everything is unset + */ + public void testNoPosition() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + assertNull(layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertNull(layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(UNIT_UNSET, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals("", layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, setting all attributes using CSS, assert getter agree + */ + public void testFullCss() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.PICAS, layout.getPosition(b) + .getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(Sizeable.Unit.PERCENTAGE, layout.getPosition(b) + .getRightUnits()); + + assertEquals(7, layout.getPosition(b).getZIndex()); + + assertEquals(CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, setting some attributes using CSS, assert getters agree + */ + public void testPartialCss() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, PARTIAL_CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals(PARTIAL_CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component setting all attributes using CSS, then reset using partial + * CSS; assert getters agree and the appropriate attributes are unset. + */ + public void testPartialCssReset() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + layout.getPosition(b).setCSSString(PARTIAL_CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals(PARTIAL_CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, then set all position attributes with individual setters + * for value and units; assert getters agree. + */ + public void testSetPosition() { + final Float SIZE = Float.valueOf(12); + + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + layout.getPosition(b).setTopValue(SIZE); + layout.getPosition(b).setRightValue(SIZE); + layout.getPosition(b).setBottomValue(SIZE); + layout.getPosition(b).setLeftValue(SIZE); + + layout.getPosition(b).setTopUnits(Sizeable.Unit.CM); + layout.getPosition(b).setRightUnits(Sizeable.Unit.EX); + layout.getPosition(b).setBottomUnits(Sizeable.Unit.INCH); + layout.getPosition(b).setLeftUnits(Sizeable.Unit.MM); + + assertEquals(SIZE, layout.getPosition(b).getTopValue()); + assertEquals(SIZE, layout.getPosition(b).getRightValue()); + assertEquals(SIZE, layout.getPosition(b).getBottomValue()); + assertEquals(SIZE, layout.getPosition(b).getLeftValue()); + + assertEquals(Sizeable.Unit.CM, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.EX, layout.getPosition(b).getRightUnits()); + assertEquals(Sizeable.Unit.INCH, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.MM, layout.getPosition(b).getLeftUnits()); + + } + + /** + * Add component, then set all position attributes with combined setters for + * value and units; assert getters agree. + */ + public void testSetPosition2() { + final Float SIZE = Float.valueOf(12); + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + layout.getPosition(b).setTop(SIZE, Sizeable.Unit.CM); + layout.getPosition(b).setRight(SIZE, Sizeable.Unit.EX); + layout.getPosition(b).setBottom(SIZE, Sizeable.Unit.INCH); + layout.getPosition(b).setLeft(SIZE, Sizeable.Unit.MM); + + assertEquals(SIZE, layout.getPosition(b).getTopValue()); + assertEquals(SIZE, layout.getPosition(b).getRightValue()); + assertEquals(SIZE, layout.getPosition(b).getBottomValue()); + assertEquals(SIZE, layout.getPosition(b).getLeftValue()); + + assertEquals(Sizeable.Unit.CM, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.EX, layout.getPosition(b).getRightUnits()); + assertEquals(Sizeable.Unit.INCH, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.MM, layout.getPosition(b).getLeftUnits()); + + } + + /** + * Add component, set all attributes using CSS, unset some using method + * calls, assert getters agree. + */ + public void testUnsetPosition() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + layout.getPosition(b).setTopValue(null); + layout.getPosition(b).setRightValue(null); + layout.getPosition(b).setBottomValue(null); + layout.getPosition(b).setLeftValue(null); + + layout.getPosition(b).setZIndex(-1); + + assertNull(layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertNull(layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals("", layout.getPosition(b).getCSSString()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java new file mode 100644 index 0000000000..1903e66f92 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java @@ -0,0 +1,61 @@ +package com.vaadin.tests.server.component.abstractcomponent; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbstractComponent; + +public class TestAbstractComponentStyleNames extends TestCase { + + public void testSetMultiple() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testSetAdd() { + AbstractComponent component = getComponent(); + component.setStyleName("style1"); + component.addStyleName("style2"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testAddSame() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + component.addStyleName("style1"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testSetRemove() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + component.removeStyleName("style1"); + assertEquals(component.getStyleName(), "style2"); + } + + public void testAddRemove() { + AbstractComponent component = getComponent(); + component.addStyleName("style1"); + component.addStyleName("style2"); + component.removeStyleName("style1"); + assertEquals(component.getStyleName(), "style2"); + } + + public void testRemoveMultipleWithExtraSpaces() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2 style3"); + component.removeStyleName(" style1 style3 "); + assertEquals(component.getStyleName(), "style2"); + } + + public void testSetWithExtraSpaces() { + AbstractComponent component = getComponent(); + component.setStyleName(" style1 style2 "); + assertEquals(component.getStyleName(), "style1 style2"); + } + + private AbstractComponent getComponent() { + return new AbstractComponent() { + }; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java new file mode 100644 index 0000000000..f9f170eb2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java @@ -0,0 +1,22 @@ +package com.vaadin.tests.server.component.abstractcomponentcontainer; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.ComponentContainer.ComponentAttachEvent; +import com.vaadin.ui.ComponentContainer.ComponentAttachListener; +import com.vaadin.ui.ComponentContainer.ComponentDetachEvent; +import com.vaadin.ui.ComponentContainer.ComponentDetachListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.VerticalLayout; + +public class TestAbstractComponentContainerListeners extends + AbstractListenerMethodsTest { + public void testComponentDetachListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(HorizontalLayout.class, + ComponentDetachEvent.class, ComponentDetachListener.class); + } + + public void testComponentAttachListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(VerticalLayout.class, + ComponentAttachEvent.class, ComponentAttachListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java new file mode 100644 index 0000000000..57af748247 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java @@ -0,0 +1,216 @@ +package com.vaadin.tests.server.component.abstractfield; + +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.StringToIntegerConverter; +import com.vaadin.tests.data.bean.Address; +import com.vaadin.tests.data.bean.Country; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.data.bean.Sex; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.TextField; + +public class AbstractFieldValueConversions extends TestCase { + + Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", + 34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", + Country.FINLAND)); + + public void testWithoutConversion() { + TextField tf = new TextField(); + tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, + "firstName")); + assertEquals("Paula", tf.getValue()); + assertEquals("Paula", tf.getPropertyDataSource().getValue()); + tf.setValue("abc"); + assertEquals("abc", tf.getValue()); + assertEquals("abc", tf.getPropertyDataSource().getValue()); + assertEquals("abc", paulaBean.getFirstName()); + } + + public void testStringIdentityConversion() { + TextField tf = new TextField(); + tf.setConverter(new Converter<String, String>() { + + @Override + public String convertToModel(String value, Locale locale) { + return value; + } + + @Override + public String convertToPresentation(String value, Locale locale) { + return value; + } + + @Override + public Class<String> getModelType() { + return String.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + }); + tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, + "firstName")); + assertEquals("Paula", tf.getValue()); + assertEquals("Paula", tf.getPropertyDataSource().getValue()); + tf.setValue("abc"); + assertEquals("abc", tf.getValue()); + assertEquals("abc", tf.getPropertyDataSource().getValue()); + assertEquals("abc", paulaBean.getFirstName()); + } + + public void testFailingConversion() { + TextField tf = new TextField(); + tf.setConverter(new Converter<String, Integer>() { + + @Override + public Integer convertToModel(String value, Locale locale) { + throw new ConversionException("Failed"); + } + + @Override + public String convertToPresentation(Integer value, Locale locale) { + throw new ConversionException("Failed"); + } + + @Override + public Class<Integer> getModelType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Class<String> getPresentationType() { + // TODO Auto-generated method stub + return null; + } + }); + try { + tf.setValue(1); + fail("setValue(Integer) should throw an exception"); + } catch (Converter.ConversionException e) { + // OK, expected + } + } + + public void testIntegerStringConversion() { + TextField tf = new TextField(); + + tf.setConverter(new StringToIntegerConverter()); + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, "age")); + assertEquals(34, tf.getPropertyDataSource().getValue()); + assertEquals("34", tf.getValue()); + tf.setValue("12"); + assertEquals(12, tf.getPropertyDataSource().getValue()); + assertEquals("12", tf.getValue()); + tf.getPropertyDataSource().setValue(42); + assertEquals(42, tf.getPropertyDataSource().getValue()); + assertEquals("42", tf.getValue()); + } + + public void testBooleanNullConversion() { + CheckBox cb = new CheckBox(); + cb.setConverter(new Converter<Boolean, Boolean>() { + + @Override + public Boolean convertToModel(Boolean value, Locale locale) { + // value from a CheckBox should never be null as long as it is + // not set to null (handled by conversion below). + assertNotNull(value); + return value; + } + + @Override + public Boolean convertToPresentation(Boolean value, Locale locale) { + // Datamodel -> field + if (value == null) { + return false; + } + + return value; + } + + @Override + public Class<Boolean> getModelType() { + return Boolean.class; + } + + @Override + public Class<Boolean> getPresentationType() { + return Boolean.class; + } + + }); + MethodProperty<Boolean> property = new MethodProperty<Boolean>( + paulaBean, "deceased"); + cb.setPropertyDataSource(property); + assertEquals(Boolean.FALSE, property.getValue()); + assertEquals(Boolean.FALSE, cb.getValue()); + Boolean newDmValue = cb.getConverter().convertToPresentation( + cb.getValue(), new Locale("fi", "FI")); + assertEquals(Boolean.FALSE, newDmValue); + + // FIXME: Should be able to set to false here to cause datamodel to be + // set to false but the change will not be propagated to the Property + // (field value is already false) + + cb.setValue(true); + assertEquals(Boolean.TRUE, cb.getValue()); + assertEquals(Boolean.TRUE, property.getValue()); + + cb.setValue(false); + assertEquals(Boolean.FALSE, cb.getValue()); + assertEquals(Boolean.FALSE, property.getValue()); + + } + + public static class NumberBean { + private Number number; + + public Number getNumber() { + return number; + } + + public void setNumber(Number number) { + this.number = number; + } + + } + + public void testNumberDoubleConverterChange() { + final Application a = new Application(); + Application.setCurrent(a); + TextField tf = new TextField() { + @Override + public Application getApplication() { + return a; + } + }; + NumberBean nb = new NumberBean(); + nb.setNumber(490); + + tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number")); + assertEquals(490, tf.getPropertyDataSource().getValue()); + assertEquals("490", tf.getValue()); + + Converter c1 = tf.getConverter(); + + tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number")); + Converter c2 = tf.getConverter(); + assertTrue( + "StringToNumber converter is ok for integer types and should stay even though property is changed", + c1 == c2); + assertEquals(490, tf.getPropertyDataSource().getValue()); + assertEquals("490", tf.getValue()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java new file mode 100644 index 0000000000..25430fc9a5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java @@ -0,0 +1,48 @@ +package com.vaadin.tests.server.component.abstractfield; + +import java.math.BigDecimal; +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.tests.data.bean.Address; +import com.vaadin.tests.data.bean.Country; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.data.bean.Sex; +import com.vaadin.ui.TextField; + +public class DefaultConverterFactory extends TestCase { + + Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", + 34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", + Country.FINLAND)); + { + paulaBean.setSalary(49000); + BigDecimal rent = new BigDecimal(57223); + rent = rent.scaleByPowerOfTen(-2); + paulaBean.setRent(rent); + } + + public void testDefaultNumberConversion() { + Application app = new Application(); + Application.setCurrent(app); + TextField tf = new TextField(); + tf.setLocale(new Locale("en", "US")); + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, + "salary")); + assertEquals("49,000", tf.getValue()); + + tf.setLocale(new Locale("fi", "FI")); + // FIXME: The following line should not be necessary and should be + // removed + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, + "salary")); + String value = tf.getValue(); + // Java uses a non-breaking space (ascii 160) instead of space when + // formatting + String expected = "49" + (char) 160 + "000"; + assertEquals(expected, value); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java new file mode 100644 index 0000000000..5dbab8467e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java @@ -0,0 +1,101 @@ +package com.vaadin.tests.server.component.abstractfield; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.data.Property; +import com.vaadin.data.util.AbstractProperty; +import com.vaadin.data.util.converter.Converter.ConversionException; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.UI; + +public class RemoveListenersOnDetach { + + int numValueChanges = 0; + int numReadOnlyChanges = 0; + + AbstractField field = new AbstractField() { + private UI uI = new UI() { + + @Override + protected void init(WrappedRequest request) { + + } + + }; + private Application application = new Application() { + + }; + + @Override + public Class<?> getType() { + return String.class; + } + + @Override + public void valueChange(Property.ValueChangeEvent event) { + super.valueChange(event); + numValueChanges++; + } + + @Override + public void readOnlyStatusChange( + Property.ReadOnlyStatusChangeEvent event) { + super.readOnlyStatusChange(event); + numReadOnlyChanges++; + } + + @Override + public com.vaadin.ui.UI getUI() { + return uI; + }; + + @Override + public Application getApplication() { + return application; + }; + }; + + Property property = new AbstractProperty() { + @Override + public Object getValue() { + return null; + } + + @Override + public void setValue(Object newValue) throws ReadOnlyException, + ConversionException { + fireValueChange(); + } + + @Override + public Class<?> getType() { + return String.class; + } + }; + + @Test + public void testAttachDetach() { + field.setPropertyDataSource(property); + + property.setValue(null); + property.setReadOnly(true); + assertEquals(1, numValueChanges); + assertEquals(1, numReadOnlyChanges); + + field.attach(); + property.setValue(null); + property.setReadOnly(false); + assertEquals(2, numValueChanges); + assertEquals(2, numReadOnlyChanges); + + field.detach(); + property.setValue(null); + property.setReadOnly(true); + assertEquals(2, numValueChanges); + assertEquals(2, numReadOnlyChanges); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java new file mode 100644 index 0000000000..9937bf92d5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java @@ -0,0 +1,21 @@ +package com.vaadin.tests.server.component.abstractfield; + +import com.vaadin.data.Property.ReadOnlyStatusChangeEvent; +import com.vaadin.data.Property.ReadOnlyStatusChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.CheckBox; + +public class TestAbstractFieldListeners extends AbstractListenerMethodsTest { + public void testReadOnlyStatusChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CheckBox.class, + ReadOnlyStatusChangeEvent.class, + ReadOnlyStatusChangeListener.class); + } + + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CheckBox.class, ValueChangeEvent.class, + ValueChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java new file mode 100644 index 0000000000..1971fb6d0e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java @@ -0,0 +1,115 @@ +package com.vaadin.tests.server.component.abstractorderedlayout; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; +import com.vaadin.ui.VerticalLayout; + +public class AddComponentsTest { + + Component[] children = new Component[] { new Label("A"), new Label("B"), + new Label("C"), new Label("D") }; + + @Test + public void moveComponentsBetweenLayouts() { + AbstractOrderedLayout layout1 = new HorizontalLayout(); + AbstractOrderedLayout layout2 = new VerticalLayout(); + + layout1.addComponent(children[0]); + layout1.addComponent(children[1]); + + layout2.addComponent(children[2]); + layout2.addComponent(children[3]); + + layout2.addComponent(children[1], 1); + assertOrder(layout1, new int[] { 0 }); + assertOrder(layout2, new int[] { 2, 1, 3 }); + + layout1.addComponent(children[3], 0); + assertOrder(layout1, new int[] { 3, 0 }); + assertOrder(layout2, new int[] { 2, 1 }); + + layout2.addComponent(children[0]); + assertOrder(layout1, new int[] { 3 }); + assertOrder(layout2, new int[] { 2, 1, 0 }); + + layout1.addComponentAsFirst(children[1]); + assertOrder(layout1, new int[] { 1, 3 }); + assertOrder(layout2, new int[] { 2, 0 }); + } + + @Test + public void shuffleChildComponents() { + shuffleChildComponents(new HorizontalLayout()); + shuffleChildComponents(new VerticalLayout()); + } + + private void shuffleChildComponents(AbstractOrderedLayout layout) { + + for (int i = 0; i < children.length; ++i) { + layout.addComponent(children[i], i); + } + + assertOrder(layout, new int[] { 0, 1, 2, 3 }); + + // Move C from #2 to #1 + // Exhibits defect #7668 + layout.addComponent(children[2], 1); + assertOrder(layout, new int[] { 0, 2, 1, 3 }); + + // Move C from #1 to #4 (which becomes #3 when #1 is erased) + layout.addComponent(children[2], 4); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Keep everything in place + layout.addComponent(children[1], 1); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Move D from #2 to #0 + layout.addComponent(children[3], 0); + assertOrder(layout, new int[] { 3, 0, 1, 2 }); + + // Move A from #1 to end (#4 which becomes #3) + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Keep everything in place + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Move C from #2 to #0 + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + + // Keep everything in place + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + } + + /** + * Asserts that layout has the components in children in the order specified + * by indices. + */ + private void assertOrder(Layout layout, int[] indices) { + Iterator<?> i = layout.getComponentIterator(); + try { + for (int index : indices) { + assertSame(children[index], i.next()); + } + assertFalse("Too many components in layout", i.hasNext()); + } catch (NoSuchElementException e) { + fail("Too few components in layout"); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java new file mode 100644 index 0000000000..a0b34aca78 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.abstractorderedlayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.VerticalLayout; + +public class TestAbstractOrderedLayoutListeners extends + AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(VerticalLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java new file mode 100644 index 0000000000..75c19b0517 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.abstractselect; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.ComboBox; + +public class TestAbstractSelectListeners extends AbstractListenerMethodsTest { + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(ComboBox.class, ItemSetChangeEvent.class, + ItemSetChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(ComboBox.class, PropertySetChangeEvent.class, + PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java new file mode 100644 index 0000000000..2b6cdaa6cc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.abstractsplitpanel; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.AbstractSplitPanel.SplitterClickEvent; +import com.vaadin.ui.AbstractSplitPanel.SplitterClickListener; +import com.vaadin.ui.HorizontalSplitPanel; + +public class TestAbstractSplitPanelListeners extends + AbstractListenerMethodsTest { + public void testSplitterClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(HorizontalSplitPanel.class, + SplitterClickEvent.class, SplitterClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java new file mode 100644 index 0000000000..9868d6ebfd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.abstracttextfield; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.event.FieldEvents.TextChangeEvent; +import com.vaadin.event.FieldEvents.TextChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.TextField; + +public class TestAbstractTextFieldListeners extends AbstractListenerMethodsTest { + public void testTextChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, TextChangeEvent.class, + TextChangeListener.class); + } + + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java new file mode 100644 index 0000000000..4fe499a0a0 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java @@ -0,0 +1,48 @@ +package com.vaadin.tests.server.component.button; + +import static org.junit.Assert.assertEquals; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; + +import org.junit.Test; + +/** + * Tests the public click() method. + */ +public class ButtonClick { + private boolean clicked = false; + + @Test + public void testClick() { + getButton().click(); + assertEquals(clicked, true); + } + + @Test + public void testClickDisabled() { + Button b = getButton(); + b.setEnabled(false); + b.click(); + assertEquals(clicked, false); + } + + @Test + public void testClickReadOnly() { + Button b = getButton(); + b.setReadOnly(true); + b.click(); + assertEquals(clicked, false); + } + + private Button getButton() { + Button b = new Button(); + b.addListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent ev) { + clicked = true; + } + }); + return b; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java b/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java new file mode 100644 index 0000000000..dc37312eea --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.button; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; + +public class ButtonListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, BlurEvent.class, + BlurListener.class); + } + + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java b/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java new file mode 100644 index 0000000000..c0d739b597 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java @@ -0,0 +1,109 @@ +package com.vaadin.tests.server.component.csslayout; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; + +public class AddComponentsTest { + + private Component[] children = new Component[] { new Label("A"), + new Label("B"), new Label("C"), new Label("D") }; + + @Test + public void moveComponentsBetweenLayouts() { + CssLayout layout1 = new CssLayout(); + CssLayout layout2 = new CssLayout(); + + layout1.addComponent(children[0]); + layout1.addComponent(children[1]); + + layout2.addComponent(children[2]); + layout2.addComponent(children[3]); + + layout2.addComponent(children[1], 1); + assertOrder(layout1, new int[] { 0 }); + assertOrder(layout2, new int[] { 2, 1, 3 }); + + layout1.addComponent(children[3], 0); + assertOrder(layout1, new int[] { 3, 0 }); + assertOrder(layout2, new int[] { 2, 1 }); + + layout2.addComponent(children[0]); + assertOrder(layout1, new int[] { 3 }); + assertOrder(layout2, new int[] { 2, 1, 0 }); + + layout1.addComponentAsFirst(children[1]); + assertOrder(layout1, new int[] { 1, 3 }); + assertOrder(layout2, new int[] { 2, 0 }); + } + + @Test + public void shuffleChildComponents() { + CssLayout layout = new CssLayout(); + + for (int i = 0; i < children.length; ++i) { + layout.addComponent(children[i], i); + } + + assertOrder(layout, new int[] { 0, 1, 2, 3 }); + + // Move C from #2 to #1 + // Exhibits defect #7668 + layout.addComponent(children[2], 1); + assertOrder(layout, new int[] { 0, 2, 1, 3 }); + + // Move C from #1 to #4 (which becomes #3 when #1 is erased) + layout.addComponent(children[2], 4); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Keep everything in place + layout.addComponent(children[1], 1); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Move D from #2 to #0 + layout.addComponent(children[3], 0); + assertOrder(layout, new int[] { 3, 0, 1, 2 }); + + // Move A from #1 to end (#4 which becomes #3) + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Keep everything in place + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Move C from #2 to #0 + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + + // Keep everything in place + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + } + + /** + * Asserts that layout has the components in children in the order specified + * by indices. + */ + private void assertOrder(Layout layout, int[] indices) { + Iterator<?> i = layout.getComponentIterator(); + try { + for (int index : indices) { + assertSame(children[index], i.next()); + } + assertFalse("Too many components in layout", i.hasNext()); + } catch (NoSuchElementException e) { + fail("Too few components in layout"); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java new file mode 100644 index 0000000000..21a48888d6 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.csslayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.CssLayout; + +public class CssLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CssLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java new file mode 100644 index 0000000000..0f4aee35c7 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.datefield; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.DateField; + +public class DateFieldListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(DateField.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(DateField.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java b/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java new file mode 100644 index 0000000000..00b5c60dad --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java @@ -0,0 +1,61 @@ +package com.vaadin.tests.server.component.datefield; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import com.vaadin.tests.util.TestUtil; +import com.vaadin.ui.DateField.Resolution; + +public class ResolutionTest extends TestCase { + + public void testResolutionHigherOrEqualToYear() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsHigherOrEqualTo(Resolution.YEAR); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.YEAR); + TestUtil.assertIterableEquals(expected, higherOrEqual); + } + + public void testResolutionHigherOrEqualToDay() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsHigherOrEqualTo(Resolution.DAY); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.DAY); + expected.add(Resolution.MONTH); + expected.add(Resolution.YEAR); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } + + public void testResolutionLowerThanDay() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.DAY); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.HOUR); + expected.add(Resolution.MINUTE); + expected.add(Resolution.SECOND); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } + + public void testResolutionLowerThanSecond() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.SECOND); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + TestUtil.assertIterableEquals(expected, higherOrEqual); + } + + public void testResolutionLowerThanYear() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.YEAR); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.MONTH); + expected.add(Resolution.DAY); + expected.add(Resolution.HOUR); + expected.add(Resolution.MINUTE); + expected.add(Resolution.SECOND); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java b/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java new file mode 100644 index 0000000000..7512f0f499 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.embedded; + +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Embedded; + +public class EmbeddedListeners extends AbstractListenerMethodsTest { + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Embedded.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java new file mode 100644 index 0000000000..ce3a9faa65 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.gridlayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.GridLayout; + +public class GridLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(GridLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java new file mode 100644 index 0000000000..48279c7c88 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.server.component.label; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.Property; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.ui.Label; + +public class LabelConverters extends TestCase { + + public void testLabelSetDataSourceLaterOn() { + Person p = Person.createTestPerson1(); + Label l = new Label("My label"); + assertEquals("My label", l.getValue()); + assertNull(l.getConverter()); + l.setPropertyDataSource(new MethodProperty<String>(p, "firstName")); + assertEquals(p.getFirstName(), l.getValue()); + p.setFirstName("123"); + assertEquals("123", l.getValue()); + } + + public void testIntegerDataSource() { + Application.setCurrent(new Application()); + Label l = new Label("Foo"); + Property ds = new MethodProperty<Integer>(Person.createTestPerson1(), + "age"); + l.setPropertyDataSource(ds); + assertEquals(String.valueOf(Person.createTestPerson1().getAge()), + l.getValue()); + } + + public void testSetValueWithDataSource() { + try { + MethodProperty<String> property = new MethodProperty<String>( + Person.createTestPerson1(), "firstName"); + Label l = new Label(property); + l.setValue("Foo"); + fail("setValue should throw an exception when a data source is set"); + } catch (Exception e) { + } + + } + + public void testLabelWithoutDataSource() { + Label l = new Label("My label"); + assertEquals("My label", l.getValue()); + assertNull(l.getConverter()); + assertNull(l.getPropertyDataSource()); + l.setValue("New value"); + assertEquals("New value", l.getValue()); + assertNull(l.getConverter()); + assertNull(l.getPropertyDataSource()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java b/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java new file mode 100644 index 0000000000..3ed79f5010 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.label; + +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Label; +import com.vaadin.ui.Label.ValueChangeEvent; + +public class LabelListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Label.class, ValueChangeEvent.class, + ValueChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java b/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java new file mode 100644 index 0000000000..fd3e02994c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.loginform; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.LoginForm; +import com.vaadin.ui.LoginForm.LoginEvent; +import com.vaadin.ui.LoginForm.LoginListener; + +public class LoginFormListeners extends AbstractListenerMethodsTest { + public void testLoginListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(LoginForm.class, LoginEvent.class, + LoginListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java b/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java new file mode 100644 index 0000000000..f304315ebc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java @@ -0,0 +1,98 @@ +package com.vaadin.tests.server.component.menubar; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.Command; +import com.vaadin.ui.MenuBar.MenuItem; + +public class MenuBarIds extends TestCase implements Command { + + private MenuItem lastSelectedItem; + private MenuItem menuFile; + private MenuItem menuEdit; + private MenuItem menuEditCopy; + private MenuItem menuEditCut; + private MenuItem menuEditPaste; + private MenuItem menuEditFind; + private MenuItem menuFileOpen; + private MenuItem menuFileSave; + private MenuItem menuFileExit; + private Set<MenuItem> menuItems = new HashSet<MenuItem>(); + + private MenuBar menuBar; + + @Override + public void setUp() { + menuBar = new MenuBar(); + menuFile = menuBar.addItem("File", this); + menuEdit = menuBar.addItem("Edit", this); + menuEditCopy = menuEdit.addItem("Copy", this); + menuEditCut = menuEdit.addItem("Cut", this); + menuEditPaste = menuEdit.addItem("Paste", this); + menuEdit.addSeparator(); + menuEditFind = menuEdit.addItem("Find...", this); + menuFileOpen = menuFile.addItem("Open", this); + menuFileSave = menuFile.addItem("Save", this); + menuFile.addSeparator(); + menuFileExit = menuFile.addItem("Exit", this); + + menuItems.add(menuFile); + menuItems.add(menuEdit); + menuItems.add(menuEditCopy); + menuItems.add(menuEditCut); + menuItems.add(menuEditPaste); + menuItems.add(menuEditFind); + menuItems.add(menuFileOpen); + menuItems.add(menuFileSave); + menuItems.add(menuFileExit); + } + + public void testMenubarIdUniqueness() { + // Ids within a menubar must be unique + assertUniqueIds(menuBar); + + menuBar.removeItem(menuFile); + MenuItem file2 = menuBar.addItem("File2", this); + MenuItem file3 = menuBar.addItem("File3", this); + MenuItem file2sub = file2.addItem("File2 sub menu", this); + menuItems.add(file2); + menuItems.add(file2sub); + menuItems.add(file3); + + assertUniqueIds(menuBar); + } + + private static void assertUniqueIds(MenuBar menuBar) { + + Set<Object> ids = new HashSet<Object>(); + + for (MenuItem item : menuBar.getItems()) { + assertUniqueIds(ids, item); + } + } + + private static void assertUniqueIds(Set<Object> ids, MenuItem item) { + int id = item.getId(); + System.out.println("Item " + item.getText() + ", id: " + id); + assertFalse(ids.contains(id)); + ids.add(id); + if (item.getChildren() != null) { + for (MenuItem subItem : item.getChildren()) { + assertUniqueIds(ids, subItem); + } + } + } + + @Override + public void menuSelected(MenuItem selectedItem) { + assertNull("lastSelectedItem was not cleared before selecting an item", + lastSelectedItem); + + lastSelectedItem = selectedItem; + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java b/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java new file mode 100644 index 0000000000..7eb35c3882 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.optiongroup; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.OptionGroup; + +public class OptionGroupListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(OptionGroup.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(OptionGroup.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java b/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java new file mode 100644 index 0000000000..6a9d55d7e4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java @@ -0,0 +1,49 @@ +package com.vaadin.tests.server.component.orderedlayout; + +import java.util.Iterator; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +public class TestOrderedLayout extends TestCase { + + public void testVLIteration() { + testIndexing(new VerticalLayout(), 10); + } + + public void testHLIteration() { + testIndexing(new HorizontalLayout(), 12); + } + + public void testIndexing(AbstractOrderedLayout aol, int nrComponents) { + Component[] components = generateComponents(nrComponents); + for (Component c : components) { + aol.addComponent(c); + } + for (int i = 0; i < nrComponents; i++) { + assert (aol.getComponent(i) == components[i]); + assert (aol.getComponentIndex(components[i]) == i); + } + + // Iteration should be in indexed order + int idx = 0; + for (Iterator<Component> i = aol.getComponentIterator(); i.hasNext();) { + Component c = i.next(); + assert (aol.getComponentIndex(c) == idx++); + } + } + + private Component[] generateComponents(int nr) { + Component[] components = new Component[nr]; + for (int i = 0; i < nr; i++) { + components[i] = new Label("" + i); + } + + return components; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java b/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java new file mode 100644 index 0000000000..275e90f5d1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.panel; + +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Panel; + +public class PanelListeners extends AbstractListenerMethodsTest { + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Panel.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java b/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java new file mode 100644 index 0000000000..12a5a0f520 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.popupview; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupView; +import com.vaadin.ui.PopupView.PopupVisibilityEvent; +import com.vaadin.ui.PopupView.PopupVisibilityListener; + +public class PopupViewListeners extends AbstractListenerMethodsTest { + public void testPopupVisibilityListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(PopupView.class, PopupVisibilityEvent.class, + PopupVisibilityListener.class, new PopupView("", new Label())); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java new file mode 100644 index 0000000000..906d6ccebd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java @@ -0,0 +1,137 @@ +package com.vaadin.tests.server.component.root; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.Application; +import com.vaadin.Application.ApplicationStartEvent; +import com.vaadin.UIRequiresMoreInformationException; +import com.vaadin.server.DefaultUIProvider; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.UI; + +public class CustomUIClassLoader extends TestCase { + + /** + * Stub root + */ + public static class MyUI extends UI { + @Override + protected void init(WrappedRequest request) { + // Nothing to see here + } + } + + /** + * Dummy ClassLoader that just saves the name of the requested class before + * delegating to the default implementation. + */ + public class LoggingClassLoader extends ClassLoader { + + private List<String> requestedClasses = new ArrayList<String>(); + + @Override + protected synchronized Class<?> loadClass(String name, boolean resolve) + throws ClassNotFoundException { + requestedClasses.add(name); + return super.loadClass(name, resolve); + } + } + + /** + * Tests that a UI class can be loaded even if no classloader has been + * provided. + * + * @throws Exception + * if thrown + */ + public void testWithNullClassLoader() throws Exception { + Application application = createStubApplication(); + application.start(new ApplicationStartEvent(null, + createConfigurationMock(), null)); + + UI uI = application.getUIForRequest(createRequestMock(null)); + assertTrue(uI instanceof MyUI); + } + + private static DeploymentConfiguration createConfigurationMock() { + DeploymentConfiguration configurationMock = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(configurationMock.isProductionMode()).andReturn(false); + EasyMock.expect(configurationMock.getInitParameters()).andReturn( + new Properties()); + + EasyMock.replay(configurationMock); + return configurationMock; + } + + private static WrappedRequest createRequestMock(ClassLoader classloader) { + // Mock a DeploymentConfiguration to give the passed classloader + DeploymentConfiguration configurationMock = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(configurationMock.getClassLoader()).andReturn( + classloader); + + // Mock a WrappedRequest to give the mocked deployment configuration + WrappedRequest requestMock = EasyMock.createMock(WrappedRequest.class); + EasyMock.expect(requestMock.getDeploymentConfiguration()).andReturn( + configurationMock); + + EasyMock.replay(configurationMock, requestMock); + return requestMock; + } + + /** + * Tests that the ClassLoader passed in the ApplicationStartEvent is used to + * load UI classes. + * + * @throws Exception + * if thrown + */ + public void testWithClassLoader() throws Exception { + LoggingClassLoader loggingClassLoader = new LoggingClassLoader(); + + Application application = createStubApplication(); + application.start(new ApplicationStartEvent(null, + createConfigurationMock(), null)); + + UI uI = application + .getUIForRequest(createRequestMock(loggingClassLoader)); + assertTrue(uI instanceof MyUI); + assertEquals(1, loggingClassLoader.requestedClasses.size()); + assertEquals(MyUI.class.getName(), + loggingClassLoader.requestedClasses.get(0)); + + } + + private Application createStubApplication() { + return new Application() { + { + addUIProvider(new DefaultUIProvider()); + } + + @Override + public String getProperty(String name) { + if (name.equals(UI_PARAMETER)) { + return MyUI.class.getName(); + } else { + return super.getProperty(name); + } + } + + @Override + public UI getUIForRequest(WrappedRequest request) + throws UIRequiresMoreInformationException { + // Always create a new root for testing (can't directly use + // getRoot as it's protected) + return getUI(request); + } + }; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java b/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java new file mode 100644 index 0000000000..c7703303d3 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.select; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Select; + +public class SelectListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Select.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Select.class, BlurEvent.class, + BlurListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java b/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java new file mode 100644 index 0000000000..b969bf5e53 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.slider; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.ui.Slider; +import com.vaadin.ui.Slider.ValueOutOfBoundsException; + +public class SliderTest extends TestCase { + + public void testOutOfBounds() { + Slider s = new Slider(0, 10); + s.setValue(0); + Assert.assertEquals(0.0, s.getValue()); + s.setValue(10); + Assert.assertEquals(10.0, s.getValue()); + try { + s.setValue(20); + fail("Should throw out of bounds exception"); + } catch (ValueOutOfBoundsException e) { + // TODO: handle exception + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java b/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java new file mode 100644 index 0000000000..299f9c79d4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java @@ -0,0 +1,143 @@ +package com.vaadin.tests.server.component.table; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.Align; + +public class TableColumnAlignments { + + @Test + public void defaultColumnAlignments() { + for (int properties = 0; properties < 10; properties++) { + Table t = TableGenerator.createTableWithDefaultContainer( + properties, 10); + Object[] expected = new Object[properties]; + for (int i = 0; i < properties; i++) { + expected[i] = Align.LEFT; + } + org.junit.Assert.assertArrayEquals("getColumnAlignments", expected, + t.getColumnAlignments()); + } + } + + @Test + public void explicitColumnAlignments() { + int properties = 5; + Table t = TableGenerator + .createTableWithDefaultContainer(properties, 10); + Align[] explicitAlignments = new Align[] { Align.CENTER, Align.LEFT, + Align.RIGHT, Align.RIGHT, Align.LEFT }; + + t.setColumnAlignments(explicitAlignments); + + assertArrayEquals("Explicit visible columns, 5 properties", + explicitAlignments, t.getColumnAlignments()); + } + + @Test + public void invalidColumnAlignmentStrings() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT }; + try { + t.setColumnAlignments(new Align[] { Align.RIGHT, Align.RIGHT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + } + + @Test + public void columnAlignmentForPropertyNotInContainer() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT }; + try { + t.setColumnAlignment("Property 1200", Align.LEFT); + // FIXME: Uncomment as there should be an exception (#6475) + // junit.framework.Assert + // .fail("No exception thrown for property not in container"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + // FIXME: Uncomment as null should be returned (#6474) + // junit.framework.Assert.assertEquals( + // "Column alignment for property not in container returned", + // null, t.getColumnAlignment("Property 1200")); + + } + + @Test + public void invalidColumnAlignmentsLength() { + Table t = TableGenerator.createTableWithDefaultContainer(7, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT }; + + try { + t.setColumnAlignments(new Align[] { Align.LEFT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + try { + t.setColumnAlignments(new Align[] {}); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + try { + t.setColumnAlignments(new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, + Align.LEFT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + } + + @Test + public void explicitColumnAlignmentOneByOne() { + int properties = 5; + Table t = TableGenerator + .createTableWithDefaultContainer(properties, 10); + Align[] explicitAlignments = new Align[] { Align.CENTER, Align.LEFT, + Align.RIGHT, Align.RIGHT, Align.LEFT }; + + Align[] currentAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT }; + + for (int i = 0; i < properties; i++) { + t.setColumnAlignment("Property " + i, explicitAlignments[i]); + currentAlignments[i] = explicitAlignments[i]; + + assertArrayEquals("Explicit visible columns, " + i + + " alignments set", currentAlignments, + t.getColumnAlignments()); + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java b/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java new file mode 100644 index 0000000000..0e63049944 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java @@ -0,0 +1,42 @@ +package com.vaadin.tests.server.component.table; + +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.ui.Table; + +public class TableGenerator { + public static Table createTableWithDefaultContainer(int properties, + int items) { + Table t = new Table(); + + for (int i = 0; i < properties; i++) { + t.addContainerProperty("Property " + i, String.class, null); + } + + for (int j = 0; j < items; j++) { + Item item = t.addItem("Item " + j); + for (int i = 0; i < properties; i++) { + item.getItemProperty("Property " + i).setValue( + "Item " + j + "/Property " + i); + } + } + + return t; + } + + @Test + public void testTableGenerator() { + Table t = createTableWithDefaultContainer(1, 1); + junit.framework.Assert.assertEquals(t.size(), 1); + junit.framework.Assert.assertEquals(t.getContainerPropertyIds().size(), + 1); + + t = createTableWithDefaultContainer(100, 50); + junit.framework.Assert.assertEquals(t.size(), 50); + junit.framework.Assert.assertEquals(t.getContainerPropertyIds().size(), + 100); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java b/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java new file mode 100644 index 0000000000..6cc522f8c7 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java @@ -0,0 +1,41 @@ +package com.vaadin.tests.server.component.table; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnReorderEvent; +import com.vaadin.ui.Table.ColumnReorderListener; +import com.vaadin.ui.Table.ColumnResizeEvent; +import com.vaadin.ui.Table.ColumnResizeListener; +import com.vaadin.ui.Table.FooterClickEvent; +import com.vaadin.ui.Table.FooterClickListener; +import com.vaadin.ui.Table.HeaderClickEvent; +import com.vaadin.ui.Table.HeaderClickListener; + +public class TableListeners extends AbstractListenerMethodsTest { + public void testColumnResizeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ColumnResizeEvent.class, + ColumnResizeListener.class); + } + + public void testItemClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ItemClickEvent.class, + ItemClickListener.class); + } + + public void testFooterClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, FooterClickEvent.class, + FooterClickListener.class); + } + + public void testHeaderClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, HeaderClickEvent.class, + HeaderClickListener.class); + } + + public void testColumnReorderListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ColumnReorderEvent.class, + ColumnReorderListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java b/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java new file mode 100644 index 0000000000..ee6349093c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.table; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.Table; + +public class TableSerialization extends TestCase { + + public void testSerialization() { + Table t = new Table(); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + + } + + public void testSerializationWithRowHeaders() { + Table t = new Table(); + t.setRowHeaderMode(Table.ROW_HEADER_MODE_EXPLICIT); + t.setColumnWidth(null, 100); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java b/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java new file mode 100644 index 0000000000..be312044db --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java @@ -0,0 +1,75 @@ +package com.vaadin.tests.server.component.table; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +import com.vaadin.ui.Table; + +public class TableVisibleColumns { + + String[] defaultColumns3 = new String[] { "Property 0", "Property 1", + "Property 2" }; + + @Test + public void defaultVisibleColumns() { + for (int properties = 0; properties < 10; properties++) { + Table t = TableGenerator.createTableWithDefaultContainer( + properties, 10); + Object[] expected = new Object[properties]; + for (int i = 0; i < properties; i++) { + expected[i] = "Property " + i; + } + org.junit.Assert.assertArrayEquals("getVisibleColumns", expected, + t.getVisibleColumns()); + } + } + + @Test + public void explicitVisibleColumns() { + Table t = TableGenerator.createTableWithDefaultContainer(5, 10); + Object[] newVisibleColumns = new Object[] { "Property 1", "Property 2" }; + t.setVisibleColumns(newVisibleColumns); + assertArrayEquals("Explicit visible columns, 5 properties", + newVisibleColumns, t.getVisibleColumns()); + + } + + @Test + public void invalidVisibleColumnIds() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + + try { + t.setVisibleColumns(new Object[] { "a", "Property 2", "Property 3" }); + junit.framework.Assert.fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // OK, expected + } + assertArrayEquals(defaultColumns3, t.getVisibleColumns()); + } + + @Test + public void duplicateVisibleColumnIds() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + try { + t.setVisibleColumns(new Object[] { "Property 0", "Property 1", + "Property 2", "Property 1" }); + // FIXME: Multiple properties in the Object array should be detected + // (#6476) + // junit.framework.Assert.fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // OK, expected + } + // FIXME: Multiple properties in the Object array should be detected + // (#6476) + // assertArrayEquals(defaultColumns3, t.getVisibleColumns()); + } + + @Test + public void noVisibleColumns() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + t.setVisibleColumns(new Object[] {}); + assertArrayEquals(new Object[] {}, t.getVisibleColumns()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java b/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java new file mode 100644 index 0000000000..647d13855b --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java @@ -0,0 +1,94 @@ +package com.vaadin.tests.server.component.table; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.Table; + +/** + * Test case for testing the footer API + * + */ +public class TestFooter extends TestCase { + + /** + * Tests if setting the footer visibility works properly + */ + public void testFooterVisibility() { + Table table = new Table("Test table", createContainer()); + + // The footer should by default be hidden + assertFalse(table.isFooterVisible()); + + // Set footer visibility to tru should be reflected in the + // isFooterVisible() method + table.setFooterVisible(true); + assertTrue(table.isFooterVisible()); + } + + /** + * Tests adding footers to the columns + */ + public void testAddingFooters() { + Table table = new Table("Test table", createContainer()); + + // Table should not contain any footers at initialization + assertNull(table.getColumnFooter("col1")); + assertNull(table.getColumnFooter("col2")); + assertNull(table.getColumnFooter("col3")); + + // Adding column footer + table.setColumnFooter("col1", "Footer1"); + assertEquals("Footer1", table.getColumnFooter("col1")); + + // Add another footer + table.setColumnFooter("col2", "Footer2"); + assertEquals("Footer2", table.getColumnFooter("col2")); + + // Add footer for a non-existing column + table.setColumnFooter("fail", "FooterFail"); + } + + /** + * Test removing footers + */ + public void testRemovingFooters() { + Table table = new Table("Test table", createContainer()); + table.setColumnFooter("col1", "Footer1"); + table.setColumnFooter("col2", "Footer2"); + + // Test removing footer + assertNotNull(table.getColumnFooter("col1")); + table.setColumnFooter("col1", null); + assertNull(table.getColumnFooter("col1")); + + // The other footer should still be there + assertNotNull(table.getColumnFooter("col2")); + + // Remove non-existing footer + table.setColumnFooter("fail", null); + } + + /** + * Creates a container with three properties "col1,col2,col3" with 100 items + * + * @return Returns the created table + */ + private static Container createContainer() { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty("col1", String.class, ""); + container.addContainerProperty("col2", String.class, ""); + container.addContainerProperty("col3", String.class, ""); + + for (int i = 0; i < 100; i++) { + Item item = container.addItem("item " + i); + item.getItemProperty("col1").setValue("first" + i); + item.getItemProperty("col2").setValue("middle" + i); + item.getItemProperty("col3").setValue("last" + i); + } + + return container; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java b/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java new file mode 100644 index 0000000000..767b651b68 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java @@ -0,0 +1,57 @@ +package com.vaadin.tests.server.component.table; + +import java.util.Arrays; +import java.util.Set; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.AbstractSelect.MultiSelectMode; +import com.vaadin.ui.Table; + +public class TestMultipleSelection extends TestCase { + + /** + * Tests weather the multiple select mode is set when using Table.set + */ + @SuppressWarnings("unchecked") + public void testSetMultipleItems() { + Table table = new Table("", createTestContainer()); + + // Tests if multiple selection is set + table.setMultiSelect(true); + assertTrue(table.isMultiSelect()); + + // Test multiselect by setting several items at once + + table.setValue(Arrays.asList("1", new String[] { "3" })); + assertEquals(2, ((Set<String>) table.getValue()).size()); + } + + /** + * Tests setting the multiselect mode of the Table. The multiselect mode + * affects how mouse selection is made in the table by the user. + */ + public void testSetMultiSelectMode() { + Table table = new Table("", createTestContainer()); + + // Default multiselect mode should be MultiSelectMode.DEFAULT + assertEquals(MultiSelectMode.DEFAULT, table.getMultiSelectMode()); + + // Tests if multiselectmode is set + table.setMultiSelectMode(MultiSelectMode.SIMPLE); + assertEquals(MultiSelectMode.SIMPLE, table.getMultiSelectMode()); + } + + /** + * Creates a testing container for the tests + * + * @return A new container with test items + */ + private Container createTestContainer() { + IndexedContainer container = new IndexedContainer(Arrays.asList("1", + new String[] { "2", "3", "4" })); + return container; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java new file mode 100644 index 0000000000..5c01a1c99f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.tabsheet; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +public class TabSheetListeners extends AbstractListenerMethodsTest { + public void testSelectedTabChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TabSheet.class, SelectedTabChangeEvent.class, + SelectedTabChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java new file mode 100644 index 0000000000..0ef8ae5a76 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java @@ -0,0 +1,224 @@ +package com.vaadin.tests.server.component.tabsheet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import java.util.Iterator; + +import org.junit.Test; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.Tab; + +public class TestTabSheet { + + @Test + public void addExistingComponent() { + Component c = new Label("abc"); + TabSheet tabSheet = new TabSheet(); + tabSheet.addComponent(c); + tabSheet.addComponent(c); + + Iterator<Component> iter = tabSheet.getComponentIterator(); + + assertEquals(c, iter.next()); + assertEquals(false, iter.hasNext()); + assertNotNull(tabSheet.getTab(c)); + } + + @Test + public void getComponentFromTab() { + Component c = new Label("abc"); + TabSheet tabSheet = new TabSheet(); + Tab tab = tabSheet.addTab(c); + assertEquals(c, tab.getComponent()); + } + + @Test + public void addTabWithComponentOnly() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + // Check right order of tabs + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab2)); + assertEquals(2, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent()); + + // Check right order of tabs + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab2)); + assertEquals(2, tabSheet.getTabPosition(tab3)); + } + + @Test + public void addTabWithComponentAndIndex() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + Tab tab4 = tabSheet.addTab(new Label("ddd"), 1); + Tab tab5 = tabSheet.addTab(new Label("eee"), 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent(), 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + } + + @Test + public void addTabWithAllParameters() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + Tab tab4 = tabSheet.addTab(new Label("ddd"), "ddd", null, 1); + Tab tab5 = tabSheet.addTab(new Label("eee"), "eee", null, 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent(), "xxx", null, 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + } + + @Test + public void getTabByPosition() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + assertEquals(tab1, tabSheet.getTab(0)); + assertEquals(tab2, tabSheet.getTab(1)); + assertEquals(tab3, tabSheet.getTab(2)); + + assertEquals(null, tabSheet.getTab(3)); + } + + @Test + public void selectTab() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + Label componentNotInSheet = new Label("ddd"); + Tab tabNotInSheet = new TabSheet().addTab(new Label("eee")); + + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // Select tab by component... + tabSheet.setSelectedTab(tab2.getComponent()); + assertEquals(tab2.getComponent(), tabSheet.getSelectedTab()); + + // by tab instance + tabSheet.setSelectedTab(tab3); + assertEquals(tab3.getComponent(), tabSheet.getSelectedTab()); + + // by index + tabSheet.setSelectedTab(0); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // Should be no-op... + tabSheet.setSelectedTab(componentNotInSheet); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // this as well + tabSheet.setSelectedTab(tabNotInSheet); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // and this + tabSheet.setSelectedTab(123); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + } + + @Test + public void replaceComponent() { + TabSheet tabSheet = new TabSheet(); + Label lbl1 = new Label("aaa"); + Label lbl2 = new Label("bbb"); + Label lbl3 = new Label("ccc"); + Label lbl4 = new Label("ddd"); + + Tab tab1 = tabSheet.addTab(lbl1); + tab1.setCaption("tab1"); + tab1.setClosable(true); + Tab tab2 = tabSheet.addTab(lbl2); + tab2.setDescription("description"); + tab2.setEnabled(false); + + // Replace component not in tabsheet with one already in tabsheet - + // should be no-op + tabSheet.replaceComponent(lbl3, lbl2); + assertEquals(2, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertNull(tabSheet.getTab(lbl3)); + + // Replace component not in tabsheet with one not in tabsheet either + // should add lbl4 as last tab + tabSheet.replaceComponent(lbl3, lbl4); + assertEquals(3, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(2, tabSheet.getTabPosition(tabSheet.getTab(lbl4))); + + // Replace component in tabsheet with another + // should swap places, tab association should stay the same but tabs + // should swap metadata + tabSheet.replaceComponent(lbl1, lbl2); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(false, tab1.isClosable()); + assertEquals(true, tab2.isClosable()); + assertEquals(false, tab1.isEnabled()); + assertEquals(true, tab2.isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(null, tab2.getDescription()); + assertEquals(3, tabSheet.getComponentCount()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl1))); + assertEquals(0, tabSheet.getTabPosition(tabSheet.getTab(lbl2))); + + // Replace component in tabsheet with one not in tabsheet + // should create a new tab instance for the new component, old tab + // instance should become unattached + // tab metadata should be copied from old to new + tabSheet.replaceComponent(lbl1, lbl3); + assertEquals(3, tabSheet.getComponentCount()); + assertNull(tabSheet.getTab(lbl1)); + assertNull(tab1.getComponent()); + assertNotNull(tabSheet.getTab(lbl3)); + assertEquals(false, tabSheet.getTab(lbl3).isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl3))); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java b/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java new file mode 100644 index 0000000000..4bb0177a18 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java @@ -0,0 +1,108 @@ +package com.vaadin.tests.server.component.textfield; + +import java.util.Collections; + +import junit.framework.TestCase; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertyFormatter; +import com.vaadin.ui.TextField; + +public class TextFieldWithPropertyFormatter extends TestCase { + + private static final String INPUT_VALUE = "foo"; + private static final String PARSED_VALUE = "BAR"; + private static final String FORMATTED_VALUE = "FOOBAR"; + private static final String ORIGINAL_VALUE = "Original"; + private TextField field; + private PropertyFormatter<String> formatter; + private ObjectProperty<String> property; + private ValueChangeListener listener; + private int listenerCalled; + private int repainted; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + field = new TextField() { + @Override + public void markAsDirty() { + repainted++; + super.markAsDirty(); + } + }; + + formatter = new PropertyFormatter<String>() { + + @Override + public String parse(String formattedValue) throws Exception { + assertEquals(INPUT_VALUE, formattedValue); + return PARSED_VALUE; + } + + @Override + public String format(String value) { + return FORMATTED_VALUE; + } + }; + + property = new ObjectProperty<String>(ORIGINAL_VALUE); + + formatter.setPropertyDataSource(property); + field.setPropertyDataSource(formatter); + + listener = new Property.ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + listenerCalled++; + assertEquals(1, listenerCalled); + assertEquals(FORMATTED_VALUE, event.getProperty().getValue()); + } + }; + + field.addListener(listener); + listenerCalled = 0; + repainted = 0; + } + + public void testWithServerApi() { + checkInitialState(); + + field.setValue(INPUT_VALUE); + + checkEndState(); + + } + + private void checkEndState() { + assertEquals(1, listenerCalled); + // setModified triggers repaint, this is done 2 times. A + // ValueChangeEvent triggers the third + assertEquals(3, repainted); + assertEquals(FORMATTED_VALUE, field.getValue()); + assertEquals(FORMATTED_VALUE, formatter.getValue()); + assertEquals(PARSED_VALUE, property.getValue()); + } + + private void checkInitialState() { + assertEquals(ORIGINAL_VALUE, property.getValue()); + assertEquals(FORMATTED_VALUE, formatter.getValue()); + assertEquals(FORMATTED_VALUE, field.getValue()); + } + + public void testWithSimulatedClientSideChange() { + checkInitialState(); + + field.changeVariables(null, + Collections.singletonMap("text", (Object) INPUT_VALUE)); + + checkEndState(); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java b/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java new file mode 100644 index 0000000000..66535d3ffb --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.tree; + +import junit.framework.TestCase; + +import com.vaadin.ui.Tree; + +public class TestHasChildren extends TestCase { + + private Tree tree; + + @Override + protected void setUp() { + tree = new Tree(); + tree.addItem("parent"); + tree.addItem("child"); + tree.setChildrenAllowed("parent", true); + tree.setParent("child", "parent"); + } + + public void testRemoveChildren() { + assertTrue(tree.hasChildren("parent")); + tree.removeItem("child"); + assertFalse(tree.hasChildren("parent")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java b/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java new file mode 100644 index 0000000000..4984cf161b --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java @@ -0,0 +1,137 @@ +package com.vaadin.tests.server.component.tree; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.ui.Tree; +import com.vaadin.ui.Tree.CollapseEvent; +import com.vaadin.ui.Tree.CollapseListener; +import com.vaadin.ui.Tree.ExpandEvent; +import com.vaadin.ui.Tree.ExpandListener; + +public class TestListeners extends TestCase implements ExpandListener, + CollapseListener { + private int expandCalled; + private int collapseCalled; + private Object lastExpanded; + private Object lastCollapsed; + + @Override + protected void setUp() { + expandCalled = 0; + } + + public void testExpandListener() { + Tree tree = createTree(10, 20, false); + tree.addListener((ExpandListener) this); + List<Object> rootIds = new ArrayList<Object>(tree.rootItemIds()); + + assertEquals(10, rootIds.size()); + assertEquals(10 + 10 * 20 + 10, tree.size()); + + // Expanding should send one expand event for the root item id + tree.expandItem(rootIds.get(0)); + assertEquals(1, expandCalled); + assertEquals(rootIds.get(0), lastExpanded); + + // Expand should send one event for each expanded item id. + // In this case root + child 4 + expandCalled = 0; + tree.expandItemsRecursively(rootIds.get(1)); + assertEquals(2, expandCalled); + List<Object> c = new ArrayList<Object>(tree.getChildren(rootIds.get(1))); + + assertEquals(c.get(4), lastExpanded); + + // Expanding an already expanded item should send no expand event + expandCalled = 0; + tree.expandItem(rootIds.get(0)); + assertEquals(0, expandCalled); + } + + /** + * Creates a tree with "rootItems" roots, each with "children" children, + * each with 1 child. + * + * @param rootItems + * @param children + * @param expand + * @return + */ + private Tree createTree(int rootItems, int children, boolean expand) { + Tree tree = new Tree(); + for (int i = 0; i < rootItems; i++) { + String rootId = "root " + i; + tree.addItem(rootId); + if (expand) { + tree.expandItemsRecursively(rootId); + } else { + tree.collapseItemsRecursively(rootId); + + } + for (int j = 0; j < children; j++) { + String childId = "child " + i + "/" + j; + tree.addItem(childId); + tree.setParent(childId, rootId); + tree.setChildrenAllowed(childId, false); + if (j == 4) { + tree.setChildrenAllowed(childId, true); + Object grandChildId = tree.addItem(); + tree.setParent(grandChildId, childId); + tree.setChildrenAllowed(grandChildId, false); + if (expand) { + tree.expandItemsRecursively(childId); + } else { + tree.collapseItemsRecursively(childId); + } + } + } + } + + return tree; + } + + public void testCollapseListener() { + Tree tree = createTree(7, 15, true); + tree.addListener((CollapseListener) this); + + List<Object> rootIds = new ArrayList<Object>(tree.rootItemIds()); + + assertEquals(7, rootIds.size()); + assertEquals(7 + 7 * 15 + 7, tree.size()); + + // Expanding should send one expand event for the root item id + tree.collapseItem(rootIds.get(0)); + assertEquals(1, collapseCalled); + assertEquals(rootIds.get(0), lastCollapsed); + + // Collapse sends one event for each collapsed node. + // In this case root + child 4 + collapseCalled = 0; + tree.collapseItemsRecursively(rootIds.get(1)); + assertEquals(2, collapseCalled); + List<Object> c = new ArrayList<Object>(tree.getChildren(rootIds.get(1))); + assertEquals(c.get(4), lastCollapsed); + + // Collapsing an already expanded item should send no expand event + collapseCalled = 0; + tree.collapseItem(rootIds.get(0)); + assertEquals(0, collapseCalled); + } + + @Override + public void nodeExpand(ExpandEvent event) { + lastExpanded = event.getItemId(); + expandCalled++; + + } + + @Override + public void nodeCollapse(CollapseEvent event) { + lastCollapsed = event.getItemId(); + collapseCalled++; + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java b/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java new file mode 100644 index 0000000000..e14ebe739d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.tree; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Tree; +import com.vaadin.ui.Tree.CollapseEvent; +import com.vaadin.ui.Tree.CollapseListener; +import com.vaadin.ui.Tree.ExpandEvent; +import com.vaadin.ui.Tree.ExpandListener; + +public class TreeListeners extends AbstractListenerMethodsTest { + public void testExpandListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, ExpandEvent.class, + ExpandListener.class); + } + + public void testItemClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, ItemClickEvent.class, + ItemClickListener.class); + } + + public void testCollapseListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, CollapseEvent.class, + CollapseListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java b/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java new file mode 100644 index 0000000000..535ed8e860 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.treetable; + +import junit.framework.TestCase; + +import com.vaadin.ui.TreeTable; + +public class EmptyTreeTable extends TestCase { + public void testLastId() { + TreeTable treeTable = new TreeTable(); + + assertFalse(treeTable.isLastId(treeTable.getValue())); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java b/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java new file mode 100644 index 0000000000..265e5382d4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java @@ -0,0 +1,41 @@ +package com.vaadin.tests.server.component.upload; + +import com.vaadin.server.StreamVariable.StreamingProgressEvent; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Upload; +import com.vaadin.ui.Upload.FailedEvent; +import com.vaadin.ui.Upload.FailedListener; +import com.vaadin.ui.Upload.FinishedEvent; +import com.vaadin.ui.Upload.FinishedListener; +import com.vaadin.ui.Upload.ProgressListener; +import com.vaadin.ui.Upload.StartedEvent; +import com.vaadin.ui.Upload.StartedListener; +import com.vaadin.ui.Upload.SucceededEvent; +import com.vaadin.ui.Upload.SucceededListener; + +public class UploadListeners extends AbstractListenerMethodsTest { + public void testProgressListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, StreamingProgressEvent.class, + ProgressListener.class); + } + + public void testSucceededListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, SucceededEvent.class, + SucceededListener.class); + } + + public void testStartedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, StartedEvent.class, + StartedListener.class); + } + + public void testFailedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, FailedEvent.class, + FailedListener.class); + } + + public void testFinishedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, FinishedEvent.class, + FinishedListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java new file mode 100644 index 0000000000..88bc28bbc8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java @@ -0,0 +1,79 @@ +package com.vaadin.tests.server.component.window; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.ui.UI; +import com.vaadin.ui.UI.LegacyWindow; +import com.vaadin.ui.Window; + +public class AddRemoveSubWindow { + + public class TestApp extends Application.LegacyApplication { + + @Override + public void init() { + LegacyWindow w = new LegacyWindow("Main window"); + setMainWindow(w); + } + } + + @Test + public void addSubWindow() { + TestApp app = new TestApp(); + app.init(); + Window subWindow = new Window("Sub window"); + UI mainWindow = app.getMainWindow(); + + mainWindow.addWindow(subWindow); + // Added to main window so the parent of the sub window should be the + // main window + assertEquals(subWindow.getParent(), mainWindow); + + try { + mainWindow.addWindow(subWindow); + assertTrue("Window.addWindow did not throw the expected exception", + false); + } catch (IllegalArgumentException e) { + // Should throw an exception as it has already been added to the + // main window + } + + // Try to add the same sub window to another window + try { + LegacyWindow w = new LegacyWindow(); + w.addWindow(subWindow); + assertTrue("Window.addWindow did not throw the expected exception", + false); + } catch (IllegalArgumentException e) { + // Should throw an exception as it has already been added to the + // main window + } + + } + + @Test + public void removeSubWindow() { + TestApp app = new TestApp(); + app.init(); + Window subWindow = new Window("Sub window"); + UI mainWindow = app.getMainWindow(); + mainWindow.addWindow(subWindow); + + // Added to main window so the parent of the sub window should be the + // main window + assertEquals(subWindow.getParent(), mainWindow); + + // Parent should still be set + assertEquals(subWindow.getParent(), mainWindow); + + // Remove from the main window and assert it has been removed + boolean removed = mainWindow.removeWindow(subWindow); + assertTrue("Window was not removed correctly", removed); + assertNull(subWindow.getParent()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java new file mode 100644 index 0000000000..0fb0765c9f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java @@ -0,0 +1,254 @@ +package com.vaadin.tests.server.component.window; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.Label; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class AttachDetachWindow { + + private Application testApp = new Application(); + + private interface TestContainer { + public boolean attachCalled(); + + public boolean detachCalled(); + + public TestContent getTestContent(); + + public Application getApplication(); + } + + private class TestWindow extends Window implements TestContainer { + boolean windowAttachCalled = false; + boolean windowDetachCalled = false; + private TestContent testContent = new TestContent();; + + TestWindow() { + setContent(testContent); + } + + @Override + public void attach() { + super.attach(); + windowAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + windowDetachCalled = true; + } + + @Override + public boolean attachCalled() { + return windowAttachCalled; + } + + @Override + public boolean detachCalled() { + return windowDetachCalled; + } + + @Override + public TestContent getTestContent() { + return testContent; + } + } + + private class TestContent extends VerticalLayout { + boolean contentDetachCalled = false; + boolean childDetachCalled = false; + boolean contentAttachCalled = false; + boolean childAttachCalled = false; + + private Label child = new Label() { + @Override + public void attach() { + super.attach(); + childAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + childDetachCalled = true; + } + }; + + public TestContent() { + addComponent(child); + } + + @Override + public void attach() { + super.attach(); + contentAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + contentDetachCalled = true; + } + } + + private class TestUI extends UI implements TestContainer { + boolean rootAttachCalled = false; + boolean rootDetachCalled = false; + private TestContent testContent = new TestContent();; + + public TestUI() { + setContent(testContent); + } + + @Override + protected void init(WrappedRequest request) { + // Do nothing + } + + @Override + public boolean attachCalled() { + return rootAttachCalled; + } + + @Override + public boolean detachCalled() { + return rootDetachCalled; + } + + @Override + public TestContent getTestContent() { + return testContent; + } + + @Override + public void attach() { + super.attach(); + rootAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + rootDetachCalled = true; + } + } + + TestUI main = new TestUI(); + TestWindow sub = new TestWindow(); + + @Test + public void addSubWindowBeforeAttachingMainWindow() { + assertUnattached(main); + assertUnattached(sub); + + main.addWindow(sub); + assertUnattached(main); + assertUnattached(sub); + + // attaching main should recurse to sub + main.setApplication(testApp); + assertAttached(main); + assertAttached(sub); + } + + @Test + public void addSubWindowAfterAttachingMainWindow() { + assertUnattached(main); + assertUnattached(sub); + + main.setApplication(testApp); + assertAttached(main); + assertUnattached(sub); + + // main is already attached, so attach should be called for sub + main.addWindow(sub); + assertAttached(main); + assertAttached(sub); + } + + @Test + public void removeSubWindowBeforeDetachingMainWindow() { + main.setApplication(testApp); + main.addWindow(sub); + + // sub should be detached when removing from attached main + main.removeWindow(sub); + assertAttached(main); + assertDetached(sub); + + // main detach should recurse to sub + main.setApplication(null); + assertDetached(main); + assertDetached(sub); + } + + @Test + public void removeSubWindowAfterDetachingMainWindow() { + main.setApplication(testApp); + main.addWindow(sub); + + // main detach should recurse to sub + main.setApplication(null); + assertDetached(main); + assertDetached(sub); + + main.removeWindow(sub); + assertDetached(main); + assertDetached(sub); + } + + /** + * Asserts that win and its children are attached to testApp and their + * attach() methods have been called. + */ + private void assertAttached(TestContainer win) { + TestContent testContent = win.getTestContent(); + + assertTrue("window attach not called", win.attachCalled()); + assertTrue("window content attach not called", + testContent.contentAttachCalled); + assertTrue("window child attach not called", + testContent.childAttachCalled); + + assertSame("window not attached", win.getApplication(), testApp); + assertSame("window content not attached", testContent.getApplication(), + testApp); + assertSame("window children not attached", + testContent.child.getApplication(), testApp); + } + + /** + * Asserts that win and its children are not attached. + */ + private void assertUnattached(TestContainer win) { + assertSame("window not detached", win.getApplication(), null); + assertSame("window content not detached", win.getTestContent() + .getApplication(), null); + assertSame("window children not detached", + win.getTestContent().child.getApplication(), null); + } + + /** + * Asserts that win and its children are unattached and their detach() + * methods have been been called. + * + * @param win + */ + private void assertDetached(TestContainer win) { + assertUnattached(win); + assertTrue("window detach not called", win.detachCalled()); + assertTrue("window content detach not called", + win.getTestContent().contentDetachCalled); + assertTrue("window child detach not called", + win.getTestContent().childDetachCalled); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java b/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java new file mode 100644 index 0000000000..c33871cbd8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.component.window; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.CloseEvent; +import com.vaadin.ui.Window.CloseListener; +import com.vaadin.ui.Window.ResizeEvent; +import com.vaadin.ui.Window.ResizeListener; + +public class WindowListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, BlurEvent.class, + BlurListener.class); + } + + public void testResizeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, ResizeEvent.class, + ResizeListener.class); + } + + public void testCloseListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, CloseEvent.class, + CloseListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java new file mode 100644 index 0000000000..e3e743d02a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java @@ -0,0 +1,84 @@ +package com.vaadin.tests.server.componentcontainer; + +import junit.framework.TestCase; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; + +public abstract class AbstractIndexedLayoutTest extends TestCase { + + private Layout layout; + + protected abstract Layout createLayout(); + + @Override + protected void setUp() throws Exception { + layout = createLayout(); + } + + public Layout getLayout() { + return layout; + } + + public void testAddRemoveComponent() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + + assertEquals(c1, getComponent(0)); + assertEquals(1, getComponentCount()); + layout.addComponent(c2); + assertEquals(c1, getComponent(0)); + assertEquals(c2, getComponent(1)); + assertEquals(2, getComponentCount()); + layout.removeComponent(c1); + assertEquals(c2, getComponent(0)); + assertEquals(1, getComponentCount()); + layout.removeComponent(c2); + assertEquals(0, getComponentCount()); + } + + protected abstract int getComponentCount(); + + protected abstract Component getComponent(int index); + + protected abstract int getComponentIndex(Component c); + + public void testGetComponentIndex() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + assertEquals(0, getComponentIndex(c1)); + layout.addComponent(c2); + assertEquals(0, getComponentIndex(c1)); + assertEquals(1, getComponentIndex(c2)); + layout.removeComponent(c1); + assertEquals(0, getComponentIndex(c2)); + layout.removeComponent(c2); + assertEquals(-1, getComponentIndex(c2)); + assertEquals(-1, getComponentIndex(c1)); + } + + public void testGetComponent() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + assertEquals(c1, getComponent(0)); + layout.addComponent(c2); + assertEquals(c1, getComponent(0)); + assertEquals(c2, getComponent(1)); + layout.removeComponent(c1); + assertEquals(c2, getComponent(0)); + layout.removeComponent(c2); + try { + getComponent(0); + fail(); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java new file mode 100644 index 0000000000..828404bd5a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java @@ -0,0 +1,40 @@ +package com.vaadin.tests.server.componentcontainer; + +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; + +public class AddRemoveComponentTest extends TestCase { + + public void testRemoveComponentFromWrongContainer() + throws InstantiationException, IllegalAccessException { + List<Class<? extends ComponentContainer>> containerClasses = VaadinClasses + .getComponentContainersSupportingAddRemoveComponent(); + + // No default constructor, special case + containerClasses.remove(CustomLayout.class); + testRemoveComponentFromWrongContainer(new CustomLayout("dummy")); + + for (Class<? extends ComponentContainer> c : containerClasses) { + testRemoveComponentFromWrongContainer(c.newInstance()); + } + } + + private void testRemoveComponentFromWrongContainer( + ComponentContainer componentContainer) { + HorizontalLayout hl = new HorizontalLayout(); + Label label = new Label(); + hl.addComponent(label); + + componentContainer.removeComponent(label); + assertEquals( + "Parent no longer correct for " + componentContainer.getClass(), + hl, label.getParent()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java new file mode 100644 index 0000000000..dc9667c38e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Layout; + +public class CssLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new CssLayout(); + } + + @Override + public CssLayout getLayout() { + return (CssLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java new file mode 100644 index 0000000000..71a813d423 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.Layout; + +public class FormLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new FormLayout(); + } + + @Override + public FormLayout getLayout() { + return (FormLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java new file mode 100644 index 0000000000..0e3a1d5734 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Layout; +import com.vaadin.ui.VerticalLayout; + +public class VerticalLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new VerticalLayout(); + } + + @Override + public VerticalLayout getLayout() { + return (VerticalLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java b/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java new file mode 100644 index 0000000000..f2de4f3c04 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java @@ -0,0 +1,129 @@ +package com.vaadin.tests.server.components; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.Property.ValueChangeNotifier; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.ui.AbstractField; + +/** + * Base class for tests for checking that value change listeners for fields are + * not called exactly once when they should be, and not at other times. + * + * Does not check all cases (e.g. properties that do not implement + * {@link ValueChangeNotifier}). + * + * Subclasses should implement {@link #setValue()} and call + * <code>super.setValue(AbstractField)</code>. Also, subclasses should typically + * override {@link #setValue(AbstractField)} to set the field value via + * <code>changeVariables()</code>. + */ +public abstract class AbstractTestFieldValueChange<T> extends TestCase { + + private AbstractField<T> field; + private ValueChangeListener listener; + + protected void setUp(AbstractField<T> field) throws Exception { + this.field = field; + listener = EasyMock.createStrictMock(ValueChangeListener.class); + + } + + protected ValueChangeListener getListener() { + return listener; + } + + /** + * Test that listeners are not called when they have been unregistered. + */ + public void testRemoveListener() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(false); + + // Expectations and start test + listener.valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(listener); + + // Add listener and set the value -> should end up in listener once + getField().addListener(listener); + setValue(getField()); + + // Ensure listener was called once + EasyMock.verify(listener); + + // Remove the listener and set the value -> should not end up in + // listener + getField().removeListener(listener); + setValue(getField()); + + // Ensure listener still has been called only once + EasyMock.verify(listener); + } + + /** + * Common unbuffered case: both writeThrough (auto-commit) and readThrough + * are on. Calling commit() should not cause notifications. + * + * Using the readThrough mode allows changes made to the property value to + * be seen in some cases also when there is no notification of value change + * from the property. + * + * Field value change notifications closely mirror value changes of the data + * source behind the field. + */ + public void testNonBuffered() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(false); + + expectValueChangeFromSetValueNotCommit(); + } + + /** + * Fully buffered use where the data source is neither read nor modified + * during editing, and is updated at commit(). + * + * Field value change notifications reflect the buffered value in the field, + * not the original data source value changes. + */ + public void testBuffered() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(true); + + expectValueChangeFromSetValueNotCommit(); + } + + protected void expectValueChangeFromSetValueNotCommit() { + // Expectations and start test + listener.valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(listener); + + // Add listener and set the value -> should end up in listener once + getField().addListener(listener); + setValue(getField()); + + // Ensure listener was called once + EasyMock.verify(listener); + + // commit + getField().commit(); + + // Ensure listener was not called again + EasyMock.verify(listener); + } + + protected AbstractField<T> getField() { + return field; + } + + /** + * Override in subclasses to set value with changeVariables(). + */ + protected void setValue(AbstractField<T> field) { + field.setValue("newValue"); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java new file mode 100644 index 0000000000..3ba1c4c7f1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java @@ -0,0 +1,345 @@ +package com.vaadin.tests.server.components; + +import java.util.Iterator; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbsoluteLayout; +import com.vaadin.ui.AbsoluteLayout.ComponentPosition; +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.ComponentContainer.ComponentAttachEvent; +import com.vaadin.ui.ComponentContainer.ComponentAttachListener; +import com.vaadin.ui.ComponentContainer.ComponentDetachEvent; +import com.vaadin.ui.ComponentContainer.ComponentDetachListener; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.GridLayout.Area; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; + +public class ComponentAttachDetachListenerTest extends TestCase { + + private AbstractOrderedLayout olayout; + private GridLayout gridlayout; + private AbsoluteLayout absolutelayout; + private CssLayout csslayout; + + // General variables + private int attachCounter = 0; + private Component attachedComponent = null; + private ComponentContainer attachTarget = null; + private boolean foundInContainer = false; + + private int detachCounter = 0; + private Component detachedComponent = null; + private ComponentContainer detachedTarget = null; + + // Ordered layout specific variables + private int indexOfComponent = -1; + + // Grid layout specific variables + private Area componentArea = null; + + // Absolute layout specific variables + private ComponentPosition componentPosition = null; + + private class MyAttachListener implements ComponentAttachListener { + @Override + public void componentAttachedToContainer(ComponentAttachEvent event) { + attachCounter++; + attachedComponent = event.getAttachedComponent(); + attachTarget = event.getContainer(); + + // Search for component in container (should be found) + Iterator<Component> iter = attachTarget.getComponentIterator(); + while (iter.hasNext()) { + if (iter.next() == attachedComponent) { + foundInContainer = true; + break; + } + } + + // Get layout specific variables + if (attachTarget instanceof AbstractOrderedLayout) { + indexOfComponent = ((AbstractOrderedLayout) attachTarget) + .getComponentIndex(attachedComponent); + } else if (attachTarget instanceof GridLayout) { + componentArea = ((GridLayout) attachTarget) + .getComponentArea(attachedComponent); + } else if (attachTarget instanceof AbsoluteLayout) { + componentPosition = ((AbsoluteLayout) attachTarget) + .getPosition(attachedComponent); + } + } + } + + private class MyDetachListener implements ComponentDetachListener { + @Override + public void componentDetachedFromContainer(ComponentDetachEvent event) { + detachCounter++; + detachedComponent = event.getDetachedComponent(); + detachedTarget = event.getContainer(); + + // Search for component in container (should NOT be found) + Iterator<Component> iter = detachedTarget.getComponentIterator(); + while (iter.hasNext()) { + if (iter.next() == detachedComponent) { + foundInContainer = true; + break; + } + } + + // Get layout specific variables + if (detachedTarget instanceof AbstractOrderedLayout) { + indexOfComponent = ((AbstractOrderedLayout) detachedTarget) + .getComponentIndex(detachedComponent); + } else if (detachedTarget instanceof GridLayout) { + componentArea = ((GridLayout) detachedTarget) + .getComponentArea(detachedComponent); + } else if (detachedTarget instanceof AbsoluteLayout) { + componentPosition = ((AbsoluteLayout) detachedTarget) + .getPosition(detachedComponent); + } + + } + } + + private void resetVariables() { + // Attach + attachCounter = 0; + attachedComponent = null; + attachTarget = null; + foundInContainer = false; + + // Detach + detachCounter = 0; + detachedComponent = null; + detachedTarget = null; + + // Common + indexOfComponent = -1; + componentArea = null; + componentPosition = null; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + olayout = new HorizontalLayout(); + olayout.addListener(new MyAttachListener()); + olayout.addListener(new MyDetachListener()); + + gridlayout = new GridLayout(); + gridlayout.addListener(new MyAttachListener()); + gridlayout.addListener(new MyDetachListener()); + + absolutelayout = new AbsoluteLayout(); + absolutelayout.addListener(new MyAttachListener()); + absolutelayout.addListener(new MyDetachListener()); + + csslayout = new CssLayout(); + csslayout.addListener(new MyAttachListener()); + csslayout.addListener(new MyDetachListener()); + } + + public void testOrderedLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + olayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(olayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The index of the component should not be -1 + assertFalse(indexOfComponent == -1); + } + + public void testOrderedLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + olayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + olayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(olayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The index of the component should be -1 + assertEquals(-1, indexOfComponent); + } + + public void testGridLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + gridlayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(gridlayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The grid area should not be null + assertNotNull(componentArea); + } + + public void testGridLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + gridlayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + gridlayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(gridlayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The grid area should be null + assertNull(componentArea); + } + + public void testAbsoluteLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + absolutelayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(absolutelayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The component position should not be null + assertNotNull(componentPosition); + } + + public void testAbsoluteLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + absolutelayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + absolutelayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(absolutelayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The component position should be null + assertNull(componentPosition); + } + + public void testCSSLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + csslayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(csslayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + } + + public void testCSSLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + csslayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + csslayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(csslayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java b/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java new file mode 100644 index 0000000000..308889fa33 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java @@ -0,0 +1,31 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.ComboBox; + +/** + * Check that the value change listener for a combo box is triggered exactly + * once when setting the value, at the correct time. + * + * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. + */ +public class TestComboBoxValueChange extends + AbstractTestFieldValueChange<Object> { + @Override + protected void setUp() throws Exception { + ComboBox combo = new ComboBox(); + combo.addItem("myvalue"); + super.setUp(combo); + } + + @Override + protected void setValue(AbstractField<Object> field) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("selected", new String[] { "myvalue" }); + ((ComboBox) field).changeVariables(field, variables); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java b/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java new file mode 100644 index 0000000000..92664917fd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java @@ -0,0 +1,40 @@ +package com.vaadin.tests.server.components; + +import junit.framework.TestCase; + +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; + +public class TestGridLayoutLastRowRemoval extends TestCase { + + public void testRemovingLastRow() { + GridLayout grid = new GridLayout(2, 1); + grid.addComponent(new Label("Col1")); + grid.addComponent(new Label("Col2")); + + try { + // Removing the last row in the grid + grid.removeRow(0); + } catch (IllegalArgumentException iae) { + // Removing the last row should not throw an + // IllegalArgumentException + fail("removeRow(0) threw an IllegalArgumentExcetion when removing the last row"); + } + + // The column amount should be preserved + assertEquals(2, grid.getColumns()); + + // There should be one row left + assertEquals(1, grid.getRows()); + + // There should be no component left in the grid layout + assertNull("A component should not be left in the layout", + grid.getComponent(0, 0)); + assertNull("A component should not be left in the layout", + grid.getComponent(1, 0)); + + // The cursor should be in the first cell + assertEquals(0, grid.getCursorX()); + assertEquals(0, grid.getCursorY()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java b/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java new file mode 100644 index 0000000000..de838e339c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java @@ -0,0 +1,126 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; + +import org.easymock.EasyMock; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.TextField; + +/** + * Check that the value change listener for a text field is triggered exactly + * once when setting the value, at the correct time. + * + * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. + */ +public class TestTextFieldValueChange extends + AbstractTestFieldValueChange<String> { + + @Override + protected void setUp() throws Exception { + super.setUp(new TextField()); + } + + /** + * Case where the text field only uses its internal buffer, no external + * property data source. + */ + public void testNoDataSource() { + getField().setPropertyDataSource(null); + + expectValueChangeFromSetValueNotCommit(); + } + + @Override + protected void setValue(AbstractField<String> field) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("text", "newValue"); + ((TextField) field).changeVariables(field, variables); + } + + /** + * Test that field propagates value change events originating from property, + * but don't fire value change events twice if value has only changed once. + * + * + * TODO make test field type agnostic (eg. combobox) + */ + public void testValueChangeEventPropagationWithReadThrough() { + ObjectProperty<String> property = new ObjectProperty<String>(""); + getField().setPropertyDataSource(property); + + // defaults, buffering off + getField().setBuffered(false); + + // Expectations and start test + getListener().valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(getListener()); + + // Add listener and set the value -> should end up in listener once + getField().addListener(getListener()); + + property.setValue("Foo"); + + // Ensure listener was called once + EasyMock.verify(getListener()); + + // get value should not fire value change again + Object value = getField().getValue(); + Assert.assertEquals("Foo", value); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + } + + /** + * Value change events from property should not propagate if read through is + * false. Execpt when the property is being set. + * + * TODO make test field type agnostic (eg. combobox) + */ + public void testValueChangePropagationWithReadThroughOff() { + final String initialValue = "initial"; + ObjectProperty<String> property = new ObjectProperty<String>( + initialValue); + + // set buffering + getField().setBuffered(true); + + // Value change should only happen once, when setting the property, + // further changes via property should not cause value change listener + // in field to be notified + getListener().valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(getListener()); + + getField().addListener(getListener()); + getField().setPropertyDataSource(property); + + // Ensure listener was called once + EasyMock.verify(getListener()); + + // modify property value, should not fire value change in field as the + // read buffering is on (read through == false) + property.setValue("Foo"); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + + // get value should not fire value change again + Object value = getField().getValue(); + + // field value should be different from the original value and current + // proeprty value + boolean isValueEqualToInitial = value.equals(initialValue); + Assert.assertTrue(isValueEqualToInitial); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestWindow.java b/server/tests/src/com/vaadin/tests/server/components/TestWindow.java new file mode 100644 index 0000000000..12d3a3c8f5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestWindow.java @@ -0,0 +1,92 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.ui.UI.LegacyWindow; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.CloseEvent; +import com.vaadin.ui.Window.CloseListener; +import com.vaadin.ui.Window.ResizeEvent; +import com.vaadin.ui.Window.ResizeListener; + +public class TestWindow extends TestCase { + + private Window window; + + @Override + protected void setUp() throws Exception { + window = new Window(); + new LegacyWindow().addWindow(window); + } + + public void testCloseListener() { + CloseListener cl = EasyMock.createMock(Window.CloseListener.class); + + // Expectations + cl.windowClose(EasyMock.isA(CloseEvent.class)); + + // Start actual test + EasyMock.replay(cl); + + // Add listener and send a close event -> should end up in listener once + window.addListener(cl); + sendClose(window); + + // Ensure listener was called once + EasyMock.verify(cl); + + // Remove the listener and send close event -> should not end up in + // listener + window.removeListener(cl); + sendClose(window); + + // Ensure listener still has been called only once + EasyMock.verify(cl); + + } + + public void testResizeListener() { + ResizeListener rl = EasyMock.createMock(Window.ResizeListener.class); + + // Expectations + rl.windowResized(EasyMock.isA(ResizeEvent.class)); + + // Start actual test + EasyMock.replay(rl); + + // Add listener and send a resize event -> should end up in listener + // once + window.addListener(rl); + sendResize(window); + + // Ensure listener was called once + EasyMock.verify(rl); + + // Remove the listener and send close event -> should not end up in + // listener + window.removeListener(rl); + sendResize(window); + + // Ensure listener still has been called only once + EasyMock.verify(rl); + + } + + private void sendResize(Window window2) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("height", 1234); + window.changeVariables(window, variables); + + } + + private static void sendClose(Window window) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("close", true); + window.changeVariables(window, variables); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java b/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java new file mode 100644 index 0000000000..5db0df4280 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import com.vaadin.navigator.Navigator.ClassBasedViewProvider; +import com.vaadin.navigator.View; +import com.vaadin.ui.Label; + +public class ClassBasedViewProviderTest extends TestCase { + + public static class TestView extends Label implements View { + public String parameters = null; + + @Override + public void navigateTo(String parameters) { + this.parameters = parameters; + } + + } + + public static class TestView2 extends TestView { + + } + + public void testCreateProviderWithNullName() throws Exception { + try { + new ClassBasedViewProvider(null, TestView.class); + fail("Should not be able to create view provider with null name"); + } catch (IllegalArgumentException e) { + } + } + + public void testCreateProviderWithEmptyStringName() throws Exception { + new ClassBasedViewProvider("", TestView.class); + } + + public void testCreateProviderNullViewClass() throws Exception { + try { + new ClassBasedViewProvider("test", null); + fail("Should not be able to create view provider with null view class"); + } catch (IllegalArgumentException e) { + } + } + + public void testViewNameGetter() throws Exception { + ClassBasedViewProvider provider1 = new ClassBasedViewProvider("", + TestView.class); + assertEquals("View name should be empty", "", provider1.getViewName()); + + ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("View name does not match", "test", + provider2.getViewName()); + } + + public void testViewClassGetter() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("Incorrect view class returned by getter", TestView.class, + provider.getViewClass()); + } + + public void testGetViewNameForNullString() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertNull("Received view name for null view string", + provider.getViewName((String) null)); + } + + public void testGetViewNameForEmptyString() throws Exception { + ClassBasedViewProvider provider1 = new ClassBasedViewProvider("", + TestView.class); + assertEquals( + "Did not find view name for empty view string in a provider with empty string registered", + "", provider1.getViewName("")); + + ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test", + TestView.class); + assertNull( + "Found view name for empty view string when none registered", + provider2.getViewName("")); + } + + public void testGetViewNameWithParameters() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("Incorrect view name found for view string", "test", + provider.getViewName("test")); + assertEquals( + "Incorrect view name found for view string ending with slash", + "test", provider.getViewName("test/")); + assertEquals( + "Incorrect view name found for view string with parameters", + "test", provider.getViewName("test/params/are/here")); + } + + public void testGetView() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + + View view = provider.getView("test"); + assertNotNull("Did not get view from a provider", view); + assertEquals("Incorrect view type", TestView.class, view.getClass()); + } + + public void testGetViewIncorrectViewName() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + + View view = provider.getView("test2"); + assertNull("Got view from a provider for incorrect view name", view); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java new file mode 100644 index 0000000000..595ddb95db --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java @@ -0,0 +1,575 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.server.navigator; + +import java.util.LinkedList; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.FragmentManager; +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.navigator.ViewProvider; +import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView; +import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView2; + +public class NavigatorTest extends TestCase { + + // TODO test internal parameters (and absence of them) + // TODO test listeners blocking navigation, multiple listeners + + public static class NullDisplay implements ViewDisplay { + @Override + public void showView(View view) { + // do nothing + } + } + + public static class NullFragmentManager implements FragmentManager { + @Override + public String getFragment() { + return null; + } + + @Override + public void setFragment(String fragment) { + // do nothing + } + } + + public static class TestDisplay implements ViewDisplay { + private View currentView; + + @Override + public void showView(View view) { + currentView = view; + } + + public View getCurrentView() { + return currentView; + } + } + + public static class TestNavigator extends Navigator { + public TestNavigator() { + super(new NullFragmentManager(), new TestDisplay()); + } + + public View getView(String viewAndParameters) { + navigateTo(viewAndParameters); + return ((TestDisplay) getDisplay()).getCurrentView(); + } + } + + public static class ViewChangeTestListener implements ViewChangeListener { + private final LinkedList<ViewChangeEvent> referenceEvents = new LinkedList<ViewChangeListener.ViewChangeEvent>(); + private final LinkedList<Boolean> referenceIsCheck = new LinkedList<Boolean>(); + private final LinkedList<Boolean> checkReturnValues = new LinkedList<Boolean>(); + + public void addExpectedIsViewChangeAllowed(ViewChangeEvent event, + boolean returnValue) { + referenceIsCheck.add(true); + referenceEvents.add(event); + checkReturnValues.add(returnValue); + } + + public void addExpectedNavigatorViewChange(ViewChangeEvent event) { + referenceIsCheck.add(false); + referenceEvents.add(event); + } + + public boolean isReady() { + return referenceEvents.isEmpty(); + } + + public boolean equalsReferenceEvent(ViewChangeEvent event, + ViewChangeEvent reference) { + if (event == null) { + return false; + } + if (reference.getNavigator() != event.getNavigator()) { + return false; + } + if (reference.getOldView() != event.getOldView()) { + return false; + } + if (reference.getNewView() != event.getNewView()) { + return false; + } + if (!stringEquals(reference.getViewName(), event.getViewName())) { + return false; + } + if (!stringEquals(reference.getFragmentParameters(), + event.getFragmentParameters())) { + return false; + } + return true; + } + + private static boolean stringEquals(String string1, String string2) { + if (string1 == null) { + return string2 == null; + } else { + return string1.equals(string2); + } + } + + @Override + public boolean isViewChangeAllowed(ViewChangeEvent event) { + if (referenceEvents.isEmpty()) { + fail("Unexpected call to isViewChangeAllowed()"); + } + ViewChangeEvent reference = referenceEvents.remove(); + Boolean isCheck = referenceIsCheck.remove(); + if (!isCheck) { + fail("Expected navigatorViewChanged(), received isViewChangeAllowed()"); + } + // here to make sure exactly the correct values are removed from + // each queue + Boolean returnValue = checkReturnValues.remove(); + if (!equalsReferenceEvent(event, reference)) { + fail("View change event does not match reference event"); + } + return returnValue; + } + + @Override + public void navigatorViewChanged(ViewChangeEvent event) { + if (referenceEvents.isEmpty()) { + fail("Unexpected call to navigatorViewChanged()"); + } + ViewChangeEvent reference = referenceEvents.remove(); + Boolean isCheck = referenceIsCheck.remove(); + if (isCheck) { + fail("Expected isViewChangeAllowed(), received navigatorViewChanged()"); + } + if (!equalsReferenceEvent(event, reference)) { + fail("View change event does not match reference event"); + } + } + } + + public void testBasicNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test2/")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.addProvider(provider); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2/"); + navigator.navigateTo("test1/params"); + } + + public void testMainView() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.addProvider(provider); + + navigator.navigateTo("test2"); + navigator.navigateTo(""); + navigator.navigateTo("test1/params"); + } + + public void testListeners() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeTestListener listener = new ViewChangeTestListener(); + + // create navigator to test + Navigator navigator = new Navigator(manager, display); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1, + "test1", ""); + listener.addExpectedIsViewChangeAllowed(event1, true); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + listener.addExpectedNavigatorViewChange(event1); + + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + ViewChangeEvent event2 = new ViewChangeEvent(navigator, view1, view2, + "test2", ""); + listener.addExpectedIsViewChangeAllowed(event2, true); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + listener.addExpectedNavigatorViewChange(event2); + + control.replay(); + + // test navigator + navigator.addProvider(provider); + navigator.addListener(listener); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2"); + + if (!listener.isReady()) { + fail("Missing listener calls"); + } + } + + public void testBlockNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeTestListener listener1 = new ViewChangeTestListener(); + ViewChangeTestListener listener2 = new ViewChangeTestListener(); + + Navigator navigator = new Navigator(manager, display); + + // prepare mocks: what to expect + // first listener blocks first view change + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1, + "test1", ""); + listener1.addExpectedIsViewChangeAllowed(event1, false); + + // second listener blocks second view change + EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event2 = new ViewChangeEvent(navigator, null, view1, + "test1", "test"); + listener1.addExpectedIsViewChangeAllowed(event2, true); + listener2.addExpectedIsViewChangeAllowed(event2, false); + + // both listeners allow view change + EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event3 = new ViewChangeEvent(navigator, null, view1, + "test1", "bar"); + listener1.addExpectedIsViewChangeAllowed(event3, true); + listener2.addExpectedIsViewChangeAllowed(event3, true); + view1.navigateTo("bar"); + display.showView(view1); + manager.setFragment("test1/bar"); + listener1.addExpectedNavigatorViewChange(event3); + listener2.addExpectedNavigatorViewChange(event3); + + // both listeners allow view change from non-null view + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + ViewChangeEvent event4 = new ViewChangeEvent(navigator, view1, view2, + "test2", ""); + listener1.addExpectedIsViewChangeAllowed(event4, true); + listener2.addExpectedIsViewChangeAllowed(event4, true); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + listener1.addExpectedNavigatorViewChange(event4); + listener2.addExpectedNavigatorViewChange(event4); + + control.replay(); + + // test navigator + navigator.addProvider(provider); + navigator.addListener(listener1); + navigator.addListener(listener2); + + navigator.navigateTo("test1"); + navigator.navigateTo("test1/test"); + navigator.navigateTo("test1/bar"); + navigator.navigateTo("test2"); + + if (!listener1.isReady()) { + fail("Missing listener calls for listener1"); + } + if (!listener2.isReady()) { + fail("Missing listener calls for listener2"); + } + } + + public void testAddViewInstance() throws Exception { + View view = new TestView(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + + assertEquals("Registered view instance not returned by navigator", + view, navigator.getView("test")); + } + + public void testAddViewInstanceSameName() throws Exception { + View view1 = new TestView(); + View view2 = new TestView2(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view1); + navigator.addView("test", view2); + + assertEquals( + "Adding second view with same name should override previous view", + view2, navigator.getView("test")); + } + + public void testAddViewClass() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + + View view = navigator.getView("test"); + assertNotNull("Received null view", view); + assertEquals("Received incorrect type of view", TestView.class, + view.getClass()); + } + + public void testAddViewClassSameName() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.addView("test", TestView2.class); + + assertEquals( + "Adding second view class with same name should override previous view", + TestView2.class, navigator.getView("test").getClass()); + } + + public void testAddViewInstanceAndClassSameName() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + TestView2 view2 = new TestView2(); + navigator.addView("test", view2); + + assertEquals( + "Adding second view class with same name should override previous view", + view2, navigator.getView("test")); + + navigator.addView("test", TestView.class); + + assertEquals( + "Adding second view class with same name should override previous view", + TestView.class, navigator.getView("test").getClass()); + } + + public void testAddViewWithNullName() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView(null, new TestView()); + fail("addView() accepted null view name"); + } catch (IllegalArgumentException e) { + } + try { + navigator.addView(null, TestView.class); + fail("addView() accepted null view name"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewWithNullInstance() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView("test", (View) null); + fail("addView() accepted null view instance"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewWithNullClass() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView("test", (Class<View>) null); + fail("addView() accepted null view class"); + } catch (IllegalArgumentException e) { + } + } + + public void testRemoveViewInstance() throws Exception { + View view = new TestView(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + navigator.removeView("test"); + + assertNull("View not removed", navigator.getView("test")); + } + + public void testRemoveViewInstanceNothingElse() throws Exception { + View view = new TestView(); + View view2 = new TestView2(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + navigator.addView("test2", view2); + navigator.removeView("test"); + + assertEquals("Removed extra views", view2, navigator.getView("test2")); + } + + public void testRemoveViewClass() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.removeView("test"); + + assertNull("View not removed", navigator.getView("test")); + } + + public void testRemoveViewClassNothingElse() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.addView("test2", TestView2.class); + navigator.removeView("test"); + + assertEquals("Removed extra views", TestView2.class, + navigator.getView("test2").getClass()); + } + + public void testGetViewNestedNames() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test/subview", TestView2.class); + navigator.addView("test", TestView.class); + + assertEquals("Incorrect view name found for subview string", + TestView2.class, navigator.getView("test/subview").getClass()); + assertEquals( + "Incorrect view name found for subview string with empty parameters", + TestView2.class, navigator.getView("test/subview/").getClass()); + assertEquals( + "Incorrect view name found for subview string with parameters", + TestView2.class, navigator.getView("test/subview/parameters") + .getClass()); + assertEquals("Incorrect view name found for top level view string", + TestView.class, navigator.getView("test").getClass()); + assertEquals( + "Incorrect view name found for top level view string with empty parameters", + TestView.class, navigator.getView("test/").getClass()); + assertEquals( + "Incorrect view name found for top level view string with parameters starting like subview name", + TestView.class, navigator.getView("test/subviewnothere") + .getClass()); + } + + public void testGetViewLongestPrefixOrder() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test/subview", TestView2.class); + navigator.addView("test", TestView.class); + + assertEquals("Incorrect view name found", TestView.class, navigator + .getView("test").getClass()); + + // other order + + TestNavigator navigator2 = new TestNavigator(); + + navigator2.addView("test", TestView.class); + navigator2.addView("test/subview", TestView2.class); + + assertEquals("Incorrect view name found", TestView.class, navigator2 + .getView("test").getClass()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java new file mode 100644 index 0000000000..18ed52cc2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.Navigator.UriFragmentManager; +import com.vaadin.server.Page; +import com.vaadin.server.Page.FragmentChangedEvent; + +public class UriFragmentManagerTest extends TestCase { + + public void testGetSetFragment() { + Page page = EasyMock.createMock(Page.class); + UriFragmentManager manager = new UriFragmentManager(page, null); + + // prepare mock + EasyMock.expect(page.getFragment()).andReturn(""); + page.setFragment("test", false); + EasyMock.expect(page.getFragment()).andReturn("test"); + EasyMock.replay(page); + + // test manager using the mock + assertEquals("Incorrect fragment value", "", manager.getFragment()); + manager.setFragment("test"); + assertEquals("Incorrect fragment value", "test", manager.getFragment()); + } + + public void testListener() { + // create mocks + IMocksControl control = EasyMock.createControl(); + Navigator navigator = control.createMock(Navigator.class); + Page page = control.createMock(Page.class); + + UriFragmentManager manager = new UriFragmentManager(page, navigator); + + EasyMock.expect(page.getFragment()).andReturn("test"); + navigator.navigateTo("test"); + control.replay(); + + FragmentChangedEvent event = page.new FragmentChangedEvent(page, + "oldtest"); + manager.fragmentChanged(event); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java b/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java new file mode 100644 index 0000000000..e3320b8699 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java @@ -0,0 +1,52 @@ +package com.vaadin.tests.server.validation; + +import junit.framework.TestCase; + +import com.vaadin.data.validator.IntegerRangeValidator; + +public class RangeValidatorTest extends TestCase { + + // This test uses IntegerRangeValidator for simplicity. + // IntegerRangeValidator contains no code so we really are testing + // RangeValidator + public void testMinValueNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMinValueIncluded(false); + assertFalse(iv.isValid(0)); + assertTrue(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMinMaxValuesInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + assertTrue(iv.isValid(0)); + assertTrue(iv.isValid(1)); + assertTrue(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMaxValueNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMaxValueIncluded(false); + assertTrue(iv.isValid(0)); + assertTrue(iv.isValid(9)); + assertFalse(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMinMaxValuesNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMinValueIncluded(false); + iv.setMaxValueIncluded(false); + + assertFalse(iv.isValid(0)); + assertTrue(iv.isValid(1)); + assertTrue(iv.isValid(9)); + assertFalse(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java b/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java new file mode 100644 index 0000000000..8f6928fc35 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java @@ -0,0 +1,57 @@ +package com.vaadin.tests.server.validation; + +import org.junit.Test; + +import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.data.validator.BeanValidator; +import com.vaadin.tests.data.bean.BeanToValidate; + +public class TestBeanValidation { + @Test(expected = InvalidValueException.class) + public void testBeanValidationNull() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate(null); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationStringTooShort() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate("aa"); + } + + @Test + public void testBeanValidationStringOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate("aaa"); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationIntegerTooSmall() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, "age"); + validator.validate(17); + } + + @Test + public void testBeanValidationIntegerOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, "age"); + validator.validate(18); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationTooManyDigits() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "decimals"); + validator.validate("1234.567"); + } + + @Test + public void testBeanValidationDigitsOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "decimals"); + validator.validate("123.45"); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java b/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java new file mode 100644 index 0000000000..e37b97e02c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java @@ -0,0 +1,17 @@ +package com.vaadin.tests.server.validation; + +import org.junit.Test; + +import com.vaadin.data.validator.IntegerValidator; +import com.vaadin.ui.TextField; + +public class TestReadOnlyValidation { + + @Test + public void testIntegerValidation() { + TextField field = new TextField(); + field.addValidator(new IntegerValidator("Enter a Valid Number")); + field.setValue(String.valueOf(10)); + field.validate(); + } +} diff --git a/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java b/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java new file mode 100644 index 0000000000..9e791500b0 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java @@ -0,0 +1,149 @@ +package com.vaadin.tests.util; + +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.vaadin.tests.VaadinClasses; + +public class GraphVizClassHierarchyCreator { + + public static void main(String[] args) { + String gv = getGraphVizHierarchy((List) VaadinClasses.getComponents(), + "com.vaadin"); + System.out.println(gv); + } + + private static String getGraphVizHierarchy(List<Class> classes, + String packageToInclude) { + boolean includeInterfaces = false; + + StringBuilder header = new StringBuilder(); + header.append("digraph finite_state_machine {\n" + + " rankdir=BT;\n" + " dpi=\"150\";\n" + + " ratio=\"0.25\";\n"); + + StringBuilder sb = new StringBuilder(); + + Set<Class> classesAndParents = new HashSet<Class>(); + for (Class<?> cls : classes) { + addClassAndParents(classesAndParents, cls, packageToInclude); + } + + Set<Class> interfaces = new HashSet<Class>(); + for (Object cls : classesAndParents.toArray()) { + for (Class<?> c : ((Class) cls).getInterfaces()) { + addClassAndParentInterfaces(classesAndParents, c, + packageToInclude); + } + } + + for (Class<?> c : classesAndParents) { + appendClass(sb, c, c.getSuperclass(), packageToInclude, + includeInterfaces); + for (Class ci : c.getInterfaces()) { + appendClass(sb, c, ci, packageToInclude, includeInterfaces); + } + } + + header.append(" node [shape = ellipse, style=\"dotted\"] "); + for (Class c : classesAndParents) { + if (!c.isInterface() && Modifier.isAbstract(c.getModifiers())) { + header.append(c.getSimpleName() + " "); + } + } + if (includeInterfaces) { + System.out.print(" node [shape = ellipse, style=\"solid\"] "); + for (Class c : classesAndParents) { + if (c.isInterface()) { + header.append(c.getSimpleName() + " "); + } + } + header.append(";\n"); + } + header.append(";\n"); + header.append(" node [shape = rectangle, style=\"solid\"];\n"); + return header.toString() + sb.toString() + "}"; + } + + private static void addClassAndParents(Set<Class> classesAndParents, + Class<?> cls, String packageToInclude) { + + if (cls == null) { + return; + } + + if (classesAndParents.contains(cls)) { + return; + } + + if (!cls.getPackage().getName().startsWith(packageToInclude)) { + return; + } + + classesAndParents.add(cls); + addClassAndParents(classesAndParents, cls.getSuperclass(), + packageToInclude); + + } + + private static void addClassAndParentInterfaces( + Set<Class> classesAndParents, Class<?> cls, String packageToInclude) { + + if (cls == null) { + return; + } + + if (classesAndParents.contains(cls)) { + return; + } + + if (!cls.getPackage().getName().startsWith(packageToInclude)) { + return; + } + + classesAndParents.add(cls); + for (Class iClass : cls.getInterfaces()) { + addClassAndParentInterfaces(classesAndParents, iClass, + packageToInclude); + } + + } + + private static void appendClass(StringBuilder sb, Class<?> c, + Class<?> superClass, String packageToInclude, + boolean includeInterfaces) { + if (superClass == null) { + return; + } + if (!c.getPackage().getName().startsWith(packageToInclude)) { + return; + } + if (!superClass.getPackage().getName().startsWith(packageToInclude)) { + return; + } + if (!includeInterfaces && (c.isInterface() || superClass.isInterface())) { + return; + } + + sb.append(c.getSimpleName()).append(" -> ") + .append(superClass.getSimpleName()).append("\n"); + + } + + private static void addInterfaces(Set<Class> interfaces, Class<?> cls) { + if (interfaces.contains(cls)) { + return; + } + + if (cls.isInterface()) { + interfaces.add(cls); + } + + for (Class c : cls.getInterfaces()) { + addInterfaces(interfaces, c); + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/util/TestUtil.java b/server/tests/src/com/vaadin/tests/util/TestUtil.java new file mode 100644 index 0000000000..e84f9dd8b9 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/TestUtil.java @@ -0,0 +1,43 @@ +package com.vaadin.tests.util; + +import java.util.Iterator; + +import junit.framework.Assert; + +public class TestUtil { + public static void assertArrays(Object[] actualObjects, + Object[] expectedObjects) { + Assert.assertEquals( + "Actual contains a different number of values than was expected", + expectedObjects.length, actualObjects.length); + + for (int i = 0; i < actualObjects.length; i++) { + Object actual = actualObjects[i]; + Object expected = expectedObjects[i]; + + Assert.assertEquals("Item[" + i + "] does not match", expected, + actual); + } + + } + + public static void assertIterableEquals(Iterable<?> iterable1, + Iterable<?> iterable2) { + Iterator<?> i1 = iterable1.iterator(); + Iterator<?> i2 = iterable2.iterator(); + + while (i1.hasNext()) { + Object o1 = i1.next(); + if (!i2.hasNext()) { + Assert.fail("The second iterable contains fewer items than the first. The object " + + o1 + " has no match in the second iterable."); + } + Object o2 = i2.next(); + Assert.assertEquals(o1, o2); + } + if (i2.hasNext()) { + Assert.fail("The second iterable contains more items than the first. The object " + + i2.next() + " has no match in the first iterable."); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java b/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java new file mode 100644 index 0000000000..d62f0df332 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.util; + +import java.io.Serializable; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.UniqueSerializable; + +public class UniqueSerializableTest extends TestCase implements Serializable { + + public void testUniqueness() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable o2 = new UniqueSerializable() { + }; + assertFalse(o1 == o2); + assertFalse(o1.equals(o2)); + } + + public void testSerialization() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable d1 = (UniqueSerializable) SerializationUtils + .deserialize(SerializationUtils.serialize(o1)); + assertTrue(d1.equals(o1)); + } + +} |