All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cedarsolutions.client.gwt.validation.ValidationUtils Maven / Gradle / Ivy

There is a newer version: 5.8.4
Show newest version
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *              C E D A R
 *          S O L U T I O N S       "Software done right."
 *           S O F T W A R E
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Copyright (c) 2013 Kenneth J. Pronovici.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Apache License, Version 2.0.
 * See LICENSE for more information about the licensing terms.
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Author   : Kenneth J. Pronovici 
 * Language : Java 6
 * Project  : Common Java Functionality
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package com.cedarsolutions.client.gwt.validation;

import java.util.HashMap;
import java.util.Map;

import com.cedarsolutions.exception.InvalidDataException;
import com.cedarsolutions.shared.domain.LocalizableMessage;
import com.cedarsolutions.util.gwt.GwtStringUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.UIObject;

/**
 * Validation-related utilities.
 *
 * 

* Unlike a lot of other utility classes, which typically provide static * methods, this class is a singleton. *

* *

* It's difficult to mock static method calls, but I really want that option * for some of these methods. Normally, I would fall back on dependency * injection to solve this problem. However, it's not always possible to * inject an instance of this class into all of the places where it needs to be * used. Making the class a singleton works around that problem. *

* *

* For testing, the stubbed client test framework is wired into the * GWT.create() call within getInstance(). The framework "automagically" * generates a mocked version of this class for use by unit tests. However, * keep in mind that even the mock object is a singleton, so you must remember * to reset the mock between test cases. *

* * @author Kenneth J. Pronovici */ public class ValidationUtils { /** Message displayed as validation summary when nothing else can be found. */ public static final String INTERNAL_ERROR_MESSAGE = "Internal error: no details provided"; /** Empty validated field map, used if a view does not want to identify specific fields in validation. */ public static final Map NO_SPECIFIC_FIELDS = new HashMap(); /** Singleton instance. */ private static ValidationUtils INSTANCE; /** Default constructor is private so class cannot be instantiated. */ private ValidationUtils() { } /** Get an instance of this class to use. */ public static synchronized ValidationUtils getInstance() { if (INSTANCE == null) { INSTANCE = GWT.create(ValidationUtils.class); } return INSTANCE; } /** * Show a validation error on a view that supports it. * @param view View to operate on * @param error Validation error to show * @param style Name of the style applied to fields with errors */ public void showValidationError(IViewWithValidation view, InvalidDataException error, String style) { this.clearValidationErrors(view, style); if (error != null) { boolean hasValidationData = false; // If there's a summary, set it String summary = getSummary(view, error); if (!GwtStringUtils.isEmpty(summary)) { view.getValidationErrorWidget().setErrorSummary(summary); hasValidationData = true; } // The context will be used to decorate the field associated with // a given message. However, we will display every message, even // if we can't find the field associated with the message. That // way, we don't lose important information (like, "hey, the developer // forgot to provide a field to enter that required data"). if (error.getDetails() != null && error.getDetails().hasMessages()) { for (LocalizableMessage message : error.getDetails().getMessages()) { String translated = message.isTranslatable() ? view.translate(message) : message.getText(); if (!GwtStringUtils.isEmpty(translated)) { view.getValidationErrorWidget().addError(translated); this.decorateFieldWithValidationError(view, message, style); hasValidationData = true; } } } // If there's neither summary nor details, try to take the message from the // exception itself. If there isn't even a useful message on the exception, then // give up and show an internal error. The goal here is to make sure that // *something* legible is shown if an error is handled. Otherwise, it looks // like nothing happened, and the user won't notice the failure. if (!hasValidationData) { String message = null; if (error.getLocalizableMessage().isTranslatable()) { message = view.translate(error.getLocalizableMessage()); } else { message = error.getLocalizableMessage().getText(); } if (!GwtStringUtils.isEmpty(message)) { view.getValidationErrorWidget().setErrorSummary(message); } else { view.getValidationErrorWidget().setErrorSummary(INTERNAL_ERROR_MESSAGE); } } // Always show the widget view.getValidationErrorWidget().show(); } } /** * Clear error decorations from all fields and hide any validation errors. * @param view View to operate on * @param style Name of the style applied to fields with errors */ public void clearValidationErrors(IViewWithValidation view, String style) { view.getValidationErrorWidget().clearErrorList(); view.getValidationErrorWidget().clearErrorSummary(); view.getValidationErrorWidget().hide(); for (UIObject field : view.getValidatedFieldMap().values()) { field.removeStyleName(style); } } /** * Decorate a field that has a validation error. * @param view View to operate on * @param message Localizable message whose context identifies the field * @param style Name of the style applied to fields with errors * @return True if the field was found, false otherwise. */ public boolean decorateFieldWithValidationError(IViewWithValidation view, LocalizableMessage message, String style) { Map map = view.getValidatedFieldMap(); if (message.getContext() != null && map.containsKey(message.getContext())) { UIObject field = map.get(message.getContext()); field.addStyleName(style); return true; } else { return false; } } /** Safely get the summary for a validation error. */ private static String getSummary(IViewWithValidation view, InvalidDataException error) { if (error != null && error.getDetails() != null && error.getDetails().getSummary() != null) { if (error.getDetails().getSummary().isTranslatable()) { return view.translate(error.getDetails().getSummary()); } else { return error.getDetails().getSummary().getText(); } } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy