001    /*
002     *  jDTAUS Core API
003     *  Copyright (c) 2005 Christian Schulte
004     *
005     *  Christian Schulte, Haldener Strasse 72, 58095 Hagen, Germany
006     *  <schulte2005@users.sourceforge.net> (+49 2331 3543887)
007     *
008     *  This library is free software; you can redistribute it and/or
009     *  modify it under the terms of the GNU Lesser General Public
010     *  License as published by the Free Software Foundation; either
011     *  version 2.1 of the License, or any later version.
012     *
013     *  This library is distributed in the hope that it will be useful,
014     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
015     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016     *  Lesser General Public License for more details.
017     *
018     *  You should have received a copy of the GNU Lesser General Public
019     *  License along with this library; if not, write to the Free Software
020     *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
021     *
022     */
023    package org.jdtaus.core.monitor;
024    
025    import java.io.Serializable;
026    import java.rmi.server.UID;
027    import java.util.Comparator;
028    import org.jdtaus.core.text.Message;
029    
030    /**
031     * A task of execution.
032     * <p>A task is a sequence of operations taking time. This class defines
033     * properties to be used by applications to query a task for information and for
034     * cancelling a task. Property {@code indeterminate} indicates if a task
035     * supports properties {@code minimum}, {@code maximum} and {@code progress}.
036     * Property {@code cancelable} indicates if a task may be cancelled by an
037     * application by setting property {@code cancelled} to {@code true}.
038     * Properties {@code description} and {@code progressDescription} hold
039     * presentation descriptions of a task itself and of the work currently
040     * performed by a task.</p>
041     *
042     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
043     * @version $Id: Task.java 8044 2009-07-02 01:29:05Z schulte2005 $
044     *
045     * @see TaskEvent
046     */
047    public abstract class Task implements Cloneable, Serializable
048    {
049        //--Constants---------------------------------------------------------------
050    
051        /**
052         * Comparator for sorting tasks in ascending order of creation time.
053         * <p><b>Note:</b><br/>
054         * This comparator imposes orderings that are inconsistent with equals.</p>
055         */
056        public static final Comparator ASCENDING = new AscendingTaskComparator();
057    
058        /**
059         * Comparator for sorting tasks in descending order of creation time.
060         * <p><b>Note:</b><br/>
061         * This comparator imposes orderings that are inconsistent with equals.</p>
062         */
063        public static final Comparator DESCENDING =
064            new DescendingTaskComparator();
065    
066        /** Serial version UID for backwards compatibility with 1.0.x classes. */
067        private static final long serialVersionUID = -3919376355708819307L;
068    
069        //---------------------------------------------------------------Constants--
070        //--Constructors------------------------------------------------------------
071    
072        /** Creates a new {@code Task} instance. */
073        public Task()
074        {
075            super();
076            this.uid = new UID();
077            this.indeterminate = true;
078            this.timestamp = System.currentTimeMillis();
079        }
080    
081        //------------------------------------------------------------Constructors--
082        //--Task--------------------------------------------------------------------
083    
084        /**
085         * Unique task identifier.
086         * @serial
087         */
088        private UID uid;
089    
090        /**
091         * The timestamp this task got created.
092         * @serial
093         */
094        private long timestamp;
095    
096        /**
097         * Flag indicating that an application cancelled the task.
098         * @serial
099         */
100        private boolean cancelled;
101    
102        /**
103         * Description of the {@code Task}.
104         * @serial
105         */
106        protected Message description;
107    
108        /**
109         * Description of the progress of the {@code Task}.
110         * @serial
111         */
112        protected Message progressDescription;
113    
114        /**
115         * The lower bound of the range.
116         * @serial
117         */
118        protected int minimum;
119    
120        /**
121         * The upper bound of the range.
122         * @serial
123         */
124        protected int maximum;
125    
126        /**
127         * Indicates the progress of the task.
128         * @serial
129         */
130        protected int progress;
131    
132        /**
133         * Flag indicating if the operations performed by the task are of unknown
134         * length.
135         * @serial
136         */
137        protected boolean indeterminate;
138    
139        /**
140         * Flag indicating that an application may cancel the task.
141         * @serial
142         */
143        protected boolean cancelable;
144    
145        /**
146         * Getter for property {@code timestamp}.
147         *
148         * @return the timestamp this task got created.
149         */
150        synchronized public final long getTimestamp()
151        {
152            return this.timestamp;
153        }
154    
155        /**
156         * Getter for property {@code description}.
157         *
158         * @return description of the task.
159         */
160        synchronized public final Message getDescription()
161        {
162            return this.description;
163        }
164    
165        /**
166         * Getter for property {@code progressDescription}.
167         *
168         * @return description of the progress of the task or {@code null}.
169         */
170        synchronized public final Message getProgressDescription()
171        {
172            return this.progressDescription;
173        }
174    
175        /**
176         * Gets the lower end of the progress value.
177         *
178         * @return an int representing the minimum value.
179         *
180         * @throws IllegalStateException if the task is indeterminate.
181         */
182        synchronized public final int getMinimum()
183        {
184            if ( this.isIndeterminate() )
185            {
186                throw new IllegalStateException();
187            }
188    
189            return this.minimum;
190        }
191    
192        /**
193         * Gets the higher end of the progress value.
194         *
195         * @return an int representing the maximum value.
196         *
197         * @throws IllegalStateException if the task is indeterminate.
198         */
199        synchronized public final int getMaximum()
200        {
201            if ( this.isIndeterminate() )
202            {
203                throw new IllegalStateException();
204            }
205    
206            return this.maximum;
207        }
208    
209        /**
210         * Gets the progress of the task.
211         *
212         * @return the progress of the task.
213         *
214         * @throws IllegalStateException if the task is indeterminate.
215         */
216        synchronized public final int getProgress()
217        {
218            if ( this.isIndeterminate() )
219            {
220                throw new IllegalStateException();
221            }
222    
223            return this.progress;
224        }
225    
226        /**
227         * Flag indicating if the task supports properties {@code minimum},
228         * {@code maximum} and {@code progress}.
229         *
230         * @return {@code true} if the operations performed by the task are of
231         * unknown length; {@code false} if properties {@code minimum},
232         * {@code maximum} and {@code progress} hold progress information.
233         */
234        synchronized public final boolean isIndeterminate()
235        {
236            return this.indeterminate;
237        }
238    
239        /**
240         * Flag indicating that the task supports property {@code cancelled}.
241         *
242         * @return {@code true} if the task supports property {@code cancelled};
243         * {@code false} if property {@code cancelled} is ignored by the task.
244         */
245        synchronized public final boolean isCancelable()
246        {
247            return this.cancelable;
248        }
249    
250        /**
251         * Flag indicating that the task is cancelled.
252         *
253         * @return {@code true} if the task is cancelled; {@code false} else.
254         *
255         * @throws IllegalStateException if the task is not cancelable.
256         */
257        synchronized public final boolean isCancelled()
258        {
259            if ( !this.isCancelable() )
260            {
261                throw new IllegalStateException();
262            }
263    
264            return this.cancelled;
265        }
266    
267        /**
268         * Setter for property {@code cancelled}.
269         * <p>Applications may request cancellation of a {@code Task} by setting
270         * property {@code cancelled} to {@code true}. Implementations indicate
271         * theire support for task cancellation by property {@code cancelable}.</p>
272         *
273         * @param value {@code true} to cancel the task; {@code false} else.
274         *
275         * @throws IllegalStateException if the task is not cancelable or is already
276         * cancelled.
277         */
278        synchronized public final void setCancelled( final boolean value )
279        {
280            if ( !this.isCancelable() || this.isCancelled() )
281            {
282                throw new IllegalStateException();
283            }
284    
285            this.cancelled = value;
286        }
287    
288        /**
289         * Creates a string representing the properties of the instance.
290         *
291         * @return a string representing the properties of the instance.
292         */
293        private String internalString()
294        {
295            return new StringBuffer( 500 ).append( '{' ).
296                append( "uid=" ).append( this.uid ).
297                append( ", indeterminate=" ).append( this.indeterminate ).
298                append( ", cancelable=" ).append( this.cancelable ).
299                append( ", cancelled=" ).append( this.cancelled ).
300                append( ", maximum=" ).append( this.maximum ).
301                append( ", minimum=" ).append( this.minimum ).
302                append( ", progress=" ).append( this.progress ).
303                append( ", description=" ).append( this.description ).
304                append( ", progressDescription=" ).
305                append( this.progressDescription ).
306                append( ", timestamp=" ).append( this.timestamp ).
307                append( '}' ).toString();
308    
309        }
310    
311        //--------------------------------------------------------------------Task--
312        //--Object------------------------------------------------------------------
313    
314        /**
315         * Returns a string representation of the object.
316         *
317         * @return a string representation of the object.
318         */
319        public String toString()
320        {
321            return super.toString() + this.internalString();
322        }
323    
324        /**
325         * Returns a hash code value for this object.
326         *
327         * @return a hash code value for this object.
328         */
329        public final int hashCode()
330        {
331            return this.uid.hashCode();
332        }
333    
334        /**
335         * Indicates whether some other object is equal to this one.
336         * <p>Tasks internally cary a UID which is created during instantiation.
337         * This UID is used for comparing {@code o} with the instance.</p>
338         *
339         * @param o the reference object with which to compare.
340         *
341         * @return {@code true} if this object is the same as {@code o};
342         * {@code false} otherwise.
343         *
344         * @see UID
345         */
346        public final boolean equals( final Object o )
347        {
348            return o == this || ( o instanceof Task &&
349                ( (Task) o ).uid.equals( this.uid ) );
350    
351        }
352    
353        /**
354         * Creates and returns a copy of this object.
355         *
356         * @return a clone of this instance.
357         */
358        public Object clone()
359        {
360            try
361            {
362                return super.clone();
363            }
364            catch ( CloneNotSupportedException e )
365            {
366                throw new AssertionError( e );
367            }
368        }
369    
370        //------------------------------------------------------------------Object--
371    }
372    
373    /**
374     * Comparator for sorting tasks in ascending order of creation time.
375     * <p><b>Note:</b><br/>
376     * This comparator imposes orderings that are inconsistent with equals.</p>
377     *
378     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
379     * @version $Id: Task.java 8044 2009-07-02 01:29:05Z schulte2005 $
380     */
381    class AscendingTaskComparator implements Comparator, Serializable
382    {
383        //--Comparator--------------------------------------------------------------
384    
385        /**
386         * {@inheritDoc}
387         *
388         * @throws NullPointerException if either {@code o1} or {@code o2} is
389         * {@code null}.
390         * @throws ClassCastException if either {@code o1} or {@code o2} is not an
391         * instance of {@code Task}.
392         */
393        public int compare( final Object o1, final Object o2 )
394        {
395            if ( o1 == null )
396            {
397                throw new NullPointerException( "o1" );
398            }
399            if ( o2 == null )
400            {
401                throw new NullPointerException( "o2" );
402            }
403            if ( !( o1 instanceof Task ) )
404            {
405                throw new ClassCastException( o1.getClass().getName() );
406            }
407            if ( !( o2 instanceof Task ) )
408            {
409                throw new ClassCastException( o2.getClass().getName() );
410            }
411    
412            // TODO JDK 1.5 Long.valueOf(long)
413            final Long l1 = new Long( ( (Task) o1 ).getTimestamp() );
414            final Long l2 = new Long( ( (Task) o2 ).getTimestamp() );
415            return l1.compareTo( l2 );
416        }
417    
418        //--------------------------------------------------------------Comparator--
419    }
420    
421    /**
422     * Comparator for sorting tasks in descending order of creation time.
423     * <p><b>Note:</b><br/>
424     * This comparator imposes orderings that are inconsistent with equals.</p>
425     *
426     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
427     * @version $Id: Task.java 8044 2009-07-02 01:29:05Z schulte2005 $
428     */
429    class DescendingTaskComparator
430        extends AscendingTaskComparator
431    {
432        //--Comparator--------------------------------------------------------------
433    
434        /**
435         * {@inheritDoc}
436         *
437         * @throws NullPointerException if either {@code o1} or {@code o2} is
438         * {@code null}.
439         * @throws ClassCastException if either {@code o1} or {@code o2} is not an
440         * instance of {@code Task}.
441         */
442        public int compare( final Object o1, final Object o2 )
443        {
444            return super.compare( o2, o1 );
445        }
446    
447        //--------------------------------------------------------------Comparator--
448    }