/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.utils.validation; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import nl.strohalm.cyclos.exceptions.ApplicationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Indicates data validation exception. it contains nested validation errors * @author luis */ public class ValidationException extends ApplicationException { private static final Log LOG = LogFactory.getLog(ValidationException.class); private static final long serialVersionUID = -234845842289514432L; private Map<String, String> keysByProperty = new LinkedHashMap<String, String>(); private Map<String, String> displayNameByProperty = new LinkedHashMap<String, String>(); private Map<String, Collection<ValidationError>> errorsByProperty = new LinkedHashMap<String, Collection<ValidationError>>(); private Collection<ValidationError> generalErrors = new LinkedHashSet<ValidationError>(); /** * This flag is used in the getMessage() method */ private boolean showDetailMessage = false; /** * Contains the validator's base name useful to qualify the errors. */ private String baseName; /** * Empty constructor */ public ValidationException() { } /** * Initializes with a general error with the given error key and arguments */ public ValidationException(final String key, final Object... args) { this(new ValidationError(key, args)); } /** * Initializes with a property error, with a mapped key */ public ValidationException(final String property, final String key, final ValidationError propertyError) { addPropertyError(property, propertyError); if (key != null) { setPropertyKey(property, key); } } /** * Initializes with a property error, with no key mapping */ public ValidationException(final String property, final ValidationError propertyError) { this(property, null, propertyError); } /** * Initializes with a general error */ public ValidationException(final ValidationError generalError) { addGeneralError(generalError); } /** * Add a general error */ public void addGeneralError(final ValidationError error) { generalErrors.add(error); } /** * Add a validation error for a given property */ public void addPropertyError(final String property, final ValidationError error) { Collection<ValidationError> propertyErrors = errorsByProperty.get(property); if (propertyErrors == null) { propertyErrors = new LinkedHashSet<ValidationError>(); errorsByProperty.put(property, propertyErrors); } propertyErrors.add(error); } public Map<String, String> getDisplayNameByProperty() { return displayNameByProperty; } public Map<String, Collection<ValidationError>> getErrorsByProperty() { return errorsByProperty; } public Collection<ValidationError> getGeneralErrors() { return generalErrors; } public Map<String, String> getKeysByProperty() { return keysByProperty; } @Override public String getMessage() { if (hasErrors() && showDetailMessage) { return getErrorMessage(); } else { return null; } } /** * Return the mapped display name for the given property */ public String getPropertyDisplayName(final String property) { return displayNameByProperty.get(property); } /** * Return the mapped key for the given property */ public String getPropertyKey(final String property) { return keysByProperty.get(property); } /** * Return if there are any errors */ public boolean hasErrors() { return !generalErrors.isEmpty() || !errorsByProperty.isEmpty(); } /** * Validators objects will set its base name to the exc * @param validatorBaseName */ public void setBaseName(final String baseName) { this.baseName = baseName; } public void setDisplayNameByProperty(final Map<String, String> displayNameByProperty) { this.displayNameByProperty = displayNameByProperty; } public void setErrorsByProperty(final Map<String, Collection<ValidationError>> errorsByProperty) { this.errorsByProperty = errorsByProperty; } public void setGeneralErrors(final Collection<ValidationError> generalErrors) { this.generalErrors = generalErrors; } public void setKeysByProperty(final Map<String, String> keysByProperty) { this.keysByProperty = keysByProperty; } /** * Set the display name for the given property */ public void setPropertyDisplayName(final String property, final String displayName) { displayNameByProperty.put(property, displayName); } /** * Set the ApplicationResources key for the given property */ public void setPropertyKey(final String property, final String key) { keysByProperty.put(property, key); } public void setShowDetailMessage(final boolean showDetailMessage) { this.showDetailMessage = showDetailMessage; } /** * Throw this exception if there are any validation errors * @throws ValidationException */ public void throwIfHasErrors() throws ValidationException { if (hasErrors()) { if (LOG.isDebugEnabled()) { final String error = getErrorMessage(); LOG.debug(error, this); } throw this; } } private String getErrorMessage() { final StringBuilder sb = new StringBuilder(); if (baseName != null) { sb.append(String.format("%n%n*** Validation Exception: %s ***%n", baseName)); } else { sb.append(String.format("%n%n*** Validation Exception ***%n")); } for (final ValidationError error : generalErrors) { sb.append(String.format("* General error: %s\n", error)); } for (final Map.Entry<String, Collection<ValidationError>> entry : errorsByProperty.entrySet()) { sb.append(String.format("* Property errors for [%s]:\n", entry.getKey())); for (final ValidationError error : entry.getValue()) { sb.append(String.format(" * %s\n", error)); } } sb.append("******\n\n"); return sb.toString(); } }