001    package com.sptci.prevayler;
002    
003    import java.util.Date;
004    
005    /**
006     * Abstract base class whose instances are stored in the prevalent system.
007     * At present sptodb does not support persisting other types of classes.
008     * This restriction was introduced since we need a {@link #objectId} field
009     * in the class that can be managed by the prevalent system.  Making this
010     * an interface would not guarantee us the availability of such a field.
011     *
012     * <p>&copy; Copyright 2008 <a href='http://sptci.com/' target='_top'>Sans
013     *   Pareil Technologies, Inc.</a></p>
014     * @author Rakesh Vidyadharan 2008-05-22
015     * @version $Id: PrevalentObject.java 22 2008-11-24 19:04:25Z sptrakesh $
016     */
017    public abstract class PrevalentObject<K>
018        implements java.io.Serializable, Cloneable, Comparable<PrevalentObject<K>>
019    {
020      private static final long serialVersionUID = 1L;
021    
022      /** The object id field for the instance. */
023      private K objectId;
024    
025      /**
026       * The metadata for the persistent object.  This field will be maintained
027       * by the {@link PrevalentSystem} when persistent operations on the object
028       * are performed.
029       */
030      private MetaData _sptodbMetaData;
031    
032      /** Default constructor. Note that a no-arg constructor is mandatory. */
033      protected PrevalentObject() {}
034    
035      /**
036       * Create a new instance of the prevalent object with the specified object
037       * id.  Use this form only when you wish to control the object id (using
038       * custom object id such as {@link java.lang.String}.
039       *
040       * @param oid The {@link #objectId} value to use.
041       */
042      protected PrevalentObject( final K oid )
043      {
044        this.objectId = oid;
045      }
046    
047      /**
048       * Compare the specified object with this instance for equality.  Two
049       * objects are considered equal if they have the same class and have the
050       * same value of {@link #objectId}.  Sub-classes are strongly discouraged
051       * from over-riding this method, since this method compares strictly based
052       * on {@link #objectId} equality.  In case you need to over-ride this
053       * method it is strongly recommended that you apply the additional rules
054       * after having invoked this implementation.
055       *
056       * @param object The object to be compared for equality with this object.
057       * @return Return <code>true</code> if the specified object is equivalent
058       *   to this object.
059       */
060      @Override
061      public boolean equals( final Object object )
062      {
063        if ( this == object ) return true;
064        if ( object == null ) return false;
065        boolean result = false;
066    
067        if ( ( getClass() == object.getClass() ) && ( objectId != null ) )
068        {
069          PrevalentObject po = (PrevalentObject) object;
070          result = objectId.equals( po.getObjectId() );
071        }
072    
073        return result;
074      }
075    
076      /**
077       * Default implementation of {@link java.lang.Object#hashCode}.  Over-ridden
078       * to return the hash code based upon {@link #objectId}.  Similar to
079       * {@link #equals}, sub-classes are discouraged from over-riding this
080       * default implementation.
081       *
082       * @return The hash code for this object.
083       */
084      @Override
085      public int hashCode()
086      {
087        int hash = 7;
088    
089        hash += ( 31 * 7 ) + getClass().getName().hashCode();
090        hash += ( 31 * 7 ) + ( ( objectId == null ) ? 0 : objectId.hashCode() );
091    
092        return hash;
093      }
094    
095      /**
096       * Compare the specified prevalent object with this instance for ordering.
097       * Returns a positive integer if the specified object is considered greater
098       * than this instance, 0 if equal and negative is less.   Default
099       * implementation compares based upon {@link #objectId}.  Sub-classes may
100       * need to over-ride this method for special handling.
101       *
102       * @param prevalentObject The object to be compared with this instance.
103       * @return A positive, 0, or negative number.
104       */
105      @SuppressWarnings( {"unchecked"} )
106      public int compareTo( final PrevalentObject prevalentObject )
107      {
108        int result = 0;
109    
110        if ( ( objectId != null ) && ( objectId instanceof Comparable ) )
111        {
112          result = ( (Comparable) objectId ).compareTo(
113              prevalentObject.getObjectId() );
114        }
115    
116        return result;
117      }
118    
119      /**
120       * Return a string representation of this object.  The default
121       * implementation just return the class name and {@link #objectId}.
122       *
123       * @return The string representation of this object.
124       */
125      @Override
126      public String toString()
127      {
128        final StringBuilder builder = new StringBuilder( 64 );
129        builder.append( getClass().getName() );
130        builder.append( " objectId=" ).append( objectId );
131    
132        if ( _sptodbMetaData != null )
133        {
134          builder.append( " created=" ).append( getCreationDate() );
135          builder.append( " updated=" ).append( getModificationDate() );
136        }
137    
138        return builder.toString();
139      }
140    
141      /**
142       * Over-ridden to make publicly accessible.
143       *
144       * @return The cloned instance of this object.
145       * @throws RuntimeException If the object cannot be cloned.
146       */
147      @Override
148      public Object clone() throws RuntimeException
149      {
150        try
151        {
152          return super.clone();
153        }
154        catch ( CloneNotSupportedException cex )
155        {
156          throw new RuntimeException( cex );
157        }
158      }
159    
160      /**
161       * Getter for property {@link #_sptodbMetaData}.
162       *
163       * @return Value for property {@link #_sptodbMetaData}.
164       */
165      final MetaData get_sptodbMetaData()
166      {
167        return _sptodbMetaData;
168      }
169    
170      /**
171       * Setter for property {@link #_sptodbMetaData}.
172       *
173       * @see #get_sptodbMetaData
174       * @param metadata Value to set for property {@link #_sptodbMetaData}.
175       */
176      final void set_sptodbMetaData( final MetaData metadata )
177      {
178        this._sptodbMetaData = metadata;
179      }
180    
181      /**
182       * Return the object id for the business object.
183       *
184       * @return The {@link #objectId} value.
185       */
186      public final K getObjectId()
187      {
188        return objectId;
189      }
190    
191      /**
192       * Return the date at which this object was created.  Note that the date
193       * will return different values until the object is initially persisted
194       * to the prevalent system.
195       *
196       * @return The date at which the object was persisted.
197       */
198      public final Date getCreationDate()
199      {
200        return ( _sptodbMetaData == null ) ? new Date() :
201            new Date( _sptodbMetaData.created );
202      }
203    
204      /**
205       * Return the date at which this object was last updated in the prevalent
206       * system.  Note that the date returned will return different values until
207       * the object has been persisted initially.
208       *
209       * @return The date at which the object was last updated.
210       */
211      public final Date getModificationDate()
212      {
213        return ( _sptodbMetaData == null ) ? new Date() :
214            new Date( _sptodbMetaData.modified );
215      }
216    
217      /**
218       * Return a flag indicating whether this instance represents a persistent
219       * instance or not.
220       *
221       * @return Return <code>true</code> if the instance is perstent in the
222       *   prevalent system.
223       */
224      public final boolean isPersistent()
225      {
226        return ( _sptodbMetaData != null );
227      }
228    
229      /**
230       * Return the {@code objectId} value that may be used to retrieve the
231       * prevalent instance from the specified string representation.  This is
232       * mandated by the necessity for storing the {@code objectId} values as
233       * {@link String} instances in the lucene index.
234       *
235       * <p><b>Note:</b> The string value of {@code objectId} stored in the
236       * lucene index is the value returned by {@link Object#toString()}.  Your
237       * primary key class must return a meaningful value to be able to
238       * reconstruct the primary key instance.</p>
239       *
240       * @since Version 0.3
241       * @param oid The string value that is to be converted to the proper {@code
242       *   objectId} value.
243       * @return The primary key instance.
244       */
245      public abstract K getObjectId( final String oid );
246    }