001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ---------
028 * Task.java
029 * ---------
030 * (C) Copyright 2003-present, by David Gilbert.
031 *
032 * Original Author:  David Gilbert;
033 * Contributor(s):   Tracy Hiltbrand (equals/hashCode comply with EqualsVerifier);
034 *
035 */
036
037package org.jfree.data.gantt;
038
039import java.io.Serializable;
040import java.util.Date;
041import java.util.List;
042import java.util.Objects;
043import org.jfree.chart.util.Args;
044import org.jfree.chart.util.PublicCloneable;
045
046import org.jfree.data.time.SimpleTimePeriod;
047import org.jfree.data.time.TimePeriod;
048
049/**
050 * A simple representation of a task.  The task has a description and a
051 * duration.  You can add sub-tasks to the task.
052 */
053public class Task implements Cloneable, PublicCloneable, Serializable {
054
055    /** For serialization. */
056    private static final long serialVersionUID = 1094303785346988894L;
057
058    /** The task description. */
059    private String description;
060
061    /** The time period for the task (estimated or actual). */
062    private TimePeriod duration;
063
064    /** The percent complete ({@code null} is permitted). */
065    private Double percentComplete;
066
067    /** Storage for the sub-tasks (if any). */
068    private List subtasks;
069
070    /**
071     * Creates a new task.
072     *
073     * @param description  the task description ({@code null} not
074     *                     permitted).
075     * @param duration  the task duration ({@code null} permitted).
076     */
077    public Task(String description, TimePeriod duration) {
078        Args.nullNotPermitted(description, "description");
079        this.description = description;
080        this.duration = duration;
081        this.percentComplete = null;
082        this.subtasks = new java.util.ArrayList();
083    }
084
085    /**
086     * Creates a new task.
087     *
088     * @param description  the task description ({@code null} not
089     *                     permitted).
090     * @param start  the start date ({@code null} not permitted).
091     * @param end  the end date ({@code null} not permitted).
092     */
093    public Task(String description, Date start, Date end) {
094        this(description, new SimpleTimePeriod(start, end));
095    }
096
097    /**
098     * Returns the task description.
099     *
100     * @return The task description (never {@code null}).
101     */
102    public String getDescription() {
103        return this.description;
104    }
105
106    /**
107     * Sets the task description.
108     *
109     * @param description  the description ({@code null} not permitted).
110     */
111    public void setDescription(String description) {
112        Args.nullNotPermitted(description, "description");
113        this.description = description;
114    }
115
116    /**
117     * Returns the duration (actual or estimated) of the task.
118     *
119     * @return The task duration (possibly {@code null}).
120     */
121    public TimePeriod getDuration() {
122        return this.duration;
123    }
124
125    /**
126     * Sets the task duration (actual or estimated).
127     *
128     * @param duration  the duration ({@code null} permitted).
129     */
130    public void setDuration(TimePeriod duration) {
131        this.duration = duration;
132    }
133
134    /**
135     * Returns the percentage complete for this task.
136     *
137     * @return The percentage complete (possibly {@code null}).
138     */
139    public Double getPercentComplete() {
140        return this.percentComplete;
141    }
142
143    /**
144     * Sets the percentage complete for the task.
145     *
146     * @param percent  the percentage ({@code null} permitted).
147     */
148    public void setPercentComplete(Double percent) {
149        this.percentComplete = percent;
150    }
151
152    /**
153     * Sets the percentage complete for the task.
154     *
155     * @param percent  the percentage.
156     */
157    public void setPercentComplete(double percent) {
158        setPercentComplete(Double.valueOf(percent));
159    }
160
161    /**
162     * Adds a sub-task to the task.
163     *
164     * @param subtask  the subtask ({@code null} not permitted).
165     */
166    public void addSubtask(Task subtask) {
167        Args.nullNotPermitted(subtask, "subtask");
168        this.subtasks.add(subtask);
169    }
170
171    /**
172     * Removes a sub-task from the task.
173     *
174     * @param subtask  the subtask.
175     */
176    public void removeSubtask(Task subtask) {
177        this.subtasks.remove(subtask);
178    }
179
180    /**
181     * Returns the sub-task count.
182     *
183     * @return The sub-task count.
184     */
185    public int getSubtaskCount() {
186        return this.subtasks.size();
187    }
188
189    /**
190     * Returns a sub-task.
191     *
192     * @param index  the index.
193     *
194     * @return The sub-task.
195     */
196    public Task getSubtask(int index) {
197        return (Task) this.subtasks.get(index);
198    }
199
200    /**
201     * Tests this object for equality with an arbitrary object.
202     *
203     * @param object  the other object ({@code null} permitted).
204     *
205     * @return A boolean.
206     */
207    @Override
208    public boolean equals(Object object) {
209        if (object == this) {
210            return true;
211        }
212        if (!(object instanceof Task)) {
213            return false;
214        }
215        Task that = (Task) object;
216        if (!Objects.equals(this.description, that.description)) {
217            return false;
218        }
219        if (!Objects.equals(this.duration, that.duration)) {
220            return false;
221        }
222        if (!Objects.equals(this.percentComplete, that.percentComplete)) {
223            return false;
224        }
225        if (!Objects.equals(this.subtasks, that.subtasks)) {
226            return false;
227        }
228        if (!that.canEqual(this)) {
229            return false;
230        }
231
232        return true;
233    }
234
235    /**
236     * Ensures symmetry between super/subclass implementations of equals. For
237     * more detail, see http://jqno.nl/equalsverifier/manual/inheritance.
238     *
239     * @param other Object
240     * 
241     * @return true ONLY if the parameter is THIS class type
242     */
243    public boolean canEqual(Object other) {
244        // fix the "equals not symmetric" problem
245        return (other instanceof Task);
246    }
247
248    @Override
249    public int hashCode() {
250        int hash = 3;
251        hash = 31 * hash + Objects.hashCode(this.description);
252        hash = 31 * hash + Objects.hashCode(this.duration);
253        hash = 31 * hash + Objects.hashCode(this.percentComplete);
254        hash = 31 * hash + Objects.hashCode(this.subtasks);
255        return hash;
256    }
257
258    /**
259     * Returns a clone of the task.
260     *
261     * @return A clone.
262     *
263     * @throws CloneNotSupportedException  never thrown by this class, but
264     *         subclasses may not support cloning.
265     */
266    @Override
267    public Object clone() throws CloneNotSupportedException {
268        Task clone = (Task) super.clone();
269        return clone;
270    }
271
272}