1 package uk.org.lidalia.lang; 2 3 import static com.google.common.base.Preconditions.checkNotNull; 4 import static uk.org.lidalia.lang.Classes.inSameClassHierarchy; 5 6 /** 7 * Convenience class for types that represent a higher level abstraction over a single lower level type; for instance 8 * a class representing a network Port might extend {@code WrappedValue} and pass an {@code java.lang.Integer} as the value. 9 * 10 * Provides implementations of {@link #equals(Object)}, {@link #toString()} and {@link #hashCode()} based on the value 11 * of the wrapped instance. 12 */ 13 public abstract class WrappedValue { 14 15 private final Object wrapped; 16 17 protected WrappedValue(final Object wrapped) { 18 this.wrapped = checkNotNull(wrapped); 19 } 20 21 /** 22 * @return the toString representation of the wrapped instance 23 */ 24 @Override 25 public String toString() { 26 return wrapped.toString(); 27 } 28 29 /** 30 * Applies equality rules based on the value of the wrapped object. 31 * <ul> 32 * <li> normal rules in {@link Object#equals(Object)} - not equal to null, equal to same instance 33 * <li> other's runtime class must be the same, a super or a sub type of the runtime class of this instance 34 * <li> the value of the wrapped instance is the same as the value of the other's wrapped instance 35 * </ul> 36 * @param other the object to compare against 37 * @return true if the other type is logically equal to this 38 */ 39 @Override 40 public final boolean equals(final Object other) { 41 if (this == other) return true; 42 if (other == null) return false; 43 if (!(other instanceof WrappedValue) || !inSameClassHierarchy(getClass(), other.getClass())) return false; 44 45 final WrappedValue that = (WrappedValue) other; 46 47 return wrapped.equals(that.wrapped); 48 } 49 50 /** 51 * @return the hashCode of the wrapped instance 52 */ 53 @Override 54 public final int hashCode() { 55 return wrapped.hashCode(); 56 } 57 }