com.jgoodies.validation.message.PropertyValidationMessage Maven / Gradle / Ivy
Show all versions of jgoodies-validation Show documentation
/*
* 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 aspect 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.
*
* Example: 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:
* 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)
* );
* }
*
*
* @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
* shipping or physical 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.
*
* Examples:
* 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");
*
*
* @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.
*
* Examples:
* 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");
*
*
* @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 shipping or physical 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.
*
* 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: Customer, Shipping address, and
* Physical address.
*
* @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.
*
* Examples:
* "Customer.last name"
* "Customer.age"
* "Address.zip code"
* "Shipping address.zip code"
* "Physical address.zip code"
*
*
* @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.
*
* @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.
*
* 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.
*
* 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;
}
}