import com.vaadin.data.util.converter.ConverterFactory;
import com.vaadin.data.util.converter.DefaultConverterFactory;
import com.vaadin.service.ApplicationContext;
+import com.vaadin.terminal.AbstractErrorMessage;
import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.CombinedRequest;
-import com.vaadin.terminal.ErrorMessage;
import com.vaadin.terminal.RequestHandler;
-import com.vaadin.terminal.SystemError;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.WrappedRequest;
// Shows the error in AbstractComponent
if (owner instanceof AbstractComponent) {
- if (t instanceof ErrorMessage) {
- ((AbstractComponent) owner).setComponentError((ErrorMessage) t);
- } else {
- ((AbstractComponent) owner)
- .setComponentError(new SystemError(t));
- }
+ ((AbstractComponent) owner).setComponentError(AbstractErrorMessage
+ .getErrorMessageForException(t));
}
// also print the error on console
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;
/**
this.message = message;
}
- protected String getMessage() {
+ public String getMessage() {
return message;
}
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
+ public String getFormattedHtmlMessage() {
+ String result = null;
switch (getMode()) {
case TEXT:
- target.addText(AbstractApplicationServlet
- .safeEscapeForHtml(getMessage()));
+ result = AbstractApplicationServlet.safeEscapeForHtml(getMessage());
break;
case PREFORMATTED:
- target.addText("<pre>"
+ result = "<pre>"
+ AbstractApplicationServlet
- .safeEscapeForHtml(getMessage()) + "</pre>");
+ .safeEscapeForHtml(getMessage()) + "</pre>";
break;
case XHTML:
- target.addText(getMessage());
+ result = getMessage();
break;
}
-
- if (getCauses().size() > 0) {
+ // if no message, combine the messages of all children
+ if (null == result && null != getCauses() && getCauses().size() > 0) {
+ StringBuilder sb = new StringBuilder();
for (ErrorMessage cause : getCauses()) {
- cause.paint(target);
+ String childMessage = cause.getFormattedHtmlMessage();
+ if (null != childMessage) {
+ sb.append("<div>");
+ sb.append(childMessage);
+ sb.append("</div>\n");
+ }
}
+ if (sb.length() > 0) {
+ result = sb.toString();
+ }
+ }
+ // still no message? use an empty string for backwards compatibility
+ if (null == result) {
+ result = "";
}
+ return result;
}
// TODO replace this with a helper method elsewhere?
public ErrorLevel getErrorLevel();
/**
- * <p>
- * Paints the error message into a UIDL stream. This method creates the UIDL
- * sequence describing it and outputs it to the given UIDL stream.
- * </p>
+ * Returns the HTML formatted message to show in as the error message on the
+ * client.
*
- * @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
+ * This method should perform any necessary escaping to avoid XSS attacks.
+ *
+ * TODO this API may still change to use a separate data transfer object
+ *
+ * @return HTML formatted string for the error message
+ * @since 7.0
*/
- @Deprecated
- public void paint(PaintTarget target) throws PaintException;
+ public String getFormattedHtmlMessage();
}
*/
private Set<String> registeredEventListeners = null;
+ // HTML formatted error message for the component
+ // TODO this could be an object with more information, but currently the UI
+ // only uses the message
+ private String errorMessage = null;
+
/**
* Returns the component height as set by the server.
*
if (registeredEventListeners.size() == 0) {
registeredEventListeners = null;
}
+ }
+ /**
+ * Returns the current error message for the component.
+ *
+ * @return HTML formatted error message to show for the component or null if
+ * none
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the current error message for the component.
+ *
+ * TODO this could use an object with more details about the error
+ *
+ * @param errorMessage
+ * HTML formatted error message to show for the component or null
+ * for none
+ */
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
}
}
private String title;
- private UIDL errorUidl;
+ private String errorMessageHtml;
public TooltipInfo() {
}
this.title = title;
}
- public UIDL getErrorUidl() {
- return errorUidl;
+ public String getErrorMessage() {
+ return errorMessageHtml;
}
- public void setErrorUidl(UIDL errorUidl) {
- this.errorUidl = errorUidl;
+ public void setErrorMessage(String errorMessage) {
+ errorMessageHtml = errorMessage;
}
}
return this.length - 2;
}-*/;
- /**
- * Shorthand that returns the component errors as UIDL. Only applicable for
- * Paintables.
- *
- * @return the error UIDL if available
- */
- public native UIDL getErrors()
- /*-{
- return this[1]['error'];
- }-*/;
-
native boolean isMapAttribute(String name)
/*-{
return typeof this[1][name] == "object";
private int maxWidth = -1;
- 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 = AbstractComponentConnector.ATTRIBUTE_REQUIRED;
- protected static final String ATTRIBUTE_ERROR = AbstractComponentConnector.ATTRIBUTE_ERROR;
protected static final String ATTRIBUTE_HIDEERRORS = AbstractComponentConnector.ATTRIBUTE_HIDEERRORS;
private enum InsertPosition {
boolean hasIcon = owner.getState().getIcon() != null;
boolean showRequired = uidl
.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_REQUIRED);
- boolean showError = uidl
- .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)
+ boolean showError = owner.getState().getErrorMessage() != null
&& !uidl.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_HIDEERRORS);
if (hasIcon) {
}
}
boolean hasIcon = iconURL != null;
- boolean showError = uidl
- .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)
- && !uidl.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_HIDEERRORS);
if (hasIcon) {
if (icon == null) {
// browsers when it is set to the empty string. If there is an
// icon, error indicator or required indicator they will ensure
// that space is reserved.
- if (!hasIcon && !showError) {
+ if (!hasIcon) {
captionText.setInnerHTML(" ");
}
} else {
captionText = null;
}
- if (showError) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createDiv();
- DOM.setInnerHTML(errorIndicatorElement, " ");
- DOM.setElementProperty(errorIndicatorElement, "className",
- "v-errorindicator");
-
- DOM.insertChild(getElement(), errorIndicatorElement,
- getInsertPosition(InsertPosition.ERROR));
- }
- } else if (errorIndicatorElement != null) {
- // Remove existing
- getElement().removeChild(errorIndicatorElement);
- errorIndicatorElement = null;
- }
-
return (wasPlacedAfterComponent != placedAfterComponent);
}
if (state.getIcon() != null) {
return true;
}
+ if (state.getErrorMessage() != null) {
+ return true;
+ }
} else {
// TODO fallback for cases where the caption has no owner (Tabsheet,
// Accordion)
return true;
}
}
- if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) {
- return true;
- }
if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_REQUIRED)) {
return true;
}
package com.vaadin.terminal.gwt.client;
-import java.util.Iterator;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.FlowPanel;
setStyleName(CLASSNAME);
}
- public void updateFromUIDL(UIDL uidl) {
+ public void updateMessage(String htmlErrorMessage) {
clear();
- if (uidl.getChildCount() == 0) {
+ if (htmlErrorMessage == null || htmlErrorMessage.length() == 0) {
add(new HTML(" "));
} else {
- for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) {
- final Object child = it.next();
- if (child instanceof String) {
- final String errorMessage = (String) child;
- add(new HTML(errorMessage));
- } else {
- try {
- final VErrorMessage childError = new VErrorMessage();
- childError.updateFromUIDL((UIDL) child);
- add(childError);
- } catch (Exception e) {
- // TODO XML type error, check if this can even happen
- // anymore??
- final UIDL.XML xml = (UIDL.XML) child;
- add(new HTML(xml.getXMLAsString()));
-
- }
- }
- }
+ // pre-formatted on the server as div per child
+ add(new HTML(htmlErrorMessage));
}
}
*/
private void show(TooltipInfo info) {
boolean hasContent = false;
- if (info.getErrorUidl() != null) {
+ if (info.getErrorMessage() != null) {
em.setVisible(true);
- em.updateFromUIDL(info.getErrorUidl());
+ em.updateMessage(info.getErrorMessage());
hasContent = true;
} else {
em.setVisible(false);
// Not all references to the string literals have been converted to use
// these!
public static final String ATTRIBUTE_REQUIRED = "required";
- public static final String ATTRIBUTE_ERROR = "error";
public static final String ATTRIBUTE_HIDEERRORS = "hideErrors";
private Widget widget;
tooltipInfo.setTitle(null);
}
// add error info to tooltip if present
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
- tooltipInfo.setErrorUidl(uidl.getErrors());
- } else {
- tooltipInfo.setErrorUidl(null);
- }
+ tooltipInfo.setErrorMessage(getState().getErrorMessage());
// Set captions
if (delegateCaptionHandling()) {
}
// add error classname to components w/ error
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ if (null != state.getErrorMessage()) {
styleBuf.append(" ");
styleBuf.append(primaryStyleName);
styleBuf.append(ApplicationConnection.ERROR_CLASSNAME_EXT);
getWidget().disableOnClick = getState().isDisableOnClick();
// handle error
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ if (null != getState().getErrorMessage()) {
if (getWidget().errorIndicatorElement == null) {
getWidget().errorIndicatorElement = DOM.createSpan();
getWidget().errorIndicatorElement
getWidget().blurHandlerRegistration = EventHelper.updateBlurHandler(
this, client, getWidget().blurHandlerRegistration);
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ if (null != getState().getErrorMessage()) {
if (getWidget().errorIndicatorElement == null) {
getWidget().errorIndicatorElement = DOM.createSpan();
getWidget().errorIndicatorElement.setInnerHTML(" ");
getWidget().removeStyleDependentName("nocaption");
}
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
- final UIDL errorUidl = uidl.getErrors();
- getWidget().errorMessage.updateFromUIDL(errorUidl);
+ if (null != getState().getErrorMessage()) {
+ getWidget().errorMessage.updateMessage(getState()
+ .getErrorMessage());
getWidget().errorMessage.setVisible(true);
} else {
getWidget().errorMessage.setVisible(false);
getWidget().captionElement.setInnerText(getState().getCaption());
// handle error
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ if (null != getState().getErrorMessage()) {
if (getWidget().errorIndicatorElement == null) {
getWidget().errorIndicatorElement = DOM.createDiv();
DOM.setElementProperty(getWidget().errorIndicatorElement,
getWidget().setText(getState().getCaption());
// handle error
- if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ if (null != getState().getErrorMessage()) {
if (getWidget().errorIndicatorElement == null) {
getWidget().errorIndicatorElement = DOM.createSpan();
getWidget().errorIndicatorElement
getWidget().setIconUri(null, client);
}
- getWidget().handleError(uidl);
+ getWidget().setErrorIndicatorVisible(
+ null != getState().getErrorMessage());
// We may have actions attached to this panel
if (uidl.getChildCount() > 0) {
public void updateFromUIDL(UIDL uidl, ComponentConnector component) {
owner = component;
- if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)
+ if (null != owner.getState().getErrorMessage()
&& !uidl.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_HIDEERRORS)) {
if (errorIndicatorElement == null) {
errorIndicatorElement = DOM.createDiv();
DOM.setInnerHTML(captionText, text);
}
- void handleError(UIDL uidl) {
- if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) {
+ void setErrorIndicatorVisible(boolean showError) {
+ if (showError) {
if (errorIndicatorElement == null) {
errorIndicatorElement = DOM.createSpan();
DOM.setElementProperty(errorIndicatorElement, "className",
@Override
public boolean updateCaption(UIDL uidl) {
- if (uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION)
- || uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) {
+ if (uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION)) {
TooltipInfo tooltipInfo = new TooltipInfo();
tooltipInfo
.setTitle(uidl
.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION));
- if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) {
- tooltipInfo.setErrorUidl(uidl.getErrors());
- }
+ // TODO currently, there is no error indicator and message for a tab
client.registerTooltip(getTabsheet(), getElement(), tooltipInfo);
} else {
client.registerTooltip(getTabsheet(), getElement(), null);
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;
private JsonTag tag;
- private int errorsOpen;
-
private boolean cacheEnabled = false;
private final Collection<Paintable> paintedComponents = new HashSet<Paintable>();
tag = new JsonTag(tagName);
- if (AbstractComponentConnector.ATTRIBUTE_ERROR.equals(tagName)) {
- errorsOpen++;
- }
-
customLayoutArgumentsOpen = false;
}
+ tagName + "' expected: '" + lastTag + "'.");
}
- // simple hack which writes error uidl structure into attribute
- if (AbstractComponentConnector.ATTRIBUTE_ERROR.equals(lastTag)) {
- if (errorsOpen == 1) {
- parent.addAttribute("\""
- + AbstractComponentConnector.ATTRIBUTE_ERROR
- + "\":[\""
- + AbstractComponentConnector.ATTRIBUTE_ERROR
- + "\",{}" + tag.getData() + "]");
- } else {
- // sub error
- parent.addData(tag.getJSON());
- }
- errorsOpen--;
- } else {
- parent.addData(tag.getJSON());
- }
+ parent.addData(tag.getJSON());
tag = parent;
} else {
// Paint the contents of the component
paintContent(target);
- final ErrorMessage error = getErrorMessage();
- if (error != null) {
- error.paint(target);
- }
}
target.endPaintable(this);
sharedState.setWidth("");
}
+ ErrorMessage error = getErrorMessage();
+ if (null != error) {
+ sharedState.setErrorMessage(error.getFormattedHtmlMessage());
+ }
+
return sharedState;
}
description);
}
- final ErrorMessage componentError = tab.getComponentError();
- if (componentError != null) {
- componentError.paint(target);
- }
-
final String styleName = tab.getStyleName();
if (styleName != null && styleName.length() != 0) {
target.addAttribute(VTabsheet.TAB_STYLE_NAME, styleName);
public void setComponentError(ErrorMessage componentError);
/**
- * Gets the curent error message shown for the tab.
+ * Gets the current error message shown for the tab.
*
- * @see AbstractComponent#setComponentError(ErrorMessage)
+ * TODO currently not sent to the client
*
- * @param error
- * message or null if none
+ * @see AbstractComponent#setComponentError(ErrorMessage)
*/
public ErrorMessage getComponentError();