package org.infoglue.cms.entities.kernel; import java.io.Serializable; import org.infoglue.cms.util.DomainUtils; /** * This base class for persistent object makes it easy to define domain objects and * have them implement the basic core services of an object that will allow them to * treated properly by Lists, Sets, HashMaps, Comparators, etc. Once you have these * services ironed out, it becomes much easier to deal with your domain objects and * test the servies that use them * * @author Frank Febbraro (frank@phase2technology.com) */ public abstract class Persistent implements BaseEntityVO, Comparable, Serializable { /** * Returns if this persisten object is unsaved (no generated id) */ public boolean isUnsaved() { return getId() == null; } /** * Returns if this persisten object is saved (has generated id) */ public boolean isSaved() { return getId() != null; } /** * Compares an object to this one for order. The comparison is based on ID unless both are unsaved, in which case * the comparison is done using hashCode(). This allows us to add multiple unsaved Persistents to sets even though * they have the same ID. * @param o the object to compare * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the * specified object * @throws ClassCastException if o is not an instance of Persistent * @throws NullPointerException if o is null * @see #hashCode */ public int compareTo(Object o) { Persistent p = (Persistent)o; return (isUnsaved() && p.isUnsaved()) ? new Integer(hashCode()).compareTo(new Integer(p.hashCode())) : DomainUtils.compare(getId(), p.getId()); } /** * Compares an object to this one for equality. * @param o the object to compare * @return true if this == o or o != null and getClass().equals(o.getClass()) and compareTo(o) == 0 * @see #compareTo */ public boolean equals(Object o) { return super.equals(o) || (o != null && getClass().equals(o.getClass()) && compareTo(o) == 0); } /** * Creates a hash code for this persistent. * @return Object.hashCode() if unsaved, otherwise returns the id's hashCode() */ public int hashCode() { return (isUnsaved()) ? super.hashCode() : DomainUtils.hashCode(getId()); } /** * Returns a string representation of this object. Subclasses that require a customized string representation should * override toStringBuffer() rather than this method. * @return toStringBuffer().toString() * @see #toStringBuffer */ public String toString() { return toStringBuffer().toString(); } /** * Returns a string buffer representation of this object. The idea is that subclasses can grab the string buffer * returned by this method and append to it, to save some gratuitous string creation. * @return a StringBuffer representation of this object */ protected StringBuffer toStringBuffer() { StringBuffer buffer = new StringBuffer(getClass().getName()).append(' '); buffer.append("id=").append(getId()); return buffer; } /** * Appends the given persistent to the given string buffer. This rather odd-looking method makes it easy for * subclasses overriding toStringBuffer() (or anyone else, for that matter) to add only the ID of a related object * to a string buffer without having to check for null. In practice, adding entire objects to the buffer returned * by an overridden toStringBuffer() can make for a long string that's hard to read when debugging. This method * helps restore some sanity when dealing with a large object that has a lot of relationships. * @param buffer the desired StringBuffer * @param persistent the desired Persistent * @see #toStringBuffer */ public static void append(StringBuffer buffer, Persistent persistent) { buffer = (persistent == null) ? buffer.append(persistent) : buffer.append(persistent.getId()); } }