From e905f033ff2b2aa094b51eae72fef63e68bd1800 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Wed, 14 Mar 2012 12:32:21 +0200 Subject: [PATCH] Refactor error messages on server side (#8437). This is an intermediate step towards moving error messages from UIDL to shared state. --- src/com/vaadin/data/Buffered.java | 99 +--------- src/com/vaadin/data/Validator.java | 109 +---------- .../vaadin/terminal/AbstractErrorMessage.java | 172 ++++++++++++++++++ .../terminal/CompositeErrorMessage.java | 108 ++--------- src/com/vaadin/terminal/ErrorMessage.java | 38 ++-- src/com/vaadin/terminal/SystemError.java | 121 ++---------- src/com/vaadin/terminal/UserError.java | 129 +------------ .../vaadin/terminal/gwt/client/VCaption.java | 8 +- .../gwt/client/ui/ButtonConnector.java | 2 +- .../gwt/client/ui/CheckBoxConnector.java | 2 +- .../terminal/gwt/client/ui/FormConnector.java | 2 +- .../terminal/gwt/client/ui/LinkConnector.java | 2 +- .../gwt/client/ui/NativeButtonConnector.java | 2 +- .../terminal/gwt/client/ui/VFormLayout.java | 2 +- .../vaadin/terminal/gwt/client/ui/VPanel.java | 2 +- .../terminal/gwt/server/JsonPaintTarget.java | 12 +- src/com/vaadin/ui/AbstractField.java | 12 +- src/com/vaadin/ui/Form.java | 17 +- .../checkbox/CheckBoxNullValue.java | 7 +- .../tests/layouts/GridLayoutCaptions.java | 5 +- 20 files changed, 272 insertions(+), 579 deletions(-) create mode 100644 src/com/vaadin/terminal/AbstractErrorMessage.java diff --git a/src/com/vaadin/data/Buffered.java b/src/com/vaadin/data/Buffered.java index 552bd16d04..1387cb965b 100644 --- a/src/com/vaadin/data/Buffered.java +++ b/src/com/vaadin/data/Buffered.java @@ -5,16 +5,8 @@ package com.vaadin.data; import java.io.Serializable; -import java.util.Collections; -import java.util.List; import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.SystemError; -import com.vaadin.terminal.gwt.client.communication.SharedState; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; /** *

@@ -209,7 +201,7 @@ public interface Buffered extends Serializable { */ @SuppressWarnings("serial") public class SourceException extends RuntimeException implements - ErrorMessage, Serializable { + Serializable { /** Source class implementing the buffered interface */ private final Buffered source; @@ -256,11 +248,7 @@ public interface Buffered extends Serializable { /** * Gets the cause of the exception. * - * @return The cause for the exception. - * @throws MoreThanOneCauseException - * if there is more than one cause for the exception. This - * is possible if the commit operation triggers more than - * one error at the same time. + * @return The (first) cause for the exception, null if no cause. */ @Override public final Throwable getCause() { @@ -288,88 +276,5 @@ public interface Buffered extends Serializable { return source; } - /** - * Gets the error level of this buffered source exception. The level of - * the exception is maximum error level of all the contained causes. - *

- * The causes that do not specify error level default to - * ERROR level. Also source exception without any causes - * are of level ERROR. - *

- * - * @see com.vaadin.terminal.ErrorMessage#getErrorLevel() - */ - public ErrorLevel getErrorLevel() { - - ErrorLevel level = null; - - for (int i = 0; i < causes.length; i++) { - final ErrorLevel causeLevel = (causes[i] instanceof ErrorMessage) ? ((ErrorMessage) causes[i]) - .getErrorLevel() : ErrorLevel.ERROR; - if (level == null) { - level = causeLevel; - } else { - if (causeLevel.intValue() > level.intValue()) { - level = causeLevel; - } - } - } - - return level == null ? ErrorLevel.ERROR : level; - } - - /* Documented in super interface */ - public void paint(PaintTarget target) throws PaintException { - target.startTag("error"); - target.addAttribute("level", getErrorLevel().getText()); - - // Paint all the exceptions - for (int i = 0; i < causes.length; i++) { - if (causes[i] instanceof ErrorMessage) { - ((ErrorMessage) causes[i]).paint(target); - } else { - new SystemError(causes[i]).paint(target); - } - } - - target.endTag("error"); - - } - - public SharedState getState() { - // TODO implement: move relevant parts from paint() to getState() - return null; - } - - public List retrievePendingRpcCalls() { - return Collections.emptyList(); - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } - - public String getDebugId() { - // TODO Auto-generated method stub - return null; - } - - public void setDebugId(String id) { - throw new UnsupportedOperationException( - "Setting testing id for this Paintable is not implemented"); - } - } } diff --git a/src/com/vaadin/data/Validator.java b/src/com/vaadin/data/Validator.java index f07e957395..768a02babe 100644 --- a/src/com/vaadin/data/Validator.java +++ b/src/com/vaadin/data/Validator.java @@ -5,15 +5,8 @@ package com.vaadin.data; import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; /** * Interface that implements a method for validating if an {@link Object} is @@ -73,8 +66,7 @@ public interface Validator extends Serializable { * @since 3.0 */ @SuppressWarnings("serial") - public class InvalidValueException extends RuntimeException implements - ErrorMessage { + public class InvalidValueException extends RuntimeException { /** * Array of one or more validation errors that are causing this @@ -138,113 +130,16 @@ public interface Validator extends Serializable { return true; } - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.ErrorMessage#getErrorLevel() - */ - public final ErrorLevel getErrorLevel() { - return ErrorLevel.ERROR; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.Paintable#paint(com.vaadin.terminal.PaintTarget) - */ - public void paint(PaintTarget target) throws PaintException { - target.startTag("error"); - target.addAttribute("level", ErrorLevel.ERROR.getText()); - - // Error message - final String message = getHtmlMessage(); - if (message != null) { - target.addText(message); - } - - // Paint all the causes - for (int i = 0; i < causes.length; i++) { - causes[i].paint(target); - } - - target.endTag("error"); - } - - public SharedState getState() { - // TODO implement: move relevant parts from paint() to getState() - return null; - } - - public List retrievePendingRpcCalls() { - return Collections.emptyList(); - } - /** * Returns the message of the error in HTML. * * Note that this API may change in future versions. */ - protected String getHtmlMessage() { + public String getHtmlMessage() { return AbstractApplicationServlet .safeEscapeForHtml(getLocalizedMessage()); } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.ErrorMessage#addListener(com.vaadin.terminal. - * Paintable.RepaintRequestListener) - */ - public void addListener(RepaintRequestListener listener) { - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.ErrorMessage#removeListener(com.vaadin.terminal - * .Paintable.RepaintRequestListener) - */ - public void removeListener(RepaintRequestListener listener) { - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.ErrorMessage#requestRepaint() - */ - public void requestRepaint() { - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Paintable#requestRepaintRequests() - */ - public void requestRepaintRequests() { - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Paintable#getDebugId() - */ - public String getDebugId() { - return null; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Paintable#setDebugId(java.lang.String) - */ - public void setDebugId(String id) { - throw new UnsupportedOperationException( - "InvalidValueException cannot have a debug id"); - } - /** * Returns the {@code InvalidValueExceptions} that caused this * exception. diff --git a/src/com/vaadin/terminal/AbstractErrorMessage.java b/src/com/vaadin/terminal/AbstractErrorMessage.java new file mode 100644 index 0000000000..ce0238dde5 --- /dev/null +++ b/src/com/vaadin/terminal/AbstractErrorMessage.java @@ -0,0 +1,172 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.data.Buffered; +import com.vaadin.data.Validator; +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; +import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; + +/** + * Base class for component error messages. + * + * This class is used on the server side to construct the error messages to send + * to the client. + * + * @since 7.0 + */ +public abstract class AbstractErrorMessage implements ErrorMessage { + + public enum ContentMode { + /** + * Content mode, where the error contains only plain text. + */ + TEXT, + /** + * Content mode, where the error contains preformatted text. + */ + PREFORMATTED, + /** + * Content mode, where the error contains XHTML. + */ + XHTML; + } + + /** + * Content mode. + */ + private ContentMode mode = ContentMode.TEXT; + + /** + * Message in content mode. + */ + private String message; + + /** + * Error level. + */ + private ErrorLevel level = ErrorLevel.ERROR; + + private List causes = new ArrayList(); + + protected AbstractErrorMessage(String message) { + this.message = message; + } + + protected String getMessage() { + return message; + } + + protected void setMessage(String message) { + this.message = message; + } + + /* Documented in interface */ + public ErrorLevel getErrorLevel() { + return level; + } + + protected void setErrorLevel(ErrorLevel level) { + this.level = level; + } + + protected ContentMode getMode() { + return mode; + } + + protected void setMode(ContentMode mode) { + this.mode = mode; + } + + protected List getCauses() { + return causes; + } + + protected void addCause(ErrorMessage cause) { + causes.add(cause); + } + + @Deprecated + public void paint(PaintTarget target) throws PaintException { + + // TODO if no message and only one cause, paint cause only? error level? + + target.startTag(AbstractComponentConnector.ATTRIBUTE_ERROR); + target.addAttribute("level", level.getText()); + + paintContent(target); + + target.endTag(AbstractComponentConnector.ATTRIBUTE_ERROR); + } + + // TODO temporary method - move logic to client side + @Deprecated + protected void paintContent(PaintTarget target) throws PaintException { + // Paint the message + switch (getMode()) { + case TEXT: + target.addText(AbstractApplicationServlet + .safeEscapeForHtml(getMessage())); + break; + case PREFORMATTED: + target.addText("
"
+                    + AbstractApplicationServlet
+                            .safeEscapeForHtml(getMessage()) + "
"); + break; + case XHTML: + target.addText(getMessage()); + break; + } + + if (getCauses().size() > 0) { + for (ErrorMessage cause : getCauses()) { + cause.paint(target); + } + } + } + + // TODO replace this with a helper method elsewhere? + public static ErrorMessage getErrorMessageForException(Throwable t) { + if (null == t) { + return null; + } else if (t instanceof ErrorMessage) { + // legacy case for custom error messages + return (ErrorMessage) t; + } else if (t instanceof Validator.InvalidValueException) { + UserError error = new UserError( + ((Validator.InvalidValueException) t).getHtmlMessage(), + ContentMode.XHTML, ErrorLevel.ERROR); + for (Validator.InvalidValueException nestedException : ((Validator.InvalidValueException) t) + .getCauses()) { + error.addCause(getErrorMessageForException(nestedException)); + } + return error; + } else if (t instanceof Buffered.SourceException) { + // no message, only the causes to be painted + UserError error = new UserError(null); + // in practice, this was always ERROR in Vaadin 6 unless tweaked in + // custom exceptions implementing ErrorMessage + error.setErrorLevel(ErrorLevel.ERROR); + // causes + for (Throwable nestedException : ((Buffered.SourceException) t) + .getCauses()) { + error.addCause(getErrorMessageForException(nestedException)); + } + return error; + } else { + return new SystemError(t); + } + } + + /* Documented in superclass */ + @Override + public String toString() { + return getMessage(); + } + +} diff --git a/src/com/vaadin/terminal/CompositeErrorMessage.java b/src/com/vaadin/terminal/CompositeErrorMessage.java index efe29196d8..b82b622f54 100644 --- a/src/com/vaadin/terminal/CompositeErrorMessage.java +++ b/src/com/vaadin/terminal/CompositeErrorMessage.java @@ -4,15 +4,8 @@ package com.vaadin.terminal; -import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; -import java.util.List; - -import com.vaadin.terminal.gwt.client.communication.SharedState; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; /** * Class for combining multiple error messages together. @@ -23,17 +16,7 @@ import com.vaadin.terminal.gwt.server.ClientMethodInvocation; * @since 3.0 */ @SuppressWarnings("serial") -public class CompositeErrorMessage implements ErrorMessage, Serializable { - - /** - * Array of all the errors. - */ - private final List errors; - - /** - * Level of the error. - */ - private ErrorLevel level; +public class CompositeErrorMessage extends AbstractErrorMessage { /** * Constructor for CompositeErrorMessage. @@ -43,14 +26,14 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { * ignored, but at least one message is required. */ public CompositeErrorMessage(ErrorMessage[] errorMessages) { - errors = new ArrayList(errorMessages.length); - level = ErrorLevel.INFORMATION; + super(null); + setErrorLevel(ErrorLevel.INFORMATION); for (int i = 0; i < errorMessages.length; i++) { addErrorMessage(errorMessages[i]); } - if (errors.size() == 0) { + if (getCauses().size() == 0) { throw new IllegalArgumentException( "Composite error message must have at least one error"); } @@ -66,29 +49,20 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { */ public CompositeErrorMessage( Collection errorMessages) { - errors = new ArrayList(errorMessages.size()); - level = ErrorLevel.INFORMATION; + super(null); + setErrorLevel(ErrorLevel.INFORMATION); for (final Iterator i = errorMessages .iterator(); i.hasNext();) { addErrorMessage(i.next()); } - if (errors.size() == 0) { + if (getCauses().size() == 0) { throw new IllegalArgumentException( "Composite error message must have at least one error"); } } - /** - * The error level is the largest error level in - * - * @see com.vaadin.terminal.ErrorMessage#getErrorLevel() - */ - public final ErrorLevel getErrorLevel() { - return level; - } - /** * Adds a error message into this composite message. Updates the level * field. @@ -97,10 +71,10 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { * the error message to be added. Duplicate errors are ignored. */ private void addErrorMessage(ErrorMessage error) { - if (error != null && !errors.contains(error)) { - errors.add(error); - if (error.getErrorLevel().intValue() > level.intValue()) { - level = error.getErrorLevel(); + if (error != null && !getCauses().contains(error)) { + addCause(error); + if (error.getErrorLevel().intValue() > getErrorLevel().intValue()) { + setErrorLevel(error.getErrorLevel()); } } } @@ -111,53 +85,7 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { * @return the error iterator. */ public Iterator iterator() { - return errors.iterator(); - } - - /** - * @see com.vaadin.terminal.Paintable#paint(com.vaadin.terminal.PaintTarget) - */ - public void paint(PaintTarget target) throws PaintException { - - if (errors.size() == 1) { - (errors.iterator().next()).paint(target); - } else { - target.startTag("error"); - target.addAttribute("level", level.getText()); - - // Paint all the exceptions - for (final Iterator i = errors.iterator(); i - .hasNext();) { - i.next().paint(target); - } - - target.endTag("error"); - } - } - - public SharedState getState() { - // TODO implement: move relevant parts from paint() to getState() - return null; - } - - public List retrievePendingRpcCalls() { - return Collections.emptyList(); - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { + return getCauses().iterator(); } /** @@ -169,7 +97,8 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { public String toString() { String retval = "["; int pos = 0; - for (final Iterator i = errors.iterator(); i.hasNext();) { + for (final Iterator i = getCauses().iterator(); i + .hasNext();) { if (pos > 0) { retval += ","; } @@ -180,13 +109,4 @@ public class CompositeErrorMessage implements ErrorMessage, Serializable { return retval; } - - public String getDebugId() { - return null; - } - - public void setDebugId(String id) { - throw new UnsupportedOperationException( - "Setting testing id for this Paintable is not implemented"); - } } diff --git a/src/com/vaadin/terminal/ErrorMessage.java b/src/com/vaadin/terminal/ErrorMessage.java index 5e55bfbcf6..d0e8173883 100644 --- a/src/com/vaadin/terminal/ErrorMessage.java +++ b/src/com/vaadin/terminal/ErrorMessage.java @@ -15,7 +15,7 @@ import java.io.Serializable; * @VERSION@ * @since 3.0 */ -public interface ErrorMessage extends Paintable, Serializable { +public interface ErrorMessage extends Serializable { public enum ErrorLevel { /** @@ -111,31 +111,19 @@ public interface ErrorMessage extends Paintable, Serializable { public ErrorLevel getErrorLevel(); /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. + *

+ * Paints the error message into a UIDL stream. This method creates the UIDL + * sequence describing it and outputs it to the given UIDL stream. + *

* - * @param listener - * the listener to be added. - * @see com.vaadin.terminal.Paintable#addListener(Paintable.RepaintRequestListener) + * @param target + * the target UIDL stream where the error should paint itself to. + * @throws PaintException + * if the paint operation failed. + * @deprecated error messages should not be painted to UIDL but sent + * differently */ - public void addListener(RepaintRequestListener listener); - - /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. - * - * @param listener - * the listener to be removed. - * @see com.vaadin.terminal.Paintable#removeListener(Paintable.RepaintRequestListener) - */ - public void removeListener(RepaintRequestListener listener); - - /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. - * - * @see com.vaadin.terminal.Paintable#requestRepaint() - */ - public void requestRepaint(); + @Deprecated + public void paint(PaintTarget target) throws PaintException; } diff --git a/src/com/vaadin/terminal/SystemError.java b/src/com/vaadin/terminal/SystemError.java index 462450422b..bae135ee6b 100644 --- a/src/com/vaadin/terminal/SystemError.java +++ b/src/com/vaadin/terminal/SystemError.java @@ -4,20 +4,12 @@ package com.vaadin.terminal; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Collections; -import java.util.List; - -import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; /** - * SystemError is a runtime exception caused by error in system. - * The system error can be shown to the user as it implements - * ErrorMessage interface, but contains technical information such - * as stack trace and exception. + * SystemError is an error message for a problem caused by error in + * system, not the user application code. The system error can contain technical + * information such as stack trace and exception. * * SystemError does not support HTML in error messages or stack traces. If HTML * messages are required, use {@link UserError} or a custom implementation of @@ -29,13 +21,7 @@ import com.vaadin.terminal.gwt.server.ClientMethodInvocation; * @since 3.0 */ @SuppressWarnings("serial") -public class SystemError extends RuntimeException implements ErrorMessage { - - /** - * The cause of the system error. The cause is stored separately as JDK 1.3 - * does not support causes natively. - */ - private Throwable cause = null; +public class SystemError extends AbstractErrorMessage { /** * Constructor for SystemError with error message specified. @@ -45,6 +31,9 @@ public class SystemError extends RuntimeException implements ErrorMessage { */ public SystemError(String message) { super(message); + setErrorLevel(ErrorLevel.SYSTEMERROR); + setMode(ContentMode.XHTML); + setMessage(getHtmlMessage()); } /** @@ -56,8 +45,8 @@ public class SystemError extends RuntimeException implements ErrorMessage { * the throwable causing the system error. */ public SystemError(String message, Throwable cause) { - super(message); - this.cause = cause; + this(message); + addCause(AbstractErrorMessage.getErrorMessageForException(cause)); } /** @@ -67,40 +56,7 @@ public class SystemError extends RuntimeException implements ErrorMessage { * the throwable causing the system error. */ public SystemError(Throwable cause) { - this.cause = cause; - } - - /** - * @see com.vaadin.terminal.ErrorMessage#getErrorLevel() - */ - public final ErrorLevel getErrorLevel() { - return ErrorLevel.SYSTEMERROR; - } - - /** - * @see com.vaadin.terminal.Paintable#paint(com.vaadin.terminal.PaintTarget) - */ - public void paint(PaintTarget target) throws PaintException { - - target.startTag("error"); - target.addAttribute("level", ErrorLevel.SYSTEMERROR.getText()); - - String message = getHtmlMessage(); - - target.addXMLSection("div", message, - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); - - target.endTag("error"); - - } - - public SharedState getState() { - // TODO implement: move relevant parts from paint() to getState() - return null; - } - - public List retrievePendingRpcCalls() { - return Collections.emptyList(); + this(null, cause); } /** @@ -109,61 +65,18 @@ public class SystemError extends RuntimeException implements ErrorMessage { * Note that this API may change in future versions. */ protected String getHtmlMessage() { + // TODO wrapping div with namespace? See the old code: + // target.addXMLSection("div", message, + // "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); + StringBuilder sb = new StringBuilder(); - final String message = getLocalizedMessage(); - if (message != null) { + if (getMessage() != null) { sb.append("

"); - sb.append(AbstractApplicationServlet.safeEscapeForHtml(message)); + sb.append(AbstractApplicationServlet + .safeEscapeForHtml(getMessage())); sb.append("

"); } - - // Paint the exception - if (cause != null) { - sb.append("

Exception

"); - final StringWriter buffer = new StringWriter(); - cause.printStackTrace(new PrintWriter(buffer)); - sb.append("
");
-            sb.append(AbstractApplicationServlet.safeEscapeForHtml(buffer
-                    .toString()));
-            sb.append("
"); - } return sb.toString(); } - /** - * Gets cause for the error. - * - * @return the cause. - * @see java.lang.Throwable#getCause() - */ - @Override - public Throwable getCause() { - return cause; - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } - - public String getDebugId() { - return null; - } - - public void setDebugId(String id) { - throw new UnsupportedOperationException( - "Setting testing id for this Paintable is not implemented"); - } - } diff --git a/src/com/vaadin/terminal/UserError.java b/src/com/vaadin/terminal/UserError.java index 15473e47e1..baaf331fa0 100644 --- a/src/com/vaadin/terminal/UserError.java +++ b/src/com/vaadin/terminal/UserError.java @@ -4,13 +4,6 @@ package com.vaadin.terminal; -import java.util.Collections; -import java.util.List; - -import com.vaadin.terminal.gwt.client.communication.SharedState; -import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; - /** * UserError is a controlled error occurred in application. User * errors are occur in normal usage of the application and guide the user. @@ -21,27 +14,7 @@ import com.vaadin.terminal.gwt.server.ClientMethodInvocation; * @since 3.0 */ @SuppressWarnings("serial") -public class UserError implements ErrorMessage { - - public enum ContentMode { - /** - * Content mode, where the error contains only plain text. - */ - TEXT, - /** - * Content mode, where the error contains preformatted text. - */ - PREFORMATTED, - /** - * Formatted content mode, where the contents is XML restricted to the - * UIDL 1.0 formatting markups. - */ - UIDL, - /** - * Content mode, where the error contains XHTML. - */ - XHTML; - } +public class UserError extends AbstractErrorMessage { /** * @deprecated from 7.0, use {@link ContentMode#TEXT} instead     @@ -55,33 +28,12 @@ public class UserError implements ErrorMessage { @Deprecated public static final ContentMode CONTENT_PREFORMATTED = ContentMode.PREFORMATTED; - /** - * @deprecated from 7.0, use {@link ContentMode#UIDL} instead     - */ - @Deprecated - public static final ContentMode CONTENT_UIDL = ContentMode.UIDL; - /** * @deprecated from 7.0, use {@link ContentMode#XHTML} instead     */ @Deprecated public static final ContentMode CONTENT_XHTML = ContentMode.XHTML; - /** - * Content mode. - */ - private ContentMode mode = ContentMode.TEXT; - - /** - * Message in content mode. - */ - private final String msg; - - /** - * Error level. - */ - private ErrorLevel level = ErrorLevel.ERROR; - /** * Creates a textual error message of level ERROR. * @@ -89,91 +41,20 @@ public class UserError implements ErrorMessage { * the text of the error message. */ public UserError(String textErrorMessage) { - msg = textErrorMessage; + super(textErrorMessage); } public UserError(String message, ContentMode contentMode, ErrorLevel errorLevel) { + super(message); if (contentMode == null) { contentMode = ContentMode.TEXT; } if (errorLevel == null) { errorLevel = ErrorLevel.ERROR; } - msg = message; - mode = contentMode; - level = errorLevel; - } - - /* Documented in interface */ - public ErrorLevel getErrorLevel() { - return level; - } - - /* Documented in interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in interface */ - public void requestRepaint() { - } - - /* Documented in interface */ - public void paint(PaintTarget target) throws PaintException { - - target.startTag("error"); - target.addAttribute("level", level.getText()); - - // Paint the message - switch (mode) { - case TEXT: - target.addText(AbstractApplicationServlet.safeEscapeForHtml(msg)); - break; - case UIDL: - target.addUIDL(msg); - break; - case PREFORMATTED: - target.addText("
"
-                    + AbstractApplicationServlet.safeEscapeForHtml(msg)
-                    + "
"); - break; - case XHTML: - target.addText(msg); - break; - } - target.endTag("error"); - } - - public SharedState getState() { - // TODO implement: move relevant parts from paint() to getState() - return null; - } - - public List retrievePendingRpcCalls() { - return Collections.emptyList(); - } - - /* Documented in interface */ - public void requestRepaintRequests() { - } - - /* Documented in superclass */ - @Override - public String toString() { - return msg; - } - - public String getDebugId() { - return null; - } - - public void setDebugId(String id) { - throw new UnsupportedOperationException( - "Setting testing id for this Paintable is not implemented"); + setMode(contentMode); + setErrorLevel(errorLevel); } } diff --git a/src/com/vaadin/terminal/gwt/client/VCaption.java b/src/com/vaadin/terminal/gwt/client/VCaption.java index 900c8b0680..40ade41998 100644 --- a/src/com/vaadin/terminal/gwt/client/VCaption.java +++ b/src/com/vaadin/terminal/gwt/client/VCaption.java @@ -32,12 +32,12 @@ public class VCaption extends HTML { private int maxWidth = -1; - protected static final String ATTRIBUTE_ICON = "icon"; + protected static final String ATTRIBUTE_ICON = AbstractComponentConnector.ATTRIBUTE_ICON; protected static final String ATTRIBUTE_CAPTION = "caption"; protected static final String ATTRIBUTE_DESCRIPTION = "description"; - protected static final String ATTRIBUTE_REQUIRED = "required"; - protected static final String ATTRIBUTE_ERROR = "error"; - protected static final String ATTRIBUTE_HIDEERRORS = "hideErrors"; + protected static final String ATTRIBUTE_REQUIRED = AbstractComponentConnector.ATTRIBUTE_REQUIRED; + protected static final String ATTRIBUTE_ERROR = AbstractComponentConnector.ATTRIBUTE_ERROR; + protected static final String ATTRIBUTE_HIDEERRORS = AbstractComponentConnector.ATTRIBUTE_HIDEERRORS; private enum InsertPosition { ICON, CAPTION, REQUIRED, ERROR diff --git a/src/com/vaadin/terminal/gwt/client/ui/ButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/ButtonConnector.java index 903047171a..61807acbbf 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/ButtonConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/ButtonConnector.java @@ -74,7 +74,7 @@ public class ButtonConnector extends AbstractComponentConnector { getWidget().disableOnClick = getState().isDisableOnClick(); // handle error - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { if (getWidget().errorIndicatorElement == null) { getWidget().errorIndicatorElement = DOM.createSpan(); getWidget().errorIndicatorElement diff --git a/src/com/vaadin/terminal/gwt/client/ui/CheckBoxConnector.java b/src/com/vaadin/terminal/gwt/client/ui/CheckBoxConnector.java index d842104fab..751afa67e1 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/CheckBoxConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/CheckBoxConnector.java @@ -36,7 +36,7 @@ public class CheckBoxConnector extends AbstractFieldConnector { getWidget().blurHandlerRegistration = EventHelper.updateBlurHandler( this, client, getWidget().blurHandlerRegistration); - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { if (getWidget().errorIndicatorElement == null) { getWidget().errorIndicatorElement = DOM.createSpan(); getWidget().errorIndicatorElement.setInnerHTML(" "); diff --git a/src/com/vaadin/terminal/gwt/client/ui/FormConnector.java b/src/com/vaadin/terminal/gwt/client/ui/FormConnector.java index ff3950f37d..a5b46b7190 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/FormConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/FormConnector.java @@ -64,7 +64,7 @@ public class FormConnector extends AbstractComponentContainerConnector getWidget().removeStyleDependentName("nocaption"); } - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { final UIDL errorUidl = uidl.getErrors(); getWidget().errorMessage.updateFromUIDL(errorUidl); getWidget().errorMessage.setVisible(true); diff --git a/src/com/vaadin/terminal/gwt/client/ui/LinkConnector.java b/src/com/vaadin/terminal/gwt/client/ui/LinkConnector.java index 21172becff..28af9f6e52 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/LinkConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/LinkConnector.java @@ -60,7 +60,7 @@ public class LinkConnector extends AbstractComponentConnector { getWidget().captionElement.setInnerText(getState().getCaption()); // handle error - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { if (getWidget().errorIndicatorElement == null) { getWidget().errorIndicatorElement = DOM.createDiv(); DOM.setElementProperty(getWidget().errorIndicatorElement, diff --git a/src/com/vaadin/terminal/gwt/client/ui/NativeButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/NativeButtonConnector.java index 135fb4f676..834e08bf48 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/NativeButtonConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/NativeButtonConnector.java @@ -51,7 +51,7 @@ public class NativeButtonConnector extends AbstractComponentConnector { getWidget().setText(getState().getCaption()); // handle error - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { if (getWidget().errorIndicatorElement == null) { getWidget().errorIndicatorElement = DOM.createSpan(); getWidget().errorIndicatorElement diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java index 26ddb84920..17f6f4785c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java @@ -351,7 +351,7 @@ public class VFormLayout extends SimplePanel { public void updateFromUIDL(UIDL uidl, ComponentConnector component) { owner = component; - if (uidl.hasAttribute("error") + if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR) && !uidl.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_HIDEERRORS)) { if (errorIndicatorElement == null) { errorIndicatorElement = DOM.createDiv(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java index b9552493de..712799be2a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -115,7 +115,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, } void handleError(UIDL uidl) { - if (uidl.hasAttribute("error")) { + if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) { if (errorIndicatorElement == null) { errorIndicatorElement = DOM.createSpan(); DOM.setElementProperty(errorIndicatorElement, "className", diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java index 2807cde33d..ffec6da3c5 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java +++ b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java @@ -34,6 +34,7 @@ import com.vaadin.terminal.StreamVariable; import com.vaadin.terminal.ThemeResource; import com.vaadin.terminal.VariableOwner; import com.vaadin.terminal.gwt.client.Connector; +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.ui.Alignment; import com.vaadin.ui.ClientWidget; import com.vaadin.ui.CustomLayout; @@ -161,7 +162,7 @@ public class JsonPaintTarget implements PaintTarget { tag = new JsonTag(tagName); - if ("error".equals(tagName)) { + if (AbstractComponentConnector.ATTRIBUTE_ERROR.equals(tagName)) { errorsOpen++; } @@ -204,10 +205,13 @@ public class JsonPaintTarget implements PaintTarget { } // simple hack which writes error uidl structure into attribute - if ("error".equals(lastTag)) { + if (AbstractComponentConnector.ATTRIBUTE_ERROR.equals(lastTag)) { if (errorsOpen == 1) { - parent.addAttribute("\"error\":[\"error\",{}" - + tag.getData() + "]"); + parent.addAttribute("\"" + + AbstractComponentConnector.ATTRIBUTE_ERROR + + "\":[\"" + + AbstractComponentConnector.ATTRIBUTE_ERROR + + "\",{}" + tag.getData() + "]"); } else { // sub error parent.addData(tag.getJSON()); diff --git a/src/com/vaadin/ui/AbstractField.java b/src/com/vaadin/ui/AbstractField.java index 82d3d2af19..742d39d835 100644 --- a/src/com/vaadin/ui/AbstractField.java +++ b/src/com/vaadin/ui/AbstractField.java @@ -26,6 +26,7 @@ import com.vaadin.data.util.converter.ConverterFactory; import com.vaadin.event.Action; import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutListener; +import com.vaadin.terminal.AbstractErrorMessage; import com.vaadin.terminal.CompositeErrorMessage; import com.vaadin.terminal.ErrorMessage; import com.vaadin.terminal.PaintException; @@ -1125,7 +1126,7 @@ public abstract class AbstractField extends AbstractComponent implements * the requiredError string. For these fields the exclamation mark will * be hidden but the error must still be sent to the client. */ - ErrorMessage validationError = null; + Validator.InvalidValueException validationError = null; if (isValidationVisible()) { try { validate(); @@ -1146,8 +1147,13 @@ public abstract class AbstractField extends AbstractComponent implements } // Throw combination of the error types - return new CompositeErrorMessage(new ErrorMessage[] { superError, - validationError, getCurrentBufferedSourceException() }); + return new CompositeErrorMessage( + new ErrorMessage[] { + superError, + AbstractErrorMessage + .getErrorMessageForException(validationError), + AbstractErrorMessage + .getErrorMessageForException(getCurrentBufferedSourceException()) }); } diff --git a/src/com/vaadin/ui/Form.java b/src/com/vaadin/ui/Form.java index 1abfefbc58..a66c8e723b 100644 --- a/src/com/vaadin/ui/Form.java +++ b/src/com/vaadin/ui/Form.java @@ -24,10 +24,12 @@ import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.Action.ShortcutNotifier; import com.vaadin.event.ActionManager; +import com.vaadin.terminal.AbstractErrorMessage; import com.vaadin.terminal.CompositeErrorMessage; import com.vaadin.terminal.ErrorMessage; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; +import com.vaadin.terminal.UserError; import com.vaadin.terminal.gwt.client.ui.FormConnector; /** @@ -242,15 +244,13 @@ public class Form extends AbstractField implements Item.Editor, if (validationError != null) { // Show caption as error for fields with empty errors if ("".equals(validationError.toString())) { - validationError = new Validator.InvalidValueException( - field.getCaption()); + validationError = new UserError(field.getCaption()); } break; } else if (f instanceof Field && !((Field) f).isValid()) { // Something is wrong with the field, but no proper // error is given. Generate one. - validationError = new Validator.InvalidValueException( - field.getCaption()); + validationError = new UserError(field.getCaption()); break; } } @@ -264,9 +264,12 @@ public class Form extends AbstractField implements Item.Editor, } // Throw combination of the error types - return new CompositeErrorMessage(new ErrorMessage[] { - getComponentError(), validationError, - currentBufferedSourceException }); + return new CompositeErrorMessage( + new ErrorMessage[] { + getComponentError(), + validationError, + AbstractErrorMessage + .getErrorMessageForException(currentBufferedSourceException) }); } /** diff --git a/tests/testbench/com/vaadin/tests/components/checkbox/CheckBoxNullValue.java b/tests/testbench/com/vaadin/tests/components/checkbox/CheckBoxNullValue.java index a961b48426..2c981432c8 100644 --- a/tests/testbench/com/vaadin/tests/components/checkbox/CheckBoxNullValue.java +++ b/tests/testbench/com/vaadin/tests/components/checkbox/CheckBoxNullValue.java @@ -1,6 +1,7 @@ package com.vaadin.tests.components.checkbox; import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.terminal.AbstractErrorMessage; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -34,12 +35,14 @@ public class CheckBoxNullValue extends TestBase { try { checkbox.validate(); } catch (InvalidValueException e) { - checkbox.setComponentError(e); + checkbox.setComponentError(AbstractErrorMessage + .getErrorMessageForException(e)); } try { requiredCheckbox.validate(); } catch (InvalidValueException e) { - requiredCheckbox.setComponentError(e); + requiredCheckbox.setComponentError(AbstractErrorMessage + .getErrorMessageForException(e)); } valueLabel.setValue("Checkbox: " + checkbox.getValue() + "; Required checkbox: " + requiredCheckbox.getValue()); diff --git a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java index 987152f529..1fe33d62ca 100644 --- a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java +++ b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java @@ -3,6 +3,7 @@ package com.vaadin.tests.layouts; import com.vaadin.data.Item; import com.vaadin.data.Validator; import com.vaadin.data.util.BeanItem; +import com.vaadin.terminal.AbstractErrorMessage; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -95,7 +96,9 @@ public class GridLayoutCaptions extends TestBase { "Ipsum lipsum laarum lop... "); for (Object propIDs : getItemDataSource().getItemPropertyIds()) { - ((TextField) getField(propIDs)).setComponentError(ive); + ((TextField) getField(propIDs)) + .setComponentError(AbstractErrorMessage + .getErrorMessageForException(ive)); } -- 2.39.5