All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.publicobject.issuesbrowser.Issue Maven / Gradle / Ivy

The newest version!
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package com.publicobject.issuesbrowser;

import ca.odell.glazedlists.jfreechart.DefaultValueSegment;
import ca.odell.glazedlists.jfreechart.ValueSegment;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * An issue models a work effort either due to an existing problem or a desired
 * enhancement.
 *
 * @author James Lemieux
 * @author Jesse Wilson
 */
public class Issue implements Comparable {

    public static final DateFormat TABLE_DATE_FORMAT = DateFormat.getDateInstance(DateFormat.MEDIUM);
    public static final DateFormat DETAILS_DATE_FORMAT = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");

    // the project that this issue is attached to
    private Project owner;

    // mandatory issue fields
    private String id;
    private String statusCode;
    private String status;
    private Priority priority;
    private String resolution;
    private String component;
    private String version;
    private String repPlatform;
    private String assignedTo;
    private Date deltaTimestamp;
    private String subcomponent;
    private String reporter;
    private String targetMilestone;
    private String issueType;
    private Date creationTimestamp;
    private String qaContact;
    private String statusWhiteboard;
    private String fileLocation;
    private String votes;
    private String operatingSystem;
    private String shortDescription;
    private PeerIssue isDuplicate;
    // optional fields
    private List keywords = new ArrayList();
    private List blocks = new ArrayList();
    private List cc = new ArrayList();
    // issue rich fields
    private List descriptions = new ArrayList();
    private List attachments = new ArrayList();
    private List activities = new ArrayList();
    private List> stateChanges = new ArrayList>();
    private List duplicates = new ArrayList();
    private List dependsOn = new ArrayList();

    private List allUsers;

    /**
     * Creates a new empty issue.
     */
    public Issue(Project owner) {
        this.owner = owner;
    }

    /**
     * Creates a new issue that uses the specified issue as a template.
     */
    public Issue(Project owner, Issue template) {
        this.owner = owner;
        id = template.id;
        status = template.status;
        priority = template.priority;
        resolution = template.resolution;
        component = template.component;
        version = template.version;
        repPlatform = template.repPlatform;
        assignedTo = template.assignedTo;
        deltaTimestamp = template.deltaTimestamp;
        subcomponent = template.subcomponent;
        reporter = template.reporter;
        targetMilestone = template.targetMilestone;
        issueType = template.issueType;
        creationTimestamp = template.creationTimestamp;
        qaContact = template.qaContact;
        statusWhiteboard = template.statusWhiteboard;
        votes = template.votes;
        operatingSystem = template.operatingSystem;
        shortDescription = template.shortDescription;
        keywords.addAll(template.keywords);
        blocks.addAll(template.blocks);
        dependsOn.addAll(template.dependsOn);
        cc.addAll(template.cc);
        descriptions.addAll(template.descriptions);
        attachments.addAll(template.attachments);
        activities.addAll(template.activities);
    }

