summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2015-06-01 09:32:37 +0300
committerTeemu Suo-Anttila <teemusa@vaadin.com>2015-06-01 09:34:46 +0300
commit6677046e5e23667403b8fb0499a618495796e1c8 (patch)
tree0d4bb0bf40b16be2c9e7e6158729f5bd3ff54d22 /server
parentcf563c053fdf0d6b2991eba98e1cc118a8e74e54 (diff)
parent5b92ec790e3d3949992275d54ee8ac61ad94c157 (diff)
downloadvaadin-framework-6677046e5e23667403b8fb0499a618495796e1c8.tar.gz
vaadin-framework-6677046e5e23667403b8fb0499a618495796e1c8.zip
Merge remote-tracking branch 'origin/master' into grid-unbuffered-editor
This also refactors some event handling logic. Change-Id: I9cf96381650076da01686c5d964eb3e7e92c24c0
Diffstat (limited to 'server')
-rw-r--r--server/build.xml2
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java26
-rw-r--r--server/src/com/vaadin/data/util/MethodProperty.java11
-rw-r--r--server/src/com/vaadin/data/util/NestedMethodProperty.java8
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java2
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java10
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java8
-rw-r--r--server/src/com/vaadin/event/ShortcutAction.java38
-rw-r--r--server/src/com/vaadin/server/AbstractClientConnector.java40
-rw-r--r--server/src/com/vaadin/server/SystemMessages.java29
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java3
-rw-r--r--server/src/com/vaadin/server/communication/PushRequestHandler.java2
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java24
-rw-r--r--server/src/com/vaadin/server/communication/UidlRequestHandler.java4
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java20
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java18
-rw-r--r--server/src/com/vaadin/ui/AbstractSingleComponentContainer.java4
-rw-r--r--server/src/com/vaadin/ui/CustomLayout.java2
-rw-r--r--server/src/com/vaadin/ui/DragAndDropWrapper.java2
-rw-r--r--server/src/com/vaadin/ui/Flash.java9
-rw-r--r--server/src/com/vaadin/ui/Grid.java83
-rw-r--r--server/src/com/vaadin/ui/PasswordField.java6
-rw-r--r--server/src/com/vaadin/ui/PopupView.java4
-rw-r--r--server/src/com/vaadin/ui/ProgressBar.java15
-rw-r--r--server/src/com/vaadin/ui/RichTextArea.java5
-rw-r--r--server/src/com/vaadin/ui/Slider.java58
-rw-r--r--server/src/com/vaadin/ui/TextArea.java6
-rw-r--r--server/src/com/vaadin/ui/Tree.java2
-rw-r--r--server/src/com/vaadin/ui/UI.java29
-rw-r--r--server/src/com/vaadin/ui/Window.java102
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java6
-rw-r--r--server/src/com/vaadin/ui/declarative/FieldBinder.java9
-rw-r--r--server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java13
-rw-r--r--server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java6
-rw-r--r--server/src/com/vaadin/ui/renderers/ButtonRenderer.java38
-rw-r--r--server/src/com/vaadin/ui/renderers/ClickableRenderer.java6
-rw-r--r--server/src/com/vaadin/ui/renderers/DateRenderer.java91
-rw-r--r--server/src/com/vaadin/ui/renderers/HtmlRenderer.java21
-rw-r--r--server/src/com/vaadin/ui/renderers/ImageRenderer.java4
-rw-r--r--server/src/com/vaadin/ui/renderers/NumberRenderer.java77
-rw-r--r--server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java8
-rw-r--r--server/src/com/vaadin/ui/renderers/TextRenderer.java17
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java6
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java4
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java7
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java18
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java4
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java81
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java36
-rw-r--r--server/tests/src/com/vaadin/data/util/sqlcontainer/query/ValidatingSimpleJDBCConnectionPool.java89
-rw-r--r--server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java112
-rw-r--r--server/tests/src/com/vaadin/tests/design/DesignFormatterTest.java8
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/FieldDefaultValues.java11
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidatorsTest.java61
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java4
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridChildren.java59
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridExtensionTest.java41
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java56
-rw-r--r--server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java161
59 files changed, 1203 insertions, 423 deletions
diff --git a/server/build.xml b/server/build.xml
index 79bc6debe2..e88b53d937 100644
--- a/server/build.xml
+++ b/server/build.xml
@@ -26,7 +26,7 @@
<target name="jar">
<property name="server.osgi.import"
- value="javax.servlet;version=&quot;2.4.0&quot;,javax.servlet.http;version=&quot;2.4.0&quot;,javax.validation;version=&quot;1.0.0.GA&quot;;resolution:=optional,org.jsoup;version=&quot;1.6.3&quot;,org.jsoup.parser;version=&quot;1.6.3&quot;,org.jsoup.nodes;version=&quot;1.6.3&quot;,org.jsoup.helper;version=&quot;1.6.3&quot;,org.jsoup.safety;version=&quot;1.6.3&quot;" />
+ value="javax.servlet;version=&quot;2.4.0&quot;,javax.servlet.http;version=&quot;2.4.0&quot;,javax.validation;version=&quot;1.0.0.GA&quot;;resolution:=optional,org.jsoup;version=&quot;1.6.3&quot;,org.jsoup.parser;version=&quot;1.6.3&quot;,org.jsoup.nodes;version=&quot;1.6.3&quot;,org.jsoup.helper;version=&quot;1.6.3&quot;,org.jsoup.safety;version=&quot;1.6.3&quot;,org.jsoup.select;version=&quot;1.6.3&quot;" />
<property name="server.osgi.require"
value="com.google.gwt.thirdparty.guava;bundle-version=&quot;16.0.1.vaadin1&quot;,com.vaadin.shared;bundle-version=&quot;${vaadin.version}&quot;,com.vaadin.push;bundle-version=&quot;${vaadin.version}&quot;;resolution:=optional,com.vaadin.sass-compiler;bundle-version=&quot;${vaadin.sass.version}&quot;;resolution:=optional" />
<antcall target="common.jar">
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index e645ec60f7..9d18736ba8 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -50,6 +50,7 @@ import com.vaadin.server.KeyMapper;
import com.vaadin.shared.data.DataProviderRpc;
import com.vaadin.shared.data.DataRequestRpc;
import com.vaadin.shared.ui.grid.DetailsConnectorChange;
+import com.vaadin.shared.ui.grid.GridClientRpc;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.util.SharedUtil;
@@ -135,6 +136,15 @@ public class RpcDataProviderExtension extends AbstractExtension {
return String.valueOf(rollingIndex++);
}
+ /**
+ * Gets the key for a given item id. Creates a new key mapping if no
+ * existing mapping was found for the given item id.
+ *
+ * @since 7.5.0
+ * @param itemId
+ * the item id to get the key for
+ * @return the key for the given item id
+ */
public String getKey(Object itemId) {
String key = itemIdToKey.get(itemId);
if (key == null) {
@@ -1124,7 +1134,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
Object propertyId = column.getPropertyId();
cellReference.set(propertyId);
String style = generator.getStyle(cellReference);
- if (style != null) {
+ if (style != null && !style.isEmpty()) {
if (cellStyles == null) {
cellStyles = Json.createObject();
}
@@ -1142,7 +1152,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
private void setGeneratedRowStyles(RowStyleGenerator generator,
JsonObject rowObject) {
String rowStyle = generator.getStyle(rowReference);
- if (rowStyle != null) {
+ if (rowStyle != null && !rowStyle.isEmpty()) {
rowObject.put(GridState.JSONKEY_ROWSTYLE, rowStyle);
}
}
@@ -1428,6 +1438,11 @@ public class RpcDataProviderExtension extends AbstractExtension {
return visibleDetails.contains(itemId);
}
+ /**
+ * Refreshes all visible detail sections.
+ *
+ * @since 7.5.0
+ */
public void refreshDetails() {
for (Object itemId : ImmutableSet.copyOf(visibleDetails)) {
detailComponentManager.refresh(itemId);
@@ -1443,7 +1458,12 @@ public class RpcDataProviderExtension extends AbstractExtension {
return container.indexOfId(itemId);
}
- /** Gets the detail component manager for this data provider */
+ /**
+ * Gets the detail component manager for this data provider
+ *
+ * @since 7.5.0
+ * @return the detail component manager
+ * */
public DetailComponentManager getDetailComponentManager() {
return detailComponentManager;
}
diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java
index 853f68b711..83279afa53 100644
--- a/server/src/com/vaadin/data/util/MethodProperty.java
+++ b/server/src/com/vaadin/data/util/MethodProperty.java
@@ -26,6 +26,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.vaadin.data.Property;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.util.SerializerHelper;
/**
@@ -189,11 +190,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
// Assure that the first letter is upper cased (it is a common
// mistake to write firstName, not FirstName).
- if (Character.isLowerCase(beanPropertyName.charAt(0))) {
- final char[] buf = beanPropertyName.toCharArray();
- buf[0] = Character.toUpperCase(buf[0]);
- beanPropertyName = new String(buf);
- }
+ beanPropertyName = SharedUtil.capitalize(beanPropertyName);
// Find the get method
getMethod = null;
@@ -534,8 +531,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
*/
static Method initGetterMethod(String propertyName, final Class<?> beanClass)
throws NoSuchMethodException {
- propertyName = propertyName.substring(0, 1).toUpperCase()
- + propertyName.substring(1);
+ propertyName = SharedUtil.capitalize(propertyName);
Method getMethod = null;
try {
@@ -772,4 +768,5 @@ public class MethodProperty<T> extends AbstractProperty<T> {
private static final Logger getLogger() {
return Logger.getLogger(MethodProperty.class.getName());
}
+
}
diff --git a/server/src/com/vaadin/data/util/NestedMethodProperty.java b/server/src/com/vaadin/data/util/NestedMethodProperty.java
index 0493812861..29fe62f845 100644
--- a/server/src/com/vaadin/data/util/NestedMethodProperty.java
+++ b/server/src/com/vaadin/data/util/NestedMethodProperty.java
@@ -26,6 +26,7 @@ import java.util.List;
import com.vaadin.data.Property;
import com.vaadin.data.util.MethodProperty.MethodException;
+import com.vaadin.shared.util.SharedUtil;
/**
* Nested accessor based property for a bean.
@@ -164,11 +165,8 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
try {
// Assure that the first letter is upper cased (it is a common
// mistake to write firstName, not FirstName).
- if (Character.isLowerCase(lastSimplePropertyName.charAt(0))) {
- final char[] buf = lastSimplePropertyName.toCharArray();
- buf[0] = Character.toUpperCase(buf[0]);
- lastSimplePropertyName = new String(buf);
- }
+ lastSimplePropertyName = SharedUtil
+ .capitalize(lastSimplePropertyName);
setMethod = lastClass.getMethod("set" + lastSimplePropertyName,
new Class[] { type });
diff --git a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
index a84a3575f7..495bed74f8 100644
--- a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
@@ -34,6 +34,8 @@ import java.util.Locale;
* {@link String} for token types. Other constructors allow to configure
* delimiter and token types.
*
+ * @since 7.5.0
+ *
* @author Vaadin Ltd
*/
public class StringToCollectionConverter implements
diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
index c0c660c084..f07b7ecc58 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
@@ -1012,9 +1012,15 @@ public class SQLContainer implements Container, Container.Filterable,
queryDelegate.beginTransaction();
/* Perform buffered deletions */
for (RowItem item : removedItems.values()) {
- if (!queryDelegate.removeRow(item)) {
+ try {
+ if (!queryDelegate.removeRow(item)) {
+ throw new SQLException(
+ "Removal failed for row with ID: "
+ + item.getId());
+ }
+ } catch (IllegalArgumentException e) {
throw new SQLException("Removal failed for row with ID: "
- + item.getId());
+ + item.getId(), e);
}
}
/* Perform buffered modifications */
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 bb000bd8f5..9a41766a31 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
@@ -213,8 +213,8 @@ public class TableQuery extends AbstractTransactionalQuery implements
} finally {
try {
if (r != null) {
- releaseConnection(r.getStatement().getConnection(),
- r.getStatement(), r);
+ // Do not release connection, it is done in commit()
+ releaseConnection(null, r.getStatement(), r);
}
} finally {
if (shouldCloseTransaction) {
@@ -774,8 +774,8 @@ public class TableQuery extends AbstractTransactionalQuery implements
} finally {
try {
if (rs != null) {
- releaseConnection(rs.getStatement().getConnection(),
- rs.getStatement(), rs);
+ // Do not release connection, it is done in commit()
+ releaseConnection(null, rs.getStatement(), rs);
}
} finally {
if (shouldCloseTransaction) {
diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java
index 32b909e9f2..09accae1c7 100644
--- a/server/src/com/vaadin/event/ShortcutAction.java
+++ b/server/src/com/vaadin/event/ShortcutAction.java
@@ -17,8 +17,6 @@
package com.vaadin.event;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -239,42 +237,6 @@ public class ShortcutAction extends Action {
}
/**
- * Checks whether the shortcut can be triggered with the given combination
- * of keys.
- *
- * @param keyCode
- * potential match for the {@link KeyCode} that this shortcut
- * reacts to
- * @param modifierKeys
- * (optional) potential matches for the {@link ModifierKey}s
- * required for this shortcut to react
- * @return <code>true</code> if keyCode and modifierKeys are a match,
- * <code>false</code> otherwise
- */
- public boolean isTriggeredBy(int keyCode, int... modifierKeys) {
- boolean result = false;
- if (keyCode == this.keyCode) {
- if (modifierKeys == null) {
- result = (modifiers == null);
- } else if (modifiers != null) {
- List<Integer> modifierList = new ArrayList<Integer>();
- for (int modifier : modifiers) {
- modifierList.add(modifier);
- }
- for (int modifierKey : modifierKeys) {
- if (modifierList.contains(modifierKey)) {
- modifierList.remove(modifierKey);
- } else {
- return false;
- }
- }
- result = modifierList.isEmpty();
- }
- }
- return result;
- }
-
- /**
* Key codes that can be used for shortcuts
*
*/
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 87b61c9623..0655b482ed 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -180,22 +180,40 @@ public abstract class AbstractClientConnector implements ClientConnector,
* RPC interface implementation. Also used to deduce the type.
*/
protected <T extends ServerRpc> void registerRpc(T implementation) {
+ // Search upwards until an interface is found. It must be found as T
+ // extends ServerRpc
Class<?> cls = implementation.getClass();
- Class<?>[] interfaces = cls.getInterfaces();
- while (interfaces.length == 0) {
- // Search upwards until an interface is found. It must be found as T
- // extends ServerRpc
+ Class<ServerRpc> serverRpcClass = getServerRpcInterface(cls);
+
+ while (cls != null && serverRpcClass == null) {
cls = cls.getSuperclass();
- interfaces = cls.getInterfaces();
+ serverRpcClass = getServerRpcInterface(cls);
}
- if (interfaces.length != 1
- || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) {
+
+ if (serverRpcClass == null) {
throw new RuntimeException(
- "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ "No interface T extends ServerRpc found in the class hierarchy.");
+ }
+
+ registerRpc(implementation, serverRpcClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<ServerRpc> getServerRpcInterface(Class<?> implementationClass) {
+ Class<ServerRpc> serverRpcClass = null;
+ if (implementationClass != null) {
+ for (Class<?> candidateInterface : implementationClass
+ .getInterfaces()) {
+ if (ServerRpc.class.isAssignableFrom(candidateInterface)) {
+ if (serverRpcClass != null) {
+ throw new RuntimeException(
+ "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ }
+ serverRpcClass = (Class<ServerRpc>) candidateInterface;
+ }
+ }
}
- @SuppressWarnings("unchecked")
- Class<T> type = (Class<T>) interfaces[0];
- registerRpc(implementation, type);
+ return serverRpcClass;
}
/**
diff --git a/server/src/com/vaadin/server/SystemMessages.java b/server/src/com/vaadin/server/SystemMessages.java
index 51e9da5800..51cc7d497d 100644
--- a/server/src/com/vaadin/server/SystemMessages.java
+++ b/server/src/com/vaadin/server/SystemMessages.java
@@ -224,35 +224,6 @@ public class SystemMessages implements Serializable {
}
/**
- * @return null to reload the application after out of sync message.
- */
- public String getOutOfSyncURL() {
- return outOfSyncURL;
- }
-
- /**
- * @return true to enable showing out of sync message
- */
- public boolean isOutOfSyncNotificationEnabled() {
- return outOfSyncNotificationEnabled;
- }
-
- /**
- * @return "Out of sync"
- */
- public String getOutOfSyncCaption() {
- return (outOfSyncNotificationEnabled ? outOfSyncCaption : null);
- }
-
- /**
- * @return "Something has caused us to be out of sync with the server.<br/>
- * Take note of any unsaved data, and <u>click here</u> to re-sync."
- */
- public String getOutOfSyncMessage() {
- return (outOfSyncNotificationEnabled ? outOfSyncMessage : null);
- }
-
- /**
* Returns the URL the user should be redirected to after dismissing the
* "you have to enable your cookies" message. Typically null.
*
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index b30f6acf16..7aada2402d 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -871,9 +871,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
if (allowServePrecompressedResource(request, urlStr)) {
// try to serve a precompressed version if available
- URL url = new URL(urlStr + ".gz");
- connection = url.openConnection();
try {
+ connection = new URL(urlStr + ".gz").openConnection();
is = connection.getInputStream();
// set gzip headers
response.setHeader("Content-Encoding", "gzip");
diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java
index 9e25f1d8ff..c01c74e5cd 100644
--- a/server/src/com/vaadin/server/communication/PushRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java
@@ -145,7 +145,7 @@ public class PushRequestHandler implements RequestHandler,
*/
static AtmosphereFramework initAtmosphere(
final ServletConfig vaadinServletConfig) {
- AtmosphereFramework atmosphere = new AtmosphereFramework() {
+ AtmosphereFramework atmosphere = new AtmosphereFramework(false, false) {
@Override
protected void analytics() {
// Overridden to disable version number check
diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index 450c11f5c4..65fb144810 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -76,13 +76,14 @@ public class ServerRpcHandler implements Serializable {
private final JsonArray invocations;
private final int syncId;
private final JsonObject json;
+ private final boolean resynchronize;
public RpcRequest(String jsonString, VaadinRequest request) {
json = JsonUtil.parse(jsonString);
JsonValue token = json.get(ApplicationConstants.CSRF_TOKEN);
if (token == null) {
- this.csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
+ csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
} else {
String csrfToken = token.asString();
if (csrfToken.equals("")) {
@@ -98,6 +99,14 @@ public class ServerRpcHandler implements Serializable {
} else {
syncId = -1;
}
+
+ if (json.hasKey(ApplicationConstants.RESYNCHRONIZE_ID)) {
+ resynchronize = json
+ .getBoolean(ApplicationConstants.RESYNCHRONIZE_ID);
+ } else {
+ resynchronize = false;
+ }
+
invocations = json.getArray(ApplicationConstants.RPC_INVOCATIONS);
}
@@ -131,6 +140,15 @@ public class ServerRpcHandler implements Serializable {
}
/**
+ * Checks if this is a request to resynchronize the client side
+ *
+ * @return true if this is a resynchronization request, false otherwise
+ */
+ public boolean isResynchronize() {
+ return resynchronize;
+ }
+
+ /**
* Gets the entire request in JSON format, as it was received from the
* client.
* <p>
@@ -186,6 +204,10 @@ public class ServerRpcHandler implements Serializable {
ui.getConnectorTracker().cleanConcurrentlyRemovedConnectorIds(
rpcRequest.getSyncId());
+
+ if (rpcRequest.isResynchronize()) {
+ ui.getSession().getCommunicationManager().repaintAll(ui);
+ }
}
/**
diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
index 6e338c5773..33a3669b7f 100644
--- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
@@ -80,10 +80,12 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements
// repaint requested or session has timed out and new one is created
boolean repaintAll;
- // TODO PUSH repaintAll, analyzeLayouts should be
+ // TODO PUSH analyzeLayouts should be
// part of the message payload to make the functionality transport
// agnostic
+ // Resynchronize is sent in the payload but will still support the
+ // parameter also for compatibility reasons
repaintAll = (request
.getParameter(ApplicationConstants.URL_PARAMETER_REPAINT_ALL) != null);
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index fd8a72ee23..27d97d5e03 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -405,6 +405,26 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
}
+ /**
+ * Returns the explicitly set immediate value.
+ *
+ * @return the explicitly set immediate value or null if
+ * {@link #setImmediate(boolean)} has not been explicitly invoked
+ */
+ protected Boolean getExplicitImmediateValue() {
+ return explicitImmediateValue;
+ }
+
+ /**
+ * Returns the immediate mode of the component.
+ * <p>
+ * Certain operations such as adding a value change listener will set the
+ * component into immediate mode if {@link #setImmediate(boolean)} has not
+ * been explicitly called with false.
+ *
+ * @return true if the component is in immediate mode (explicitly or
+ * implicitly set), false if the component if not in immediate mode
+ */
public boolean isImmediate() {
if (explicitImmediateValue != null) {
return explicitImmediateValue;
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index 5c02c9e5fb..cf14d1cb96 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -1745,6 +1745,24 @@ public abstract class AbstractField<T> extends AbstractComponent implements
}
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Fields are automatically set to immediate if validators have been added.
+ */
+ @Override
+ public boolean isImmediate() {
+ if (getExplicitImmediateValue() != null) {
+ return getExplicitImmediateValue();
+ }
+ // Make field immediate when there is some kind of validation present
+ // (validator or required). This will avoid the UI being in a wrong
+ // state, e.g. user entered valid data but old validation error is still
+ // shown
+ return super.isImmediate() || !getValidators().isEmpty()
+ || isRequired();
+ }
+
/*
* (non-Javadoc)
*
diff --git a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
index 767ae66515..0854ffe9c2 100644
--- a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
+++ b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
@@ -298,7 +298,9 @@ public abstract class AbstractSingleComponentContainer extends
* contains multiple child elements, a DesignException is thrown. This
* method should be overridden by subclasses whose design may contain
* non-content child elements.
- *
+ *
+ * @since 7.5.0
+ *
* @param children
* the child elements of the design that is being read
* @param context
diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java
index ceb47e1e7a..d64f70e95e 100644
--- a/server/src/com/vaadin/ui/CustomLayout.java
+++ b/server/src/com/vaadin/ui/CustomLayout.java
@@ -74,6 +74,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
* for setting the appropriate fields. Either
* {@link #setTemplateName(String)}, that makes layout fetch the template
* from theme, or {@link #setTemplateContents(String)}.
+ *
+ * @since 7.5.0
*/
public CustomLayout() {
setWidth(100, Unit.PERCENTAGE);
diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java
index b813973861..ba912f15dc 100644
--- a/server/src/com/vaadin/ui/DragAndDropWrapper.java
+++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java
@@ -191,6 +191,8 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
/**
* This is an internal constructor. Use
* {@link DragAndDropWrapper#DragAndDropWrapper(Component)} instead.
+ *
+ * @since 7.5.0
*/
@Deprecated
public DragAndDropWrapper() {
diff --git a/server/src/com/vaadin/ui/Flash.java b/server/src/com/vaadin/ui/Flash.java
index 2d0f188b84..6e99d2fe35 100644
--- a/server/src/com/vaadin/ui/Flash.java
+++ b/server/src/com/vaadin/ui/Flash.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.ui;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -236,7 +237,15 @@ public class Flash extends AbstractEmbedded {
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
+
+ // Parameters, in alphabetic order
+ ArrayList<String> paramNames = new ArrayList<String>();
for (String param : getParameterNames()) {
+ paramNames.add(param);
+ }
+
+ Collections.sort(paramNames);
+ for (String param : paramNames) {
design.appendElement("parameter").attr("name", param)
.attr("value", getParameter(param));
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 43e82560df..77785c301b 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -3270,14 +3270,16 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return getState().hidable;
}
- /*
+ /**
* Writes the design attributes for this column into given element.
*
* @since 7.5.0
*
- * @param design Element to write attributes into
+ * @param design
+ * Element to write attributes into
*
- * @param designContext the design context
+ * @param designContext
+ * the design context
*/
protected void writeDesign(Element design, DesignContext designContext) {
Attributes attributes = design.attributes();
@@ -3367,20 +3369,27 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
/**
* An abstract base class for server-side Grid renderers.
* {@link com.vaadin.client.widget.grid.Renderer Grid renderers}. This class
- * currently extends the AbstractExtension superclass, but this fact should
- * be regarded as an implementation detail and subject to change in a future
- * major or minor Vaadin revision.
+ * currently extends the AbstractGridExtension superclass, but this fact
+ * should be regarded as an implementation detail and subject to change in a
+ * future major or minor Vaadin revision.
*
* @param <T>
* the type this renderer knows how to present
*/
- public static abstract class AbstractRenderer<T> extends AbstractExtension
- implements Renderer<T> {
+ public static abstract class AbstractRenderer<T> extends
+ AbstractGridExtension implements Renderer<T> {
private final Class<T> presentationType;
- protected AbstractRenderer(Class<T> presentationType) {
+ private final String nullRepresentation;
+
+ protected AbstractRenderer(Class<T> presentationType, String nullRepresentation) {
this.presentationType = presentationType;
+ this.nullRepresentation = nullRepresentation;
+ }
+
+ protected AbstractRenderer(Class<T> presentationType) {
+ this(presentationType, null);
}
/**
@@ -3410,7 +3419,19 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public JsonValue encode(T value) {
- return encode(value, getPresentationType());
+ if (value == null) {
+ return encode(getNullRepresentation(), String.class);
+ } else {
+ return encode(value, getPresentationType());
+ }
+ }
+
+ /**
+ * Null representation for the renderer
+ * @return a textual representation of {@code null}
+ */
+ protected String getNullRepresentation() {
+ return nullRepresentation;
}
/**
@@ -3433,6 +3454,33 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return JsonCodec.encode(value, null, type,
getUI().getConnectorTracker()).getEncodedValue();
}
+ }
+
+ /**
+ * An abstract base class for server-side Grid extensions.
+ *
+ * @since 7.5
+ */
+ public static abstract class AbstractGridExtension extends
+ AbstractExtension {
+
+ /**
+ * Constructs a new Grid extension.
+ */
+ public AbstractGridExtension() {
+ super();
+ }
+
+ /**
+ * Constructs a new Grid extension and extends given Grid.
+ *
+ * @param grid
+ * a grid instance
+ */
+ public AbstractGridExtension(Grid grid) {
+ super();
+ extend(grid);
+ }
/**
* Gets the item id for a row key.
@@ -4416,6 +4464,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* added for any property id in propertyIds that has no corresponding column
* in this Grid.
*
+ * @since 7.5.0
+ *
* @param propertyIds
* properties in the desired column order
*/
@@ -5480,7 +5530,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public Iterator<Component> iterator() {
- List<Component> componentList = new ArrayList<Component>();
+ // This is a hash set to avoid adding header/footer components inside
+ // merged cells multiple times
+ LinkedHashSet<Component> componentList = new LinkedHashSet<Component>();
Header header = getHeader();
for (int i = 0; i < header.getRowCount(); ++i) {
@@ -5797,6 +5849,13 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
column.getState().editorConnector = getEditorField(column
.getPropertyId());
}
+
+ // Must ensure that all fields, recursively, are sent to the client
+ // This is needed because the fields are hidden using isRendered
+ for (Field<?> f : getEditorFields()) {
+ f.markAsDirtyRecursive();
+ }
+
}
private void setEditorField(Object propertyId, Field<?> field) {
@@ -6184,7 +6243,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return datasourceExtension.isDetailsVisible(itemId);
}
- protected SelectionMode getDefaultSelectionMode() {
+ private static SelectionMode getDefaultSelectionMode() {
return SelectionMode.SINGLE;
}
diff --git a/server/src/com/vaadin/ui/PasswordField.java b/server/src/com/vaadin/ui/PasswordField.java
index 1894804775..ff3b1fea1f 100644
--- a/server/src/com/vaadin/ui/PasswordField.java
+++ b/server/src/com/vaadin/ui/PasswordField.java
@@ -113,4 +113,10 @@ public class PasswordField extends AbstractTextField {
DesignAttributeHandler.writeAttribute("value", attr, getValue(),
def.getValue(), String.class);
}
+
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
}
diff --git a/server/src/com/vaadin/ui/PopupView.java b/server/src/com/vaadin/ui/PopupView.java
index 12034cb56c..73c93b29f3 100644
--- a/server/src/com/vaadin/ui/PopupView.java
+++ b/server/src/com/vaadin/ui/PopupView.java
@@ -69,6 +69,8 @@ public class PopupView extends AbstractComponent implements HasComponents {
/**
* This is an internal constructor. Use
* {@link PopupView#PopupView(String, Component)} instead.
+ *
+ * @since 7.5.0
*/
@Deprecated
public PopupView() {
@@ -106,6 +108,8 @@ public class PopupView extends AbstractComponent implements HasComponents {
/**
* Creates a Content from given text representation and popup content.
*
+ * @since 7.5.0
+ *
* @param minimizedValue
* text representation when popup is hidden
* @param popupContent
diff --git a/server/src/com/vaadin/ui/ProgressBar.java b/server/src/com/vaadin/ui/ProgressBar.java
index c288695ae1..89baac1e64 100644
--- a/server/src/com/vaadin/ui/ProgressBar.java
+++ b/server/src/com/vaadin/ui/ProgressBar.java
@@ -37,11 +37,13 @@ import com.vaadin.ui.declarative.DesignContext;
public class ProgressBar extends AbstractField<Float> implements
Property.Viewer, Property.ValueChangeListener {
+ private static final float DEFAULT_VALUE = 0f;
+
/**
* Creates a new progress bar initially set to 0% progress.
*/
public ProgressBar() {
- this(0);
+ this(DEFAULT_VALUE);
}
/**
@@ -170,4 +172,15 @@ public class ProgressBar extends AbstractField<Float> implements
DesignAttributeHandler.writeAttribute("value", design.attributes(),
getValue(), defaultValue, Float.class);
}
+
+ @Override
+ public void clear() {
+ setValue(DEFAULT_VALUE);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() || getValue() == DEFAULT_VALUE;
+
+ }
}
diff --git a/server/src/com/vaadin/ui/RichTextArea.java b/server/src/com/vaadin/ui/RichTextArea.java
index 763e42ad8b..7c23cce5cb 100644
--- a/server/src/com/vaadin/ui/RichTextArea.java
+++ b/server/src/com/vaadin/ui/RichTextArea.java
@@ -293,6 +293,11 @@ public class RichTextArea extends AbstractField<String> implements
}
@Override
+ public void clear() {
+ setValue("");
+ }
+
+ @Override
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
setValue(design.html());
diff --git a/server/src/com/vaadin/ui/Slider.java b/server/src/com/vaadin/ui/Slider.java
index 40a4047d53..2e00628eb0 100644
--- a/server/src/com/vaadin/ui/Slider.java
+++ b/server/src/com/vaadin/ui/Slider.java
@@ -104,9 +104,9 @@ public class Slider extends AbstractField<Double> {
*/
public Slider(double min, double max, int resolution) {
this();
- setMin(min);
- setMax(max);
setResolution(resolution);
+ setMax(max);
+ setMin(min);
}
/**
@@ -167,14 +167,15 @@ public class Slider extends AbstractField<Double> {
* The new maximum slider value
*/
public void setMax(double max) {
- getState().maxValue = max;
+ double roundedMax = getRoundedValue(max);
+ getState().maxValue = roundedMax;
- if (getMin() > max) {
- getState().minValue = max;
+ if (getMin() > roundedMax) {
+ getState().minValue = roundedMax;
}
- if (getValue() > max) {
- setValue(max);
+ if (getValue() > roundedMax) {
+ setValue(roundedMax);
}
}
@@ -195,14 +196,15 @@ public class Slider extends AbstractField<Double> {
* The new minimum slider value
*/
public void setMin(double min) {
- getState().minValue = min;
+ double roundedMin = getRoundedValue(min);
+ getState().minValue = roundedMin;
- if (getMax() < min) {
- getState().maxValue = min;
+ if (getMax() < roundedMin) {
+ getState().maxValue = roundedMin;
}
- if (getValue() < min) {
- setValue(min);
+ if (getValue() < roundedMin) {
+ setValue(roundedMin);
}
}
@@ -268,28 +270,28 @@ public class Slider extends AbstractField<Double> {
*/
@Override
protected void setValue(Double value, boolean repaintIsNotNeeded) {
- final double v = value.doubleValue();
- final int resolution = getResolution();
- double newValue;
-
- if (resolution > 0) {
- // Round up to resolution
- newValue = Math.floor(v * Math.pow(10, resolution));
- newValue = newValue / Math.pow(10, resolution);
- if (getMin() > newValue || getMax() < newValue) {
- throw new ValueOutOfBoundsException(newValue);
- }
- } else {
- newValue = (int) v;
- if (getMin() > newValue || getMax() < newValue) {
- throw new ValueOutOfBoundsException(newValue);
- }
+ double newValue = getRoundedValue(value);
+
+ if (getMin() > newValue || getMax() < newValue) {
+ throw new ValueOutOfBoundsException(newValue);
}
getState().value = newValue;
super.setValue(newValue, repaintIsNotNeeded);
}
+ private double getRoundedValue(Double value) {
+ final double v = value.doubleValue();
+ final int resolution = getResolution();
+
+ double ratio = Math.pow(10, resolution);
+ if(v >= 0) {
+ return Math.floor(v * ratio) / ratio;
+ } else {
+ return Math.ceil(v * ratio) / ratio;
+ }
+ }
+
@Override
public void setValue(Double newFieldValue) {
super.setValue(newFieldValue);
diff --git a/server/src/com/vaadin/ui/TextArea.java b/server/src/com/vaadin/ui/TextArea.java
index c8103f9c5b..b4dfb209e8 100644
--- a/server/src/com/vaadin/ui/TextArea.java
+++ b/server/src/com/vaadin/ui/TextArea.java
@@ -159,4 +159,10 @@ public class TextArea extends AbstractTextField {
super.writeDesign(design, designContext);
design.html(getValue());
}
+
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
}
diff --git a/server/src/com/vaadin/ui/Tree.java b/server/src/com/vaadin/ui/Tree.java
index 48f4e54831..aac827e5b5 100644
--- a/server/src/com/vaadin/ui/Tree.java
+++ b/server/src/com/vaadin/ui/Tree.java
@@ -273,7 +273,7 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* @param sendChildTree
* flag to indicate if client needs subtree or not (may be
* cached)
- * @return True iff the expand operation succeeded
+ * @return True if the expand operation succeeded
*/
private boolean expandItem(Object itemId, boolean sendChildTree) {
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index 8dd600ddd0..b16d7e32d3 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -16,6 +16,8 @@
package com.vaadin.ui;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
@@ -67,6 +69,7 @@ import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.shared.ui.ui.UIServerRpc;
import com.vaadin.shared.ui.ui.UIState;
import com.vaadin.ui.Component.Focusable;
+import com.vaadin.ui.declarative.Design;
import com.vaadin.util.ConnectorHelper;
import com.vaadin.util.CurrentInstance;
@@ -211,6 +214,32 @@ public abstract class UI extends AbstractSingleComponentContainer implements
json.toString());
}
+ @Override
+ public void showServerDesign(Connector connector) {
+ if (!(connector instanceof Component)) {
+ getLogger().severe(
+ "Tried to output declarative design for " + connector
+ + ", which is not a component");
+ return;
+ }
+ if (connector instanceof UI) {
+ // We want to see the content of the UI, so we can add it to
+ // another UI or component container
+ connector = ((UI) connector).getContent();
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ Design.write((Component) connector, baos);
+ getLogger().info(
+ "Design for " + connector
+ + " requested from debug window:\n"
+ + baos.toString("UTF-8"));
+ } catch (IOException e) {
+ getLogger().log(Level.WARNING,
+ "Error producing design for " + connector, e);
+ }
+
+ }
};
/**
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index e7764ffd8d..61664fc95d 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -21,9 +21,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -133,7 +130,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
super(caption, content);
registerRpc(rpc);
setSizeUndefined();
- setCloseShortcut(ShortcutAction.KeyCode.ESCAPE);
}
/* ********************************************************************* */
@@ -820,48 +816,14 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/*
* Actions
*/
- private LinkedHashSet<CloseShortcut> closeShortcuts = new LinkedHashSet<CloseShortcut>();
-
- protected Collection<CloseShortcut> getCloseShortcuts() {
- return Collections.unmodifiableCollection(closeShortcuts);
- }
-
- /**
- * Adds a keyboard shortcut for closing the window when user presses the
- * given {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
- * Note that this shortcut only reacts while the window has focus, closing
- * itself - if you want to close a window from a UI, use
- * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead.
- * <p>
- * If there is a prior CloseShortcut with the same keycode and modifiers,
- * that gets removed before the new one is added. Prior CloseShortcuts with
- * differing keycodes or modifiers are not affected.
- *
- * @param keyCode
- * the keycode for invoking the shortcut
- * @param modifiers
- * the (optional) modifiers for invoking the shortcut, null for
- * none
- */
- public void addCloseShortcut(int keyCode, int... modifiers) {
- // make sure there are no duplicates
- removeCloseShortcut(keyCode, modifiers);
- CloseShortcut closeShortcut = new CloseShortcut(this, keyCode,
- modifiers);
- closeShortcuts.add(closeShortcut);
- addAction(closeShortcut);
- }
+ protected CloseShortcut closeShortcut;
/**
- * Sets the keyboard shortcut for closing the window when user presses the
- * given {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
+ * Makes is possible to close the window by pressing the given
+ * {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
* Note that this shortcut only reacts while the window has focus, closing
* itself - if you want to close a window from a UI, use
* {@link UI#addAction(com.vaadin.event.Action)} of the UI instead.
- * <p>
- * If there are any prior CloseShortcuts when this method is called those
- * get removed before the new one is added. <b>NOTE: this also removes the
- * default shortcut that is added for accessibility purposes.</b>
*
* @param keyCode
* the keycode for invoking the shortcut
@@ -870,61 +832,22 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* none
*/
public void setCloseShortcut(int keyCode, int... modifiers) {
- removeCloseShortcuts();
- addCloseShortcut(keyCode, modifiers);
- }
-
- /**
- * Removes a keyboard shortcut previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)}.
- *
- * @param keyCode
- * the keycode for invoking the shortcut
- * @param modifiers
- * the (optional) modifiers for invoking the shortcut, null for
- * none
- */
- public void removeCloseShortcut(int keyCode, int... modifiers) {
- for (CloseShortcut closeShortcut : closeShortcuts) {
- if (closeShortcut.isTriggeredBy(keyCode, modifiers)) {
- removeAction(closeShortcut);
- closeShortcuts.remove(closeShortcut);
- break;
- }
+ if (closeShortcut != null) {
+ removeAction(closeShortcut);
}
+ closeShortcut = new CloseShortcut(this, keyCode, modifiers);
+ addAction(closeShortcut);
}
/**
- * @deprecated use {@link #resetCloseShortcuts()} instead, or
- * {@link #removeCloseShortcuts()} if you also want to get rid
- * of the default shortcut
+ * Removes the keyboard shortcut previously set with
+ * {@link #setCloseShortcut(int, int...)}.
*/
- @Deprecated
public void removeCloseShortcut() {
- resetCloseShortcuts();
- }
-
- /**
- * Removes all the keyboard shortcuts previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)} and re-adds the default shortcut
- * {@link KeyCode.ESCAPE}.
- */
- public void resetCloseShortcuts() {
- setCloseShortcut(ShortcutAction.KeyCode.ESCAPE);
- }
-
- /**
- * Removes all the keyboard shortcuts previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)}.
- */
- public void removeCloseShortcuts() {
- for (CloseShortcut closeShortcut : closeShortcuts) {
+ if (closeShortcut != null) {
removeAction(closeShortcut);
+ closeShortcut = null;
}
- closeShortcuts.clear();
}
/**
@@ -1391,8 +1314,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
private CloseShortcut getCloseShortcut() {
- Iterator<CloseShortcut> i = getCloseShortcuts().iterator();
- return i.hasNext() ? i.next() : null;
+ return closeShortcut;
}
@Override
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index d6cb970ce8..0d68c22ea0 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -171,6 +171,8 @@ public class DesignContext implements Serializable {
* component was mapped to some string s different from localId, the mapping
* from s to component is removed.
*
+ * @since 7.5.0
+ *
* @param component
* The component whose local id is to be set.
* @param localId
@@ -186,7 +188,9 @@ public class DesignContext implements Serializable {
}
/**
- * Returns the local id for a component
+ * Returns the local id for a component.
+ *
+ * @since 7.5.0
*
* @param component
* The component whose local id to get.
diff --git a/server/src/com/vaadin/ui/declarative/FieldBinder.java b/server/src/com/vaadin/ui/declarative/FieldBinder.java
index bd906682fa..577e9f5515 100644
--- a/server/src/com/vaadin/ui/declarative/FieldBinder.java
+++ b/server/src/com/vaadin/ui/declarative/FieldBinder.java
@@ -204,11 +204,14 @@ public class FieldBinder implements Serializable {
}
return true;
} catch (IllegalAccessException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
} catch (IllegalArgumentException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
} catch (InvocationTargetException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
}
}
diff --git a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
index ff73b61eb2..ffa51fedd1 100644
--- a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
+++ b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
@@ -28,8 +28,8 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.server.FontIcon;
import com.vaadin.server.GenericFontIcon;
import com.vaadin.server.Resource;
+import com.vaadin.server.ResourceReference;
import com.vaadin.server.ThemeResource;
-import com.vaadin.shared.ApplicationConstants;
import com.vaadin.ui.declarative.DesignAttributeHandler;
/**
@@ -109,8 +109,7 @@ public class DesignResourceConverter implements Converter<String, Resource> {
@Override
public String format(Resource value)
throws Converter.ConversionException {
- return ApplicationConstants.THEME_PROTOCOL_PREFIX
- + ((ThemeResource) value).getResourceId();
+ return new ResourceReference(value, null, null).getURL();
}
},
FONTICON {
@@ -118,8 +117,7 @@ public class DesignResourceConverter implements Converter<String, Resource> {
public Resource parse(String value) {
final String address = (value.split("://", 2))[1];
final String[] familyAndCode = address.split("/", 2);
- final int codepoint = Integer.valueOf(
- familyAndCode[1].substring(2), 16);
+ final int codepoint = Integer.valueOf(familyAndCode[1], 16);
if (FontAwesome.FONT_FAMILY.equals(familyAndCode[0])) {
try {
@@ -141,9 +139,8 @@ public class DesignResourceConverter implements Converter<String, Resource> {
public String format(Resource value)
throws Converter.ConversionException {
FontIcon icon = (FontIcon) value;
- return ApplicationConstants.FONTICON_PROTOCOL_PREFIX
- + icon.getFontFamily() + "/0x"
- + Integer.toHexString(icon.getCodepoint());
+ return new ResourceReference(icon, null, null).getURL();
+
}
},
@Deprecated
diff --git a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
index bed34cf6e3..104e07f02f 100644
--- a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
@@ -105,8 +105,12 @@ public abstract class AbstractJavaScriptRenderer<T> extends AbstractRenderer<T>
private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
this);
+ protected AbstractJavaScriptRenderer(Class<T> presentationType, String nullRepresentation) {
+ super(presentationType, nullRepresentation);
+ }
+
protected AbstractJavaScriptRenderer(Class<T> presentationType) {
- super(presentationType);
+ super(presentationType, null);
}
@Override
diff --git a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
index 0b070d3f69..a747e45713 100644
--- a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.ui.renderers;
+import elemental.json.JsonValue;
+
/**
* A Renderer that displays a button with a textual caption. The value of the
* corresponding property is used as the caption. Click listeners can be added
@@ -27,9 +29,12 @@ public class ButtonRenderer extends ClickableRenderer<String> {
/**
* Creates a new button renderer.
+ *
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
*/
- public ButtonRenderer() {
- super(String.class);
+ public ButtonRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
}
/**
@@ -37,9 +42,34 @@ public class ButtonRenderer extends ClickableRenderer<String> {
*
* @param listener
* the click listener to register
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
*/
- public ButtonRenderer(RendererClickListener listener) {
- this();
+ public ButtonRenderer(RendererClickListener listener, String nullRepresentation) {
+ this(nullRepresentation);
addClickListener(listener);
}
+
+ /**
+ * Creates a new button renderer.
+ */
+ public ButtonRenderer() {
+ this("");
+ }
+
+ /**
+ * Creates a new button renderer and adds the given click listener to it.
+ *
+ * @param listener
+ * the click listener to register
+ */
+ public ButtonRenderer(RendererClickListener listener) {
+ this(listener, "");
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
+
}
diff --git a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
index 38e9acef9c..01e939bb67 100644
--- a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
@@ -103,7 +103,11 @@ public class ClickableRenderer<T> extends AbstractRenderer<T> {
}
protected ClickableRenderer(Class<T> presentationType) {
- super(presentationType);
+ this(presentationType, null);
+ }
+
+ protected ClickableRenderer(Class<T> presentationType, String nullRepresentation) {
+ super(presentationType, nullRepresentation);
registerRpc(new RendererClickRpc() {
@Override
public void click(String rowKey, String columnId,
diff --git a/server/src/com/vaadin/ui/renderers/DateRenderer.java b/server/src/com/vaadin/ui/renderers/DateRenderer.java
index 9dd4d19e87..092b3f405e 100644
--- a/server/src/com/vaadin/ui/renderers/DateRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/DateRenderer.java
@@ -41,7 +41,7 @@ public class DateRenderer extends AbstractRenderer<Date> {
* representation for the default locale.
*/
public DateRenderer() {
- this(Locale.getDefault());
+ this(Locale.getDefault(), "");
}
/**
@@ -56,7 +56,24 @@ public class DateRenderer extends AbstractRenderer<Date> {
* if {@code locale} is {@code null}
*/
public DateRenderer(Locale locale) throws IllegalArgumentException {
- this("%s", locale);
+ this("%s", locale, "");
+ }
+
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the {@link Date#toString()}
+ * representation for the given locale.
+ *
+ * @param locale
+ * the locale in which to present dates
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code locale} is {@code null}
+ */
+ public DateRenderer(Locale locale, String nullRepresentation) throws IllegalArgumentException {
+ this("%s", locale, nullRepresentation);
}
/**
@@ -74,7 +91,27 @@ public class DateRenderer extends AbstractRenderer<Date> {
* String Syntax</a>
*/
public DateRenderer(String formatString) throws IllegalArgumentException {
- this(formatString, Locale.getDefault());
+ this(formatString, "");
+ }
+
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the given string format, as
+ * displayed in the default locale.
+ *
+ * @param formatString
+ * the format string with which to format the date
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code formatString} is {@code null}
+ * @see <a
+ * href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
+ * String Syntax</a>
+ */
+ public DateRenderer(String formatString, String nullRepresentation) throws IllegalArgumentException {
+ this(formatString, Locale.getDefault(), nullRepresentation);
}
/**
@@ -95,7 +132,29 @@ public class DateRenderer extends AbstractRenderer<Date> {
*/
public DateRenderer(String formatString, Locale locale)
throws IllegalArgumentException {
- super(Date.class);
+ this(formatString,locale, "");
+ }
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the given string format, as
+ * displayed in the given locale.
+ *
+ * @param formatString
+ * the format string to format the date with
+ * @param locale
+ * the locale to use
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if either argument is {@code null}
+ * @see <a
+ * href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
+ * String Syntax</a>
+ */
+ public DateRenderer(String formatString, Locale locale, String nullRepresentation)
+ throws IllegalArgumentException {
+ super(Date.class, nullRepresentation);
if (formatString == null) {
throw new IllegalArgumentException("format string may not be null");
@@ -121,7 +180,20 @@ public class DateRenderer extends AbstractRenderer<Date> {
* if {@code dateFormat} is {@code null}
*/
public DateRenderer(DateFormat dateFormat) throws IllegalArgumentException {
- super(Date.class);
+ this(dateFormat, "");
+ }
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with he given date format.
+ *
+ * @param dateFormat
+ * the date format to use when rendering dates
+ * @throws IllegalArgumentException
+ * if {@code dateFormat} is {@code null}
+ */
+ public DateRenderer(DateFormat dateFormat, String nullRepresentation) throws IllegalArgumentException {
+ super(Date.class, nullRepresentation);
if (dateFormat == null) {
throw new IllegalArgumentException("date format may not be null");
}
@@ -132,9 +204,16 @@ public class DateRenderer extends AbstractRenderer<Date> {
}
@Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
+
+ @Override
public JsonValue encode(Date value) {
String dateString;
- if (dateFormat != null) {
+ if (value == null) {
+ dateString = getNullRepresentation();
+ } else if (dateFormat != null) {
dateString = dateFormat.format(value);
} else {
dateString = String.format(locale, formatString, value);
diff --git a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
index 34774b3825..df89c60ad2 100644
--- a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
@@ -16,18 +16,33 @@
package com.vaadin.ui.renderers;
import com.vaadin.ui.Grid.AbstractRenderer;
+import elemental.json.JsonValue;
/**
* A renderer for presenting HTML content.
- *
- * @since 7.4
+ *
* @author Vaadin Ltd
+ * @since 7.4
*/
public class HtmlRenderer extends AbstractRenderer<String> {
/**
* Creates a new HTML renderer.
+ *
+ * @param nullRepresentation the html representation of {@code null} value
+ */
+ public HtmlRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
+ }
+
+ /**
+ * Creates a new HTML renderer.
*/
public HtmlRenderer() {
- super(String.class);
+ this("");
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
}
}
diff --git a/server/src/com/vaadin/ui/renderers/ImageRenderer.java b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
index 4bb3671033..2fb872583e 100644
--- a/server/src/com/vaadin/ui/renderers/ImageRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
@@ -39,7 +39,7 @@ public class ImageRenderer extends ClickableRenderer<Resource> {
* Creates a new image renderer.
*/
public ImageRenderer() {
- super(Resource.class);
+ super(Resource.class, null);
}
/**
@@ -55,7 +55,7 @@ public class ImageRenderer extends ClickableRenderer<Resource> {
@Override
public JsonValue encode(Resource resource) {
- if (!(resource instanceof ExternalResource || resource instanceof ThemeResource)) {
+ if (!(resource == null || resource instanceof ExternalResource || resource instanceof ThemeResource)) {
throw new IllegalArgumentException(
"ImageRenderer only supports ExternalResource and ThemeResource ("
+ resource.getClass().getSimpleName() + "given )");
diff --git a/server/src/com/vaadin/ui/renderers/NumberRenderer.java b/server/src/com/vaadin/ui/renderers/NumberRenderer.java
index 5c30e55b17..1d4d7e0ec9 100644
--- a/server/src/com/vaadin/ui/renderers/NumberRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/NumberRenderer.java
@@ -24,7 +24,7 @@ import elemental.json.JsonValue;
/**
* A renderer for presenting number values.
- *
+ *
* @since 7.4
* @author Vaadin Ltd
*/
@@ -35,7 +35,7 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the number's natural string
* representation in the default locale.
*/
@@ -45,18 +45,35 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render the number as defined with the given
* number format.
- *
+ *
* @param numberFormat
* the number format with which to display numbers
* @throws IllegalArgumentException
* if {@code numberFormat} is {@code null}
*/
- public NumberRenderer(NumberFormat numberFormat)
+ public NumberRenderer(NumberFormat numberFormat) {
+ this(numberFormat, "");
+ }
+
+ /**
+ * Creates a new number renderer.
+ * <p/>
+ * The renderer is configured to render the number as defined with the given
+ * number format.
+ *
+ * @param numberFormat
+ * the number format with which to display numbers
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code numberFormat} is {@code null}
+ */
+ public NumberRenderer(NumberFormat numberFormat, String nullRepresentation)
throws IllegalArgumentException {
- super(Number.class);
+ super(Number.class, nullRepresentation);
if (numberFormat == null) {
throw new IllegalArgumentException("Number format may not be null");
@@ -69,10 +86,10 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the number's natural string
* representation in the given locale.
- *
+ *
* @param locale
* the locale in which to display numbers
* @throws IllegalArgumentException
@@ -84,12 +101,29 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
- * The renderer is configured to render with the given format string in the
- * default locale.
- *
+ * <p/>
+ * The renderer is configured to render with the number's natural string
+ * representation in the given locale.
+ *
* @param formatString
* the format string with which to format the number
+ * @param locale
+ * the locale in which to display numbers
+ * @throws IllegalArgumentException
+ * if {@code locale} is {@code null}
+ */
+ public NumberRenderer(String formatString, Locale locale) throws IllegalArgumentException {
+ this(formatString, locale, ""); //This will call #toString() during formatting
+ }
+
+ /**
+ * Creates a new number renderer.
+ * <p/>
+ * The renderer is configured to render with the given format string in the
+ * default locale.
+ *
+ * @param
+ * formatString the format string with which to format the number
* @throws IllegalArgumentException
* if {@code formatString} is {@code null}
* @see <a
@@ -97,15 +131,15 @@ public class NumberRenderer extends AbstractRenderer<Number> {
* String Syntax</a>
*/
public NumberRenderer(String formatString) throws IllegalArgumentException {
- this(formatString, Locale.getDefault());
+ this(formatString, Locale.getDefault(), "");
}
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the given format string in the
* given locale.
- *
+ *
* @param formatString
* the format string with which to format the number
* @param locale
@@ -116,8 +150,8 @@ public class NumberRenderer extends AbstractRenderer<Number> {
* href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
* String Syntax</a>
*/
- public NumberRenderer(String formatString, Locale locale) {
- super(Number.class);
+ public NumberRenderer(String formatString, Locale locale, String nullRepresentation) {
+ super(Number.class, nullRepresentation);
if (formatString == null) {
throw new IllegalArgumentException("Format string may not be null");
@@ -135,7 +169,9 @@ public class NumberRenderer extends AbstractRenderer<Number> {
@Override
public JsonValue encode(Number value) {
String stringValue;
- if (formatString != null && locale != null) {
+ if (value == null) {
+ stringValue = getNullRepresentation();
+ } else if (formatString != null && locale != null) {
stringValue = String.format(locale, formatString, value);
} else if (numberFormat != null) {
stringValue = numberFormat.format(value);
@@ -160,4 +196,9 @@ public class NumberRenderer extends AbstractRenderer<Number> {
return String.format("%s [%s]", getClass().getSimpleName(), fieldInfo);
}
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
}
diff --git a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
index a077cd8012..1566c47222 100644
--- a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
@@ -21,9 +21,9 @@ import elemental.json.JsonValue;
/**
* A renderer that represents a double values as a graphical progress bar.
- *
- * @since 7.4
+ *
* @author Vaadin Ltd
+ * @since 7.4
*/
public class ProgressBarRenderer extends AbstractRenderer<Double> {
@@ -31,13 +31,15 @@ public class ProgressBarRenderer extends AbstractRenderer<Double> {
* Creates a new text renderer
*/
public ProgressBarRenderer() {
- super(Double.class);
+ super(Double.class, null);
}
@Override
public JsonValue encode(Double value) {
if (value != null) {
value = Math.max(Math.min(value, 1), 0);
+ } else {
+ value = 0d;
}
return super.encode(value);
}
diff --git a/server/src/com/vaadin/ui/renderers/TextRenderer.java b/server/src/com/vaadin/ui/renderers/TextRenderer.java
index 3723a45f70..0045024b2f 100644
--- a/server/src/com/vaadin/ui/renderers/TextRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/TextRenderer.java
@@ -16,6 +16,7 @@
package com.vaadin.ui.renderers;
import com.vaadin.ui.Grid.AbstractRenderer;
+import elemental.json.JsonValue;
/**
* A renderer for presenting simple plain-text string values.
@@ -29,6 +30,20 @@ public class TextRenderer extends AbstractRenderer<String> {
* Creates a new text renderer
*/
public TextRenderer() {
- super(String.class);
+ this("");
+ }
+
+ /**
+ * Creates a new text renderer
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ */
+ public TextRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
}
}
diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java
index c70462012e..b2cc9a5d0c 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java
@@ -29,9 +29,9 @@ import com.vaadin.data.Item;
import com.vaadin.data.util.filter.Like;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants.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;
+import com.vaadin.data.util.sqlcontainer.query.ValidatingSimpleJDBCConnectionPool;
public class SQLContainerTableQueryTest {
@@ -51,7 +51,7 @@ public class SQLContainerTableQueryTest {
public void setUp() throws SQLException {
try {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
} catch (SQLException e) {
@@ -99,7 +99,7 @@ public class SQLContainerTableQueryTest {
assertTrue(container.removeItem(container.lastItemId()));
}
- @Test(expected = IllegalArgumentException.class)
+ @Test(expected = SQLException.class)
public void itemWithNonExistingVersionColumnCannotBeRemoved()
throws SQLException {
query.setVersionColumn("version");
diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java
index 4c132eba30..a332d9d9ee 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java
@@ -26,11 +26,11 @@ import com.vaadin.data.util.filter.Compare.Equal;
import com.vaadin.data.util.filter.Like;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants.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.ValidatingSimpleJDBCConnectionPool;
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;
@@ -45,7 +45,7 @@ public class SQLContainerTest {
public void setUp() throws SQLException {
try {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
} catch (SQLException e) {
diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java
index 110225e206..e180e3f3e7 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java
@@ -16,10 +16,11 @@ 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.SQLTestsConstants.DB;
-import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool;
+import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool;
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.ValidatingSimpleJDBCConnectionPool;
import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper;
import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder;
import com.vaadin.ui.Table;
@@ -27,11 +28,11 @@ import com.vaadin.ui.Window;
public class TicketTests {
- private SimpleJDBCConnectionPool connectionPool;
+ private JDBCConnectionPool connectionPool;
@Before
public void setUp() throws SQLException {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
DataGenerator.addPeopleToDatabase(connectionPool);
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
index 99ad420229..b786f5b2de 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java
@@ -9,13 +9,14 @@ import org.junit.Before;
import org.junit.Test;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants;
+import com.vaadin.data.util.sqlcontainer.query.ValidatingSimpleJDBCConnectionPool;
public class SimpleJDBCConnectionPoolTest {
private JDBCConnectionPool connectionPool;
@Before
public void setUp() throws SQLException {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
}
@@ -145,8 +146,11 @@ public class SimpleJDBCConnectionPoolTest {
EasyMock.expectLastCall().atLeastOnce();
EasyMock.replay(c);
// make sure the connection pool is initialized
- connectionPool.reserveConnection();
- connectionPool.releaseConnection(c);
+ // Bypass validation
+ JDBCConnectionPool realPool = ((ValidatingSimpleJDBCConnectionPool) connectionPool)
+ .getRealPool();
+ realPool.reserveConnection();
+ realPool.releaseConnection(c);
EasyMock.verify(c);
}
@@ -154,7 +158,13 @@ public class SimpleJDBCConnectionPoolTest {
public void destroy_shouldCloseAllConnections() throws SQLException {
Connection c1 = connectionPool.reserveConnection();
Connection c2 = connectionPool.reserveConnection();
- connectionPool.destroy();
+ try {
+ connectionPool.destroy();
+ } catch (RuntimeException e) {
+ // The test connection pool throws an exception when the pool was
+ // not empty but only after cleanup of the real pool has been done
+ }
+
Assert.assertTrue(c1.isClosed());
Assert.assertTrue(c2.isClosed());
}
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
index 59e879a8e0..c2dbf0f12a 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java
@@ -18,9 +18,9 @@ import com.vaadin.data.util.sqlcontainer.RowItem;
import com.vaadin.data.util.sqlcontainer.SQLContainer;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants;
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.ValidatingSimpleJDBCConnectionPool;
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;
@@ -34,7 +34,7 @@ public class SQLGeneratorsTest {
public void setUp() throws SQLException {
try {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
} catch (SQLException e) {
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
index 195911475e..e193b79df3 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java
@@ -23,7 +23,6 @@ import com.vaadin.data.util.sqlcontainer.SQLContainer;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants.DB;
import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool;
-import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool;
public class FreeformQueryTest {
@@ -34,7 +33,7 @@ public class FreeformQueryTest {
public void setUp() throws SQLException {
try {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
} catch (SQLException e) {
@@ -148,7 +147,10 @@ public class FreeformQueryTest {
connectionPool, "ID");
query.getCount();
query.getCount();
- Assert.assertNotNull(connectionPool.reserveConnection());
+ Connection c = connectionPool.reserveConnection();
+ Assert.assertNotNull(c);
+ // Cleanup to make test connection pool happy
+ connectionPool.releaseConnection(c);
}
@Test
@@ -276,37 +278,38 @@ public class FreeformQueryTest {
new Object[] { 1 }), null));
}
- @Test(expected = UnsupportedOperationException.class)
+ @Test
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);
+ try {
+ query.storeRow(new RowItem(container,
+ new RowId(new Object[] { 1 }), null));
+ Assert.fail("storeRow should fail when there is no delegate");
+ } catch (UnsupportedOperationException e) {
+ // Cleanup to make test connection pool happy
+ query.rollback();
+ }
}
- @Test(expected = UnsupportedOperationException.class)
+ @Test
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();
+ try {
+ query.removeRow(new RowItem(container,
+ new RowId(new Object[] { 1 }), null));
+ Assert.fail("removeRow should fail when there is no delgate");
+ } catch (UnsupportedOperationException e) {
+ // Cleanup to make test connection pool happy
+ query.rollback();
+ }
}
@Test
@@ -628,7 +631,7 @@ public class FreeformQueryTest {
EasyMock.verify(delegate, container);
}
- @Test(expected = UnsupportedOperationException.class)
+ @Test
public void storeRow_delegateDoesNotImplementStoreRow_shouldFail()
throws SQLException {
FreeformQuery query = new FreeformQuery("SELECT * FROM people",
@@ -646,10 +649,13 @@ public class FreeformQueryTest {
query.beginTransaction();
RowItem row = new RowItem(container, new RowId(new Object[] { 1 }),
null);
- query.storeRow(row);
- query.commit();
-
- EasyMock.verify(delegate, container);
+ try {
+ query.storeRow(row);
+ Assert.fail("storeRow should fail when delgate does not implement storeRow");
+ } catch (UnsupportedOperationException e) {
+ // Cleanup to make test connection pool happy
+ query.rollback();
+ }
}
@Test
@@ -675,7 +681,7 @@ public class FreeformQueryTest {
EasyMock.verify(delegate, container);
}
- @Test(expected = UnsupportedOperationException.class)
+ @Test
public void removeRow_delegateDoesNotImplementRemoveRow_shouldFail()
throws SQLException {
FreeformQuery query = new FreeformQuery("SELECT * FROM people",
@@ -693,10 +699,13 @@ public class FreeformQueryTest {
query.beginTransaction();
RowItem row = new RowItem(container, new RowId(new Object[] { 1 }),
null);
- query.removeRow(row);
- query.commit();
-
- EasyMock.verify(delegate, container);
+ try {
+ query.removeRow(row);
+ Assert.fail("removeRow should fail when delegate does not implement removeRow");
+ } catch (UnsupportedOperationException e) {
+ // Cleanup to make test connection pool happy
+ query.rollback();
+ }
}
@Test
@@ -710,16 +719,24 @@ public class FreeformQueryTest {
query.setDelegate(delegate);
query.beginTransaction();
+ // Cleanup to make test connection pool happy
+ query.rollback();
}
- @Test(expected = IllegalStateException.class)
+ @Test
public void beginTransaction_transactionAlreadyActive_shouldFail()
throws SQLException {
FreeformQuery query = new FreeformQuery("SELECT * FROM people",
Arrays.asList("ID"), connectionPool);
query.beginTransaction();
- query.beginTransaction();
+ try {
+ query.beginTransaction();
+ Assert.fail("Should throw exception when starting a transaction while already in a transaction");
+ } catch (IllegalStateException e) {
+ // Cleanup to make test connection pool happy
+ query.rollback();
+ }
}
@Test(expected = SQLException.class)
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
index f009fc505e..1cb3d722c6 100644
--- a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java
@@ -24,7 +24,6 @@ import com.vaadin.data.util.sqlcontainer.SQLContainer;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants;
import com.vaadin.data.util.sqlcontainer.SQLTestsConstants.DB;
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 {
@@ -33,16 +32,14 @@ public class TableQueryTest {
@Before
public void setUp() throws SQLException {
-
try {
- connectionPool = new SimpleJDBCConnectionPool(
+ connectionPool = new ValidatingSimpleJDBCConnectionPool(
SQLTestsConstants.dbDriver, SQLTestsConstants.dbURL,
SQLTestsConstants.dbUser, SQLTestsConstants.dbPwd, 2, 2);
} catch (SQLException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
-
DataGenerator.addPeopleToDatabase(connectionPool);
}
@@ -139,7 +136,9 @@ public class TableQueryTest {
SQLTestsConstants.sqlGen);
tQuery.getCount();
tQuery.getCount();
- Assert.assertNotNull(connectionPool.reserveConnection());
+ Connection c = connectionPool.reserveConnection();
+ Assert.assertNotNull(c);
+ connectionPool.releaseConnection(c);
}
/**********************************************************************
@@ -193,20 +192,19 @@ public class TableQueryTest {
* TableQuery transaction management tests
**********************************************************************/
@Test
- public void beginTransaction_readOnly_shouldSucceed() throws SQLException {
- TableQuery tQuery = new TableQuery("people", connectionPool,
- SQLTestsConstants.sqlGen);
- tQuery.beginTransaction();
- }
-
- @Test(expected = IllegalStateException.class)
public void beginTransaction_transactionAlreadyActive_shouldFail()
throws SQLException {
TableQuery tQuery = new TableQuery("people", connectionPool,
SQLTestsConstants.sqlGen);
tQuery.beginTransaction();
- tQuery.beginTransaction();
+ try {
+ tQuery.beginTransaction();
+ Assert.fail("Should throw exception when starting a transaction while already in a transaction");
+ } catch (IllegalStateException e) {
+ // Cleanup to make test connection pool happy
+ tQuery.rollback();
+ }
}
@Test
@@ -284,8 +282,13 @@ public class TableQueryTest {
.fail("null should throw an IllegalArgumentException from StatementHelper");
} catch (IllegalArgumentException e) {
// We should now be able to reserve two connections
- connectionPool.reserveConnection();
- connectionPool.reserveConnection();
+ Connection c1 = connectionPool.reserveConnection();
+ Connection c2 = connectionPool.reserveConnection();
+
+ // Cleanup to make test connection pool happy
+ connectionPool.releaseConnection(c1);
+ connectionPool.releaseConnection(c2);
+
}
}
@@ -693,6 +696,9 @@ public class TableQueryTest {
// cleanup - might not be an in-memory DB
statement.execute(SQLTestsConstants.dropSchema);
}
+
+ // Cleanup to make test connection pool happy
+ connectionPool.releaseConnection(conn);
}
@Test
diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/ValidatingSimpleJDBCConnectionPool.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/ValidatingSimpleJDBCConnectionPool.java
new file mode 100644
index 0000000000..464f3c8562
--- /dev/null
+++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/ValidatingSimpleJDBCConnectionPool.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2014 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.data.util.sqlcontainer.query;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool;
+import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool;
+
+/**
+ * Connection pool for testing SQLContainer. Ensures that only reserved
+ * connections are released and that all connections are released before the
+ * pool is destroyed.
+ *
+ * @author Vaadin Ltd
+ */
+public class ValidatingSimpleJDBCConnectionPool implements JDBCConnectionPool {
+
+ private JDBCConnectionPool realPool;
+ private Set<Connection> reserved = new HashSet<Connection>();
+ private Set<Connection> alreadyReleased = new HashSet<Connection>();
+
+ public ValidatingSimpleJDBCConnectionPool(String driverName,
+ String connectionUri, String userName, String password,
+ int initialConnections, int maxConnections) throws SQLException {
+ realPool = new SimpleJDBCConnectionPool(driverName, connectionUri,
+ userName, password, initialConnections, maxConnections);
+ }
+
+ @Deprecated
+ public JDBCConnectionPool getRealPool() {
+ return realPool;
+ }
+
+ @Override
+ public Connection reserveConnection() throws SQLException {
+ Connection c = realPool.reserveConnection();
+ reserved.add(c);
+ return c;
+ }
+
+ @Override
+ public void releaseConnection(Connection conn) {
+ if (conn != null && !reserved.remove(conn)) {
+ if (alreadyReleased.contains(conn)) {
+ getLogger().severe(
+ "Tried to release connection (" + conn
+ + ") which has already been released");
+ } else {
+ throw new RuntimeException("Tried to release connection ("
+ + conn + ") not reserved using reserveConnection");
+ }
+ }
+ realPool.releaseConnection(conn);
+ alreadyReleased.add(conn);
+
+ }
+
+ @Override
+ public void destroy() {
+ realPool.destroy();
+ if (!reserved.isEmpty()) {
+ throw new RuntimeException(reserved.size()
+ + " connections never released");
+ }
+ }
+
+ public static Logger getLogger() {
+ return Logger.getLogger(ValidatingSimpleJDBCConnectionPool.class
+ .getName());
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java b/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java
new file mode 100644
index 0000000000..96ca82a0b3
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2014 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.communication.FieldRpc.BlurServerRpc;
+import com.vaadin.shared.ui.ClickRpc;
+
+/**
+ * We test that AbstractClientConnector has a suitable isThis method which is
+ * needed to correctly perform an equals check between a proxy and it's
+ * underlying instance.
+ *
+ * @author Vaadin Ltd
+ */
+public class AbstractClientConnectorTest {
+
+ @Test
+ public void registerRPCMultiInterfaceTest() {
+ AbstractClientConnector mock = mock(AbstractClientConnector.class);
+ MultiServerRpcMock implementation = new MultiServerRpcMock();
+ Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+ try {
+ mock.registerRpc(implementation);
+ Assert.fail("expected exception");
+ } catch (Exception expected) {
+ Assert.assertEquals(
+ expected.getMessage(),
+ "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ }
+ }
+
+ @Test
+ public void registerRPCInterfaceTest() {
+ AbstractClientConnector mock = mock(AbstractClientConnector.class);
+ ServerRpcMock implementation = new ServerRpcMock();
+ Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+ mock.registerRpc(implementation);
+ verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
+ }
+
+ @Test
+ public void registerRPCInterfaceLastTest() {
+ AbstractClientConnector mock = mock(AbstractClientConnector.class);
+ ServerRpcLastMock implementation = new ServerRpcLastMock();
+ Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+ mock.registerRpc(implementation);
+ verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
+ }
+
+ private class ServerRpcLastMock implements Comparable<ServerRpcLastMock>,
+ ClickRpc {
+ private static final long serialVersionUID = -2822356895755286180L;
+
+ @Override
+ public void click(MouseEventDetails mouseDetails) {
+ }
+
+ @Override
+ public int compareTo(ServerRpcLastMock o) {
+ return 0;
+ }
+
+ }
+
+ private class ServerRpcMock implements ClickRpc {
+ private static final long serialVersionUID = 2822356895755286180L;
+
+ @Override
+ public void click(MouseEventDetails mouseDetails) {
+ }
+
+ }
+
+ private class MultiServerRpcMock implements ClickRpc, BlurServerRpc {
+
+ private static final long serialVersionUID = -7611999715560330373L;
+
+ @Override
+ public void blur() {
+
+ }
+
+ @Override
+ public void click(MouseEventDetails mouseDetails) {
+
+ }
+
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/tests/design/DesignFormatterTest.java b/server/tests/src/com/vaadin/tests/design/DesignFormatterTest.java
index dcabd6c637..00af20ea8c 100644
--- a/server/tests/src/com/vaadin/tests/design/DesignFormatterTest.java
+++ b/server/tests/src/com/vaadin/tests/design/DesignFormatterTest.java
@@ -275,8 +275,8 @@ public class DesignFormatterTest {
String httpUrl = "http://example.com/icon.png";
String httpsUrl = "https://example.com/icon.png";
String themePath = "icons/icon.png";
- String fontAwesomeUrl = "fonticon://FontAwesome/0xf0f9";
- String someOtherFontUrl = "fonticon://SomeOther/0xF0F9";
+ String fontAwesomeUrl = "fonticon://FontAwesome/f0f9";
+ String someOtherFontUrl = "fonticon://SomeOther/F0F9";
String fileSystemPath = "c:\\app\\resources\\icon.png";
assertEquals(httpUrl, formatter.format(new ExternalResource(httpUrl)));
@@ -315,8 +315,8 @@ public class DesignFormatterTest {
String httpUrl = "http://example.com/icon.png";
String httpsUrl = "https://example.com/icon.png";
String themePath = "icons/icon.png";
- String fontAwesomeUrl = "fonticon://FontAwesome/0xf0f9";
- String someOtherFont = "fonticon://SomeOther/0xF0F9";
+ String fontAwesomeUrl = "fonticon://FontAwesome/f0f9";
+ String someOtherFont = "fonticon://SomeOther/F0F9";
String fontAwesomeUrlOld = "font://AMBULANCE";
String fileSystemPath = "c:\\app\\resources\\icon.png";
diff --git a/server/tests/src/com/vaadin/tests/server/component/FieldDefaultValues.java b/server/tests/src/com/vaadin/tests/server/component/FieldDefaultValues.java
index 5c9993e6dd..16bbd7008f 100644
--- a/server/tests/src/com/vaadin/tests/server/component/FieldDefaultValues.java
+++ b/server/tests/src/com/vaadin/tests/server/component/FieldDefaultValues.java
@@ -23,11 +23,7 @@ import org.junit.Test;
import com.vaadin.tests.VaadinClasses;
import com.vaadin.ui.Field;
-import com.vaadin.ui.PasswordField;
-import com.vaadin.ui.ProgressBar;
-import com.vaadin.ui.RichTextArea;
import com.vaadin.ui.Slider;
-import com.vaadin.ui.TextArea;
public class FieldDefaultValues {
@@ -36,13 +32,6 @@ public class FieldDefaultValues {
for (Field<?> field : createFields()) {
Object originalValue = field.getValue();
- // Some fields are not initialized to the "empty" value. #17089
- if (field instanceof PasswordField || field instanceof ProgressBar
- || field instanceof RichTextArea
- || field instanceof TextArea) {
- originalValue = null;
- }
-
field.clear();
Object clearedValue = field.getValue();
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidatorsTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidatorsTest.java
index 61aafe317d..59831d92e1 100644
--- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidatorsTest.java
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidatorsTest.java
@@ -1,16 +1,19 @@
package com.vaadin.tests.server.component.abstractfield;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import org.easymock.EasyMock;
+import org.junit.Test;
import com.vaadin.data.Validator;
import com.vaadin.ui.AbstractField;
-import com.vaadin.ui.Field;
-public class AbsFieldValidatorsTest extends TestCase {
+public class AbsFieldValidatorsTest {
- Field<Object> field = new AbstractField<Object>() {
+ AbstractField<Object> field = new AbstractField<Object>() {
@Override
public Class getType() {
return Object.class;
@@ -20,6 +23,7 @@ public class AbsFieldValidatorsTest extends TestCase {
Validator validator = EasyMock.createMock(Validator.class);
Validator validator2 = EasyMock.createMock(Validator.class);
+ @Test
public void testAddValidator() {
assertNotNull(field.getValidators());
assertEquals(0, field.getValidators().size());
@@ -34,6 +38,7 @@ public class AbsFieldValidatorsTest extends TestCase {
assertTrue(field.getValidators().contains(validator2));
}
+ @Test
public void testRemoveValidator() {
field.addValidator(validator);
field.addValidator(validator2);
@@ -51,6 +56,7 @@ public class AbsFieldValidatorsTest extends TestCase {
assertFalse(field.getValidators().contains(validator2));
}
+ @Test
public void testRemoveAllValidators() {
field.addValidator(validator);
field.addValidator(validator2);
@@ -61,4 +67,51 @@ public class AbsFieldValidatorsTest extends TestCase {
assertFalse(field.getValidators().contains(validator));
assertFalse(field.getValidators().contains(validator2));
}
+
+ @Test
+ public void validatorShouldMakeImmediate() {
+ assertFalse("field should not be immediate by default",
+ field.isImmediate());
+ field.addValidator(validator);
+ assertTrue("field should be immediate when it has a validator",
+ field.isImmediate());
+ }
+
+ @Test
+ public void nonImmediateFieldWithValidator() {
+ field.setImmediate(false);
+ field.addValidator(validator);
+ assertFalse("field should be non-immediate because explicitly set",
+ field.isImmediate());
+ }
+
+ @Test
+ public void removeValidatorMakesNonImmediate() {
+ field.addValidator(validator);
+ field.removeValidator(validator);
+ assertFalse(
+ "field should be non-immediate after validator was removed",
+ field.isImmediate());
+ }
+
+ @Test
+ public void requiredMakesImmediate() {
+ assertFalse("field should not be immediate by default",
+ field.isImmediate());
+ field.setRequired(true);
+ assertTrue("field should be immediate when it is required",
+ field.isImmediate());
+ }
+
+ @Test
+ public void removeRequiredMakesNonImmediate() {
+ assertFalse("field should not be immediate by default",
+ field.isImmediate());
+ field.setRequired(true);
+ field.setRequired(false);
+ assertFalse(
+ "field should not be immediate even though it was required",
+ field.isImmediate());
+ }
+
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
index e277d4e075..2334542676 100644
--- a/server/tests/src/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
@@ -102,6 +102,8 @@ public class RemoveFromParentLockingTest {
"Cannot remove from parent when the session is not locked."
+ " Furthermore, there is another locked session, indicating that the component might be about to be moved from one session to another.",
e.getMessage());
+ } finally {
+ VaadinSession.setCurrent(null);
}
}
@@ -119,6 +121,8 @@ public class RemoveFromParentLockingTest {
notLockedComponent.addComponent(lockedComponent);
} catch (AssertionError e) {
// All is fine, don't care about the exact wording in this case
+ } finally {
+ VaadinSession.setCurrent(null);
}
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridChildren.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridChildren.java
new file mode 100644
index 0000000000..7af1cfef69
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridChildren.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 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.grid;
+
+import java.util.Iterator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.FooterCell;
+import com.vaadin.ui.Grid.HeaderCell;
+import com.vaadin.ui.Label;
+
+public class GridChildren {
+
+ @Test
+ public void componentsInMergedHeader() {
+ Grid grid = new Grid();
+ grid.addColumn("foo");
+ grid.addColumn("bar");
+ grid.addColumn("baz");
+ HeaderCell merged = grid.getDefaultHeaderRow()
+ .join("foo", "bar", "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Iterator<Component> i = grid.iterator();
+ Assert.assertEquals(label, i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+ @Test
+ public void componentsInMergedFooter() {
+ Grid grid = new Grid();
+ grid.addColumn("foo");
+ grid.addColumn("bar");
+ grid.addColumn("baz");
+ FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Iterator<Component> i = grid.iterator();
+ Assert.assertEquals(label, i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridExtensionTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridExtensionTest.java
new file mode 100644
index 0000000000..d9db217aa3
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridExtensionTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 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.grid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.AbstractGridExtension;
+
+public class GridExtensionTest {
+
+ public static class DummyGridExtension extends AbstractGridExtension {
+
+ public DummyGridExtension(Grid grid) {
+ super(grid);
+ }
+ }
+
+ @Test
+ public void testCreateExtension() {
+ Grid grid = new Grid();
+ DummyGridExtension dummy = new DummyGridExtension(grid);
+ assertTrue("DummyGridExtension never made it to Grid", grid
+ .getExtensions().contains(dummy));
+ }
+}
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
index d2e2654cbc..7f20f29648 100644
--- a/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java
+++ b/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java
@@ -76,4 +76,60 @@ public class SliderTest {
assertThat(slider.getValue(), is(99.01234567891234567890123456789));
}
+
+ @Test
+ public void doublesCanBeUsedAsLimits() {
+ Slider slider = new Slider(1.5, 2.5, 1);
+
+ assertThat(slider.getMin(), is(1.5));
+ assertThat(slider.getValue(), is(1.5));
+ assertThat(slider.getMax(), is(2.5));
+ }
+
+ @Test
+ public void valuesGreaterThanIntMaxValueCanBeUsed() {
+ double minValue = (double)Integer.MAX_VALUE + 1;
+
+ Slider s = new Slider(minValue, minValue + 1, 0);
+
+ assertThat(s.getValue(), is(minValue));
+ }
+
+ @Test
+ public void negativeValuesCanBeUsed() {
+ Slider slider = new Slider(-0.7, 1.0, 0);
+
+ slider.setValue(-0.4);
+
+ assertThat(slider.getValue(), is(-0.0));
+ }
+
+ @Test
+ public void boundariesAreRounded() {
+ Slider slider = new Slider(1.5, 2.5, 0);
+
+ slider.setValue(1.0);
+
+ assertThat(slider.getValue(), is(1.0));
+ assertThat(slider.getMin(), is(1.0));
+ assertThat(slider.getMax(), is(2.0));
+ }
+
+ @Test
+ public void valueWithSmallerPrecisionCanBeUsed() {
+ Slider slider = new Slider(0, 100, 10);
+
+ slider.setValue(1.2);
+
+ assertThat(slider.getValue(), is(1.2));
+ }
+
+ @Test
+ public void valueWithLargerPrecisionCanBeUsed() {
+ Slider slider = new Slider(0, 100, 2);
+
+ slider.setValue(1.2345);
+
+ assertThat(slider.getValue(), is(1.23));
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java b/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java
index 8bcbc6a5a9..8a01464180 100644
--- a/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java
+++ b/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java
@@ -15,15 +15,6 @@
*/
package com.vaadin.tests.server.renderer;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import java.util.Locale;
-
-import org.junit.Before;
-import org.junit.Test;
-
import com.vaadin.data.Item;
import com.vaadin.data.RpcDataProviderExtension;
import com.vaadin.data.util.IndexedContainer;
@@ -34,9 +25,21 @@ import com.vaadin.tests.server.component.grid.TestGrid;
import com.vaadin.tests.util.AlwaysLockedVaadinSession;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.renderers.ButtonRenderer;
+import com.vaadin.ui.renderers.DateRenderer;
+import com.vaadin.ui.renderers.HtmlRenderer;
+import com.vaadin.ui.renderers.NumberRenderer;
import com.vaadin.ui.renderers.TextRenderer;
-
import elemental.json.JsonValue;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Date;
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
public class RendererTest {
@@ -64,14 +67,14 @@ public class RendererTest {
@Override
public TestBean convertToModel(String value,
- Class<? extends TestBean> targetType, Locale locale)
+ Class<? extends TestBean> targetType, Locale locale)
throws ConversionException {
return null;
}
@Override
public String convertToPresentation(TestBean value,
- Class<? extends String> targetType, Locale locale)
+ Class<? extends String> targetType, Locale locale)
throws ConversionException {
if (value instanceof ExtendedBean) {
return "ExtendedBean(" + value.i + ", "
@@ -94,101 +97,151 @@ public class RendererTest {
private Grid grid;
- private Column foo;
- private Column bar;
- private Column baz;
- private Column bah;
+ private Column intColumn;
+ private Column textColumn;
+ private Column beanColumn;
+ private Column htmlColumn;
+ private Column numberColumn;
+ private Column dateColumn;
+ private Column extendedBeanColumn;
+ private Column buttonColumn;
@Before
+ @SuppressWarnings("unchecked")
public void setUp() {
VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null));
IndexedContainer c = new IndexedContainer();
- c.addContainerProperty("foo", Integer.class, 0);
- c.addContainerProperty("bar", String.class, "");
- c.addContainerProperty("baz", TestBean.class, null);
- c.addContainerProperty("bah", ExtendedBean.class, null);
+ c.addContainerProperty("int", Integer.class, 0);
+ c.addContainerProperty("text", String.class, "");
+ c.addContainerProperty("html", String.class, "");
+ c.addContainerProperty("number", Number.class, null);
+ c.addContainerProperty("date", Date.class, null);
+ c.addContainerProperty("bean", TestBean.class, null);
+ c.addContainerProperty("button", String.class, null);
+ c.addContainerProperty("extendedBean", ExtendedBean.class, null);
Object id = c.addItem();
Item item = c.getItem(id);
- item.getItemProperty("foo").setValue(123);
- item.getItemProperty("bar").setValue("321");
- item.getItemProperty("baz").setValue(new TestBean());
- item.getItemProperty("bah").setValue(new ExtendedBean());
+ item.getItemProperty("int").setValue(123);
+ item.getItemProperty("text").setValue("321");
+ item.getItemProperty("html").setValue("<b>html</b>");
+ item.getItemProperty("number").setValue(3.14);
+ item.getItemProperty("date").setValue(new Date(123456789));
+ item.getItemProperty("bean").setValue(new TestBean());
+ item.getItemProperty("extendedBean").setValue(new ExtendedBean());
grid = new TestGrid(c);
- foo = grid.getColumn("foo");
- bar = grid.getColumn("bar");
- baz = grid.getColumn("baz");
- bah = grid.getColumn("bah");
+ intColumn = grid.getColumn("int");
+ textColumn = grid.getColumn("text");
+ htmlColumn = grid.getColumn("html");
+ numberColumn = grid.getColumn("number");
+ dateColumn = grid.getColumn("date");
+ beanColumn = grid.getColumn("bean");
+ extendedBeanColumn = grid.getColumn("extendedBean");
+ buttonColumn = grid.getColumn("button");
+
}
@Test
public void testDefaultRendererAndConverter() throws Exception {
- assertSame(TextRenderer.class, foo.getRenderer().getClass());
- assertSame(StringToIntegerConverter.class, foo.getConverter()
+ assertSame(TextRenderer.class, intColumn.getRenderer().getClass());
+ assertSame(StringToIntegerConverter.class, intColumn.getConverter()
.getClass());
- assertSame(TextRenderer.class, bar.getRenderer().getClass());
+ assertSame(TextRenderer.class, textColumn.getRenderer().getClass());
// String->String; converter not needed
- assertNull(bar.getConverter());
+ assertNull(textColumn.getConverter());
- assertSame(TextRenderer.class, baz.getRenderer().getClass());
+ assertSame(TextRenderer.class, beanColumn.getRenderer().getClass());
// MyBean->String; converter not found
- assertNull(baz.getConverter());
+ assertNull(beanColumn.getConverter());
}
@Test
public void testFindCompatibleConverter() throws Exception {
- foo.setRenderer(renderer());
- assertSame(StringToIntegerConverter.class, foo.getConverter()
+ intColumn.setRenderer(renderer());
+ assertSame(StringToIntegerConverter.class, intColumn.getConverter()
.getClass());
- bar.setRenderer(renderer());
- assertNull(bar.getConverter());
+ textColumn.setRenderer(renderer());
+ assertNull(textColumn.getConverter());
}
@Test(expected = IllegalArgumentException.class)
public void testCannotFindConverter() {
- baz.setRenderer(renderer());
+ beanColumn.setRenderer(renderer());
}
@Test
public void testExplicitConverter() throws Exception {
- baz.setRenderer(renderer(), converter());
- bah.setRenderer(renderer(), converter());
+ beanColumn.setRenderer(renderer(), converter());
+ extendedBeanColumn.setRenderer(renderer(), converter());
}
@Test
public void testEncoding() throws Exception {
- assertEquals("42", render(foo, 42).asString());
- foo.setRenderer(renderer());
- assertEquals("renderer(42)", render(foo, 42).asString());
+ assertEquals("42", render(intColumn, 42).asString());
+ intColumn.setRenderer(renderer());
+ assertEquals("renderer(42)", render(intColumn, 42).asString());
- assertEquals("2.72", render(bar, "2.72").asString());
- bar.setRenderer(new TestRenderer());
- assertEquals("renderer(2.72)", render(bar, "2.72").asString());
+ assertEquals("2.72", render(textColumn, "2.72").asString());
+ textColumn.setRenderer(new TestRenderer());
+ assertEquals("renderer(2.72)", render(textColumn, "2.72").asString());
}
@Test
public void testEncodingWithoutConverter() throws Exception {
- assertEquals("TestBean [42]", render(baz, new TestBean()).asString());
+ assertEquals("TestBean [42]", render(beanColumn, new TestBean())
+ .asString());
}
@Test
public void testBeanEncoding() throws Exception {
- baz.setRenderer(renderer(), converter());
- bah.setRenderer(renderer(), converter());
+ beanColumn.setRenderer(renderer(), converter());
+ extendedBeanColumn.setRenderer(renderer(), converter());
- assertEquals("renderer(TestBean(42))", render(baz, new TestBean())
- .asString());
+ assertEquals("renderer(TestBean(42))",
+ render(beanColumn, new TestBean()).asString());
assertEquals("renderer(ExtendedBean(42, 3.14))",
- render(baz, new ExtendedBean()).asString());
+ render(beanColumn, new ExtendedBean()).asString());
assertEquals("renderer(ExtendedBean(42, 3.14))",
- render(bah, new ExtendedBean()).asString());
+ render(extendedBeanColumn, new ExtendedBean()).asString());
+ }
+
+ @Test
+ public void testNullEncoding() {
+
+ textColumn.setRenderer(new TextRenderer());
+ htmlColumn.setRenderer(new HtmlRenderer());
+ numberColumn.setRenderer(new NumberRenderer());
+ dateColumn.setRenderer(new DateRenderer());
+ buttonColumn.setRenderer(new ButtonRenderer());
+
+ assertEquals("", textColumn.getRenderer().encode(null).asString());
+ assertEquals("", htmlColumn.getRenderer().encode(null).asString());
+ assertEquals("", numberColumn.getRenderer().encode(null).asString());
+ assertEquals("", dateColumn.getRenderer().encode(null).asString());
+ assertEquals("", buttonColumn.getRenderer().encode(null).asString());
+ }
+ @Test
+
+ public void testNullEncodingWithDefault() {
+
+ textColumn.setRenderer(new TextRenderer("default value"));
+ htmlColumn.setRenderer(new HtmlRenderer("default value"));
+ numberColumn.setRenderer(new NumberRenderer("%s", Locale.getDefault(), "default value"));
+ dateColumn.setRenderer(new DateRenderer("%s", "default value"));
+ buttonColumn.setRenderer(new ButtonRenderer("default value"));
+
+ assertEquals("default value", textColumn.getRenderer().encode(null).asString());
+ assertEquals("default value", htmlColumn.getRenderer().encode(null).asString());
+ assertEquals("default value", numberColumn.getRenderer().encode(null).asString());
+ assertEquals("default value", dateColumn.getRenderer().encode(null).asString());
+ assertEquals("default value", buttonColumn.getRenderer().encode(null).asString());
}
private TestConverter converter() {