Java tutorial
/* * Copyright (c) 2003-2014 JGoodies Software GmbH. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of JGoodies Software GmbH nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jgoodies.validation.message; import static com.jgoodies.common.base.Preconditions.checkNotNull; import com.jgoodies.common.base.Objects; import com.jgoodies.validation.Severity; import com.jgoodies.validation.ValidationMessage; /** * An implementation of {@link ValidationMessage} that holds a text message, * the validated object (target), a descriptions of the validated property, * and a description of the role this object takes in the validation context. * The target can be used to identify the source of a validation message. * The role and property together build the <em>aspect</em> that is used * as association key; in other words, it can be used to determine whether * a view is associated with a given message or not.<p> * * <strong>Example:</strong> We validate an invoice that has a shipping address * and a physical address. We want to report that the zip code of the shipping * address is missing. This can be described by:<pre> * String validationRole = "Shipping address"; * Address validationTarget = invoice.getShippingAddress(); * String validationText = "is mandatory"; * String validationProperty= "zip code"; * if (validationTarget.getZipCode() ...) { * validationResult.addMessage( * new PropertyValidationMessage( * validationText, * validationTarget, * validationRole, * validationProperty) * ); * } * </pre> * * @author Karsten Lentzsch * @version $Revision: 1.12 $ */ public class PropertyValidationMessage extends AbstractValidationMessage { /** * Refers to the object that holds the validated property, * for example an instance of an {@code Address} class. */ private final Object target; /** * Describes the optional role of the validated object, for example * <em>shipping</em> or <em>physical</em> address. */ private final String role; /** * Holds the name of the validated property, for example "zip code". */ private final String property; // Instance Creation ****************************************************** /** * Constructs a PropertyValidationMessage of type warning * for the given text, subject, role description and property description.<p> * * <strong>Examples:</strong><pre> * new PropertyValidationMessage( * "is mandatory", aCustomer, "Customer", "last name"); * new PropertyValidationMessage( * "must be over 18", aCustomer, "Customer", "age"); * * new PropertyValidationMessage( * "is mandatory", shippingAddress, "Shipping address", "zip code"); * new PropertyValidationMessage( * "is mandatory", shippingAddress, "Physical address", "zip code"); * </pre> * * @param text describes the validation problem * @param target the object that holds the validated property * @param role describes the target's role in the context * @param property describes the validated property * * @throws NullPointerException if the text, target, role, or property * is {@code null} * @throws IllegalArgumentException if {@code severity} is {@code OK} */ public PropertyValidationMessage(String text, Object target, String role, String property) { this(Severity.WARNING, text, target, role, property); } /** * Constructs a PropertyValidationMessage for the given text, * subject, role description and property description. * * <strong>Examples:</strong><pre> * new PropertyValidationMessage( * Severity.ERROR, "is mandatory", aCustomer, "Customer", "last name"); * new PropertyValidationMessage( * Severity.WARNING, "must be over 18", aCustomer, "Customer", "age"); * * new PropertyValidationMessage( * Severity.ERROR, "is mandatory", shippingAddress, "Shipping address", "zip code"); * new PropertyValidationMessage( * Severity.ERROR, "is mandatory", physicalAddress, "Physical address", "zip code"); * </pre> * * @param severity the message severity, either error or warning * @param text describes the validation problem * @param target the object that holds the validated property * @param role describes the target's role in the context * @param property describes the validated property * * @throws NullPointerException if the text, target, role, or property * is {@code null} * @throws IllegalArgumentException if {@code severity} is {@code OK} */ public PropertyValidationMessage(Severity severity, String text, Object target, String role, String property) { super(text, severity); this.target = checkNotNull(target, "The target must not be null."); this.role = checkNotNull(role, "The role must not be null."); this.property = checkNotNull(property, "The property must not be null."); } // Accessors ************************************************************** /** * Returns the validated object that holds the validated property, * for example an address object. This object can be further described * by a role, for example <em>shipping</em> or <em>physical</em> address. * * @return the validation target that holds the validated property */ public final Object target() { return target; } /** * Returns a description of the role of the validated object. * The role may differ from the type when multiple instances of the same * type are validated in a larger container.<p> * * Example: An invoice object holds a single {@code Order} instance, * and two instances of class {@code Address}, one for the shipping * address and another for the physical address. You then may consider * using the following roles: <em>Customer, Shipping address</em>, and * <em>Physical address</em>. * * @return a description of the role of the validated object */ public final String role() { return role; } /** * Returns a description of the validated object property, for example * "zip code". * * @return a description of the validated property */ public final String property() { return property; } /** * Returns a description of the validated aspect, that is the target's * role plus the validated property.<p> * * Examples: <pre> * "Customer.last name" * "Customer.age" * "Address.zip code" * "Shipping address.zip code" * "Physical address.zip code" * </pre> * * @return a String that describes the validated aspect */ public String aspect() { return role() + "." + property(); } /** * Returns a message description as formatted text. This implementation * concatenates the validated aspect, i.e. role + property and * the message text. * * @return a message description as formatted text */ @Override public String formattedText() { return aspect() + " " + text(); } /** * Returns this message's aspect as association key. This key can be used * to associate messages with views.<p> * * @return this messages's aspect as association key * * @see #aspect() */ @Override public Object key() { return aspect(); } // Comparison and Hashing ************************************************* /** * Compares the specified object with this validation message for equality. * Returns {@code true} if and only if the specified object is also * a property validation message, both messages have the same severity, * text, target, role, and property. In other words, two property validation * messages are defined to be equal if and only if they behave one like * the other.<p> * * This implementation first checks if the specified object is this * a property validation message. If so, it returns {@code true}; * if not, it checks if the specified object is a property validation message. * If not, it returns {@code false}; if so, it checks and returns * if the severities, texts, targets, roles, and properties of both messages * are equal. * * @param o the object to be compared for equality with this validation message. * * @return {@code true} if the specified object is equal * to this validation message. * * @see Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof PropertyValidationMessage)) { return false; } PropertyValidationMessage other = (PropertyValidationMessage) o; return severity().equals(other.severity()) && Objects.equals(text(), other.text()) && Objects.equals(target(), other.target()) && Objects.equals(role(), other.role()) && Objects.equals(property(), other.property()); } /** * Returns the hash code value for this validation message. * This implementation computes and returns the hash based * on the hash code values of this messages' severity, text, * target, role, and property.<p> * * If this class could be extended, we should check if the formatted text * is {@code null}. * * @return the hash code value for this validation message. * * @see Object#hashCode() */ @Override public int hashCode() { int result = 17; result = 37 * result + severity().hashCode(); result = 37 * result + (text() == null ? 0 : text().hashCode()); result = 37 * result + (target() == null ? 0 : target().hashCode()); result = 37 * result + (role() == null ? 0 : role().hashCode()); result = 37 * result + (property() == null ? 0 : property().hashCode()); return result; } }