    /**
     * This convenience method processes a fully loaded Issue and produces a
     * List of RangedValues which describe the duration of each Status within
     * the lifetime of the given issue. For example, an Issue
     * might have a series of state changes such as:
     *
     * 

{NEW: Issue creation Timestamp -> Feb}, {STARTED: Feb -> Apr}, {CLOSED: Apr -> Mar}, {RESOLVED: Mar -> lastDate} * *

and each part of that progression will be a {@link ValueSegment} * containing a start and end Date and a status. * * @param issue the Issue to compute the state changes for * @return a List of {@link ValueSegment} objecs describing the duration * of each Status within the lifetime of the issue */ public static List> computeStateChanges(Issue issue, Date lastDate) { // this stores the sequence of state changes in chronological order, like a timeline final List> timeline = new ArrayList>(); final IssueTrackingSystem issueTracker = issue.getProject().getOwner(); String state = issueTracker.getSupportedStati()[0].getName(); // the end Date of the previous ValueSegment Date last = issue.getCreationTimestamp(); // Iterate the issues in chronological (natural) order for (Iterator i = issue.getActivities().iterator(); i.hasNext();) { Activity activity = i.next(); // if the Activity represents a change in status if ("issue_status" == activity.getField()) { // create an entry in the timeline Date when = activity.getWhen(); timeline.add(new DefaultValueSegment(last, when, state)); last = when; state = activity.getNewValue(); } } // create one last entry in the time timeline that ends at the given lastDate timeline.add(new DefaultValueSegment(last, lastDate, state)); return timeline; } /** * Gets all users related to this issue. */ public List getAllUsers() { // init the users list if necessary if(allUsers == null) { allUsers = new ArrayList(); if(assignedTo != null) allUsers.add(assignedTo); if(reporter != null) allUsers.add(reporter); if(qaContact != null) allUsers.add(qaContact); for(Iterator d = descriptions.iterator(); d.hasNext(); ) { allUsers.add(d.next().getWho()); } } return allUsers; } /** * ID of this issue (unique key). */ public String getId() { return id; } public void setId(String id) { this.id = id; } /** * Get the web address of this issue for use with a browser like IE or Firefox. */ public URL getURL() { try { return new URL(getProject().getIssueDetailUri(this)); } catch(MalformedURLException e) { throw new RuntimeException(e); } } /** * HTTP-like status code of this issue, such as "200". */ public String getStatusCode() { return statusCode; } public void setStatusCode(String statusCode) { this.statusCode = statusCode; } /** * Current status of this issue. */ public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } /** * Priority (severity) assigned to issue. */ public Priority getPriority() { return priority; } public void setPriority(Priority priority) { this.priority = priority; } /** * The issue's resolution, if any */ public String getResolution() { return resolution; } public void setResolution(String resolution) { this.resolution = resolution; } /** * Product against which issue is reported. */ public String getComponent() { return component; } public void setComponent(String component) { this.component = component; } /** * Version associated with component. */ public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } /** * Platform that the issue was reported against. */ public String getRepPlatform() { return repPlatform; } public void setRepPlatform(String repPlatform) { this.repPlatform = repPlatform; } /** * Email of person issue currently assigned to. */ public String getAssignedTo() { return assignedTo; } public void setAssignedTo(String assignedTo) { this.assignedTo = assignedTo; } /** * Last modified timestamp ('yyyyMMddhhmmss'). */ public Date getDeltaTimestamp() { return deltaTimestamp; } public void setDeltaTimestamp(Date deltaTimestamp) { this.deltaTimestamp = deltaTimestamp; } /** * Component of component issue reported against. */ public String getSubcomponent() { return subcomponent; } public void setSubcomponent(String subcomponent) { this.subcomponent = subcomponent; } /** * Email of initial issue reporter. */ public String getReporter() { return reporter; } public void setReporter(String reporter) { this.reporter = reporter; } /** * Milestone for this issue's resolution. */ public String getTargetMilestone() { return targetMilestone; } public void setTargetMilestone(String targetMilestone) { this.targetMilestone = targetMilestone; } /** * Nature of issue. This refers to whether the issue is a defect, task, * enhancement, etc. */ public String getIssueType() { return issueType; } public void setIssueType(String issueType) { this.issueType = issueType; } /** * Issue creation timestamp ('yyyy-mm-dd hh:mm:ss'). */ public Date getCreationTimestamp() { return creationTimestamp; } public void setCreationTimestamp(Date creationTimestamp) { this.creationTimestamp = creationTimestamp; } /** * Email of the QA contact for this issue. */ public String getQAContact() { return qaContact; } public void setQAContact(String qaContact) { this.qaContact = qaContact; } /** * Free text 'whiteboard' for issue comments. */ public String getStatusWhiteboard() { return statusWhiteboard; } public void setStatusWhiteboard(String statusWhiteboard) { this.statusWhiteboard = statusWhiteboard; } /** * current votes for issue. */ public String getVotes() { return votes; } public void setVotes(String votes) { this.votes = votes; } /** * URL related to issue */ public String getFileLocation() { return fileLocation; } public void setFileLocation(String fileLocation) { this.fileLocation = fileLocation; } /** * Operating system issue reported against. */ public String getOperatingSystem() { return operatingSystem; } public void setOperatingSystem(String operatingSystem) { this.operatingSystem = operatingSystem; } /** * Short description of issue. */ public String getShortDescription() { return shortDescription; } public void setShortDescription(String shortDescription) { this.shortDescription = shortDescription; } /** * List of keywords for this issue. */ public List getKeywords() { return keywords; } /** * List of email addresses of interested parties. */ public List getCC() { return cc; } /** * Data from the longdescs table for this issue id. Essentially * the log of additional comments. */ public List getDescriptions() { return descriptions; } /** * Get the attachments to this issue. */ public List getAttachments() { return attachments; } /** * Get the activities upon this issue. */ public List getActivities() { return activities; } /** * Get the List of RangedValues describing the succession of state changes * this Issue has experienced. */ public List> getStateChanges() { return stateChanges; } /** * Other issues which were closed as a duplicate of this issue. */ public List getDuplicates() { return duplicates; } /** * List of local issue IDs that depend on this one. */ public List getDependsOn() { return dependsOn; } /** * List of local issue IDs blocked by this one. */ public List getBlocks() { return blocks; } /** * The issue which this issue was closed as a duplicate of. */ public PeerIssue getDuplicate() { return isDuplicate; } public void setDuplicate(PeerIssue isDuplicate) { this.isDuplicate = isDuplicate; } /** * @return the owning project */ public Project getProject() { return owner; } /** * Write this issue for debugging. */ @Override public String toString() { return "Issue " + id + ": " + getPriority().getRating(); } /** * Compares two issues by ID. */ public int compareTo(Object other) { if (other == null) return -1; Issue otherIssue = (Issue) other; return id.compareTo(otherIssue.id); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy