package com.qprogramming.tasq.task; import com.qprogramming.tasq.account.Account; import com.qprogramming.tasq.agile.Release; import com.qprogramming.tasq.agile.Sprint; import com.qprogramming.tasq.projects.Project; import com.qprogramming.tasq.support.PeriodHelper; import com.qprogramming.tasq.support.Utils; import com.qprogramming.tasq.support.sorters.CommentsSorter; import com.qprogramming.tasq.support.sorters.WorkLogSorter; import com.qprogramming.tasq.task.comments.Comment; import com.qprogramming.tasq.task.tag.Tag; import com.qprogramming.tasq.task.worklog.LogType; import com.qprogramming.tasq.task.worklog.TaskResolution; import com.qprogramming.tasq.task.worklog.WorkLog; import org.hibernate.Hibernate; import org.joda.time.Period; import javax.persistence.*; import java.util.*; @Entity public class Task implements java.io.Serializable { /** * */ private static final long serialVersionUID = 6612220415004910977L; @Id private String id; @Column private String name; @Column(columnDefinition = "text") private String description; @Column private Date create_date; @Column private Date lastUpdate; @Column private Date finishDate; @Column private boolean active = false; @Column private Date due_date; @Column private Period estimate; @Column private Period remaining; @Column private Period loggedWork; @Column private Enum<TaskState> state; @Column private Enum<TaskPriority> priority; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "worklogtask", fetch = FetchType.LAZY) private Set<WorkLog> worklog; @Column private Boolean estimated = false; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "task", fetch = FetchType.LAZY) private Set<Comment> comments; @ManyToOne @JoinColumn(name = "task_owner") private Account owner; @ManyToOne @JoinColumn(name = "task_assignee") private Account assignee; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "project_tasks") private Project project; @Column private Integer story_points; @Column private Enum<TaskType> type; @ManyToMany(fetch = FetchType.LAZY) private Set<Sprint> sprints = new HashSet<>(); @ManyToMany(fetch = FetchType.LAZY) private Set<Tag> tags = new HashSet<>(); @ManyToOne(fetch = FetchType.EAGER) private Release release; @Column private boolean inSprint; @Column private Integer subtasks; @Column private String parent; @Column(name = "task_order") private Long taskOrder; @Enumerated(EnumType.STRING) private TaskResolution resolution; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getCreate_date() { return Utils.convertDateTimeToString(create_date); } public void setCreate_date(Date create_date) { this.create_date = create_date; } public Date getRawLastUpdate() { return lastUpdate; } public String getLastUpdate() { if (lastUpdate != null) { return Utils.convertDateTimeToString(lastUpdate); } return ""; } public void setLastUpdate(Date lastUpdate) { this.lastUpdate = lastUpdate; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } public String getDue_date() { if (due_date != null) { return Utils.convertDateToString(due_date); } return ""; } public void setDue_date(Date due_date) { this.due_date = due_date; } public Date getRawDue_date() { return due_date; } public Date getRawCreate_date() { return create_date; } public String getFinishDate() { if (finishDate != null) { return Utils.convertDateTimeToString(finishDate); } return ""; } public void setFinishDate(Date finishDate) { this.finishDate = finishDate; } public Date getRawFinishDate() { return finishDate; } public String getEstimate() { return PeriodHelper.outFormat(estimate); } public void setEstimate(Period estimate) { this.estimate = estimate; } public Period getRawEstimate() { return estimate != null ? estimate : new Period(); } public List<WorkLog> getWorklog() { List<WorkLog> list_worklog = new ArrayList<WorkLog>(); list_worklog.addAll(getRawWorkLog()); Collections.sort(list_worklog, new WorkLogSorter(true)); return list_worklog; } public void setWorklog(Set<WorkLog> worklog) { this.worklog = worklog; } public Set<WorkLog> getRawWorkLog() { if (worklog == null) { worklog = new HashSet<WorkLog>(); } return worklog; } public void addWorkLog(WorkLog wl) { if (worklog == null) { worklog = new HashSet<WorkLog>(); } worklog.add(wl); } public String getLoggedWork() { return PeriodHelper.outFormat(getRawLoggedWork()); } public void setLoggedWork(Period loggedWork) { this.loggedWork = loggedWork; } public String getRemaining() { return PeriodHelper.outFormat(remaining); } public void setRemaining(Period remaining) { this.remaining = remaining; } public Period getRawRemaining() { return remaining != null ? remaining : new Period(); } public void updateLoggedWork() { this.loggedWork = new Period(); Set<WorkLog> worklg = getRawWorkLog(); worklg.stream().filter( activity -> !LogType.ESTIMATE.equals(activity.getType())).forEach( activity -> this.loggedWork = PeriodHelper.plusPeriods(this.loggedWork, activity.getActivity())); } public Period getRawLoggedWork() { return loggedWork == null ? new Period() : loggedWork; } public void addLoggedWork(Period loggedWork) { this.loggedWork = PeriodHelper.plusPeriods(getRawLoggedWork(), loggedWork); } public Enum<TaskState> getState() { return state; } public void setState(Enum<TaskState> state) { this.state = state; } public Boolean isEstimated() { return estimated; } public Boolean getEstimated() { return estimated; } public void setEstimated(Boolean estimated) { this.estimated = estimated; } public List<Comment> getComments() { List<Comment> comments_list = new ArrayList<Comment>(comments); Collections.sort(comments_list, new CommentsSorter(false)); return comments_list; } public void setComments(Set<Comment> comments) { this.comments = comments; } public void addComment(Comment comment) { if (comments == null) { comments = new HashSet<Comment>(); } comments.add(comment); } public Account getAssignee() { return assignee; } public void setAssignee(Account assignee) { this.assignee = assignee; } public Account getOwner() { return owner; } public void setOwner(Account owner) { this.owner = owner; } public Enum<TaskPriority> getPriority() { return priority; } public void setPriority(Enum<TaskPriority> priority) { this.priority = priority; } public Project getProject() { return project; } public void setProject(Project project) { this.project = project; } public Integer getStory_points() { return story_points != null ? story_points : 0; } public void setStory_points(Integer story_points) { this.story_points = story_points; } public Set<Sprint> getSprints() { if (sprints == null) { sprints = new HashSet<Sprint>(); } return sprints; } public void setSprints(Set<Sprint> sprints) { this.sprints = sprints; } public Release getRelease() { return release; } public void setRelease(Release release) { this.release = release; } public boolean isInSprint() { return inSprint; } public void setInSprint(boolean inSprint) { this.inSprint = inSprint; } public Integer getSubtasks() { return subtasks == null ? 0 : subtasks; } public void setSubtasks(Integer subtasks) { this.subtasks = subtasks; } public String getParent() { return parent; } public void setParent(String parent) { this.parent = parent; } public Enum<TaskType> getType() { return type; } public void setType(Enum<TaskType> type) { this.type = type; } public Long getTaskOrder() { return taskOrder; } public void setTaskOrder(Long taskOrder) { this.taskOrder = taskOrder; } public Set<Tag> getTags() { return tags; } public void setTags(Set<Tag> tags) { this.tags = tags; } public TaskResolution getResolution() { return resolution; } public void setResolution(TaskResolution resolution) { this.resolution = resolution; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return getId() + " " + getName(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((owner == null) ? 0 : owner.hashCode()); result = prime * result + ((priority == null) ? 0 : priority.hashCode()); result = prime * result + ((project == null) ? 0 : project.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Task other = (Task) obj; if (id == null) { if (other.id != null) { return false; } } else if (!id.equals(other.id)) { return false; } if (owner == null) { if (other.owner != null) { return false; } } else if (!owner.equals(other.owner)) { return false; } if (priority == null) { if (other.priority != null) { return false; } } else if (!priority.equals(other.priority)) { return false; } if (project == null) { if (other.project != null) { return false; } } else if (!project.equals(other.project)) { return false; } if (type == null) { if (other.type != null) { return false; } } else if (!type.equals(other.type)) { return false; } return true; } /** * Helpers */ public float getPercentage_logged() { long estimate_milis = PeriodHelper.toStandardDuration(getRawEstimate()) .getMillis(); long remaining_milis = PeriodHelper.toStandardDuration( getRawRemaining()).getMillis(); long logged_milis = PeriodHelper.toStandardDuration(getRawLoggedWork()) .getMillis(); if (estimate_milis > 0) { return logged_milis * 100 / estimate_milis; // task was without estimation time but is estimated type } else { if (remaining_milis == 0 && logged_milis != 0) { return 100; } else if (remaining_milis == 0 && logged_milis == 0) { return 0; } else { return logged_milis * 100 / (remaining_milis + logged_milis); } } } public boolean getLowerThanEstimate() { Period loggedAndLeft = PeriodHelper.plusPeriods(getRawLoggedWork(), remaining); Period result = PeriodHelper.minusPeriods(estimate, loggedAndLeft); return PeriodHelper.toStandardDuration(result).getMillis() > 0; } public float getMoreThanEstimate() { Period loggedAndLeft = getRawLoggedWork(); if (PeriodHelper.toStandardDuration(remaining).getMillis() > 0) { loggedAndLeft = PeriodHelper.plusPeriods(loggedAndLeft, remaining); } return PeriodHelper.toStandardDuration(estimate).getMillis() * 100 / PeriodHelper.toStandardDuration(loggedAndLeft).getMillis(); } public float getOverCommited() { long remaining_milis = PeriodHelper.toStandardDuration(remaining) .getMillis(); if (remaining_milis > 0) { Period plus = PeriodHelper.plusPeriods(getRawLoggedWork(), remaining); return (remaining_milis * 100) / PeriodHelper.toStandardDuration(plus).getMillis(); } return 0; } public float getPercentage_left() { long estimate_milis = PeriodHelper.toStandardDuration(getRawEstimate()) .getMillis(); if (estimate_milis > 0) { return PeriodHelper.toStandardDuration(getRawRemaining()) .getMillis() * 100 / estimate_milis; } else { return 0; } } public void reduceRemaining(Period activity) { remaining = PeriodHelper.minusPeriods(remaining, activity); if (PeriodHelper.toStandardDuration(remaining).getMillis() < 0) { remaining = new Period(); } } public void addSprint(Sprint sprint) { getSprints().add(sprint); setInSprint(true); } public void removeSprint(Sprint sprint) { if (this.sprints != null) { this.sprints.remove(sprint); setInSprint(false); } } /** * Reqieres session and initialize * * @param sprint * @return */ public boolean inSprint(Sprint sprint) { Hibernate.initialize(getSprints()); return getSprints().contains(sprint); } public void addSubTask() { this.subtasks = getSubtasks() + 1; } public boolean isSubtask() { return parent != null; } }