import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.ConstantsManager;
import com.atlassian.jira.issue.DocumentIssueImpl;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager;
import com.atlassian.jira.issue.history.ChangeItemBean;
import com.atlassian.jira.issue.status.Status;
import com.atlassian.jira.jql.parser.JqlParseException;
import com.atlassian.jira.jql.parser.JqlQueryParser;
import com.atlassian.query.Query;
import com.decadis.jira.xchart.api.ChartParam;
import com.decadis.jira.xchart.api.model.ChartType;
def logger = Logger.getLogger("Time In Status Chart")
def i18nHelper = ComponentAccessor.getJiraAuthenticationContext().getI18nHelper()
public static BigDecimal TimeDiffInHours(Date a, Date b)
{
return BigDecimal.valueOf(((double) (Math.abs(a.getTime() - b.getTime()) / 1000l)) / 3600.0d);
}
String jql = JQL;
JqlQueryParser jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class);
Query query = null;
try
{
query = jqlQueryParser.parseQuery(jql);
} catch (JqlParseException e)
{
logger.warn("Bad JQL:" + jql, e);
throw new IllegalArgumentException("Bad JQL: " + jql);
}
// for evaluation of issue history
ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager();
ConstantsManager constantsManager = ComponentAccessor.getConstantsManager();
Date now = new Date();
def data = chartBuilder.newDataCollector()
def grouper = chartBuilder.getGrouper(Group);
Field documentField;
try
{
documentField = DocumentIssueImpl.class.getDeclaredField("document");
documentField.setAccessible(true);
// iterate over the issues
for ( Issue issue : chartBuilder.getFilterUtils().performSearch(query, user) )
{
Date since = issue.getCreated();
Date until = now;
String currentStatus = null;
def groups = grouper.getGroups((Document) documentField.get(issue));
// iterate over the issue change history of the status field
for ( ChangeItemBean item : changeHistoryManager.getChangeItemsForField(issue, "status") )
{
until = item.getCreated();
// first change item -> initial status of issue is unknown
if ( currentStatus == null )
{
currentStatus = constantsManager.getStatus(item.getFrom()).getNameTranslation(i18nHelper);
}
for ( String group : groups )
{
data.addValue(TimeDiffInHours(until, since), currentStatus, grouper.getResolvedValue(group, issue));
}
since = item.getCreated();
currentStatus = constantsManager.getStatus(item.getTo()).getNameTranslation(i18nHelper);
}
// add time of current status
until = now;
currentStatus = issue.getStatus().getNameTranslation(i18nHelper);
for ( String group : groups )
{
data.addValue(TimeDiffInHours(until, since), currentStatus, grouper.getResolvedValue(group, issue));
}
}
} catch (Exception e)
{
logger.error("Could not compute time in status", e);
throw new RuntimeException(e);
}
data.fillMissingValues();
def chartData = chartBuilder.newChartData(i18nHelper.getText("xchart.charts.time"));
chartData.setType(ChartType.BAR.getKey());
chartData.addCustomData("tooltip", "formatTooltipAsHoursWithDays");
chartData.setYType(i18nHelper.getText("xchart.charts.time"));
List<String> statusOrder = new LinkedList<String>(data.keySet());
statusOrder.sort(new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
Status ss1 = constantsManager.getStatusByTranslatedName(o1);
if ( ss1 != null )
{
Status ss2 = constantsManager.getStatusByTranslatedName(o2);
if ( ss2 != null )
{
Long s1 = ss1.getSequence();
Long s2 = ss2.getSequence();
return s1.compareTo(s2);
}
}
return o1.compareToIgnoreCase(o2);
}
});
chartBuilder.getChartUtil().transformResultOrdered(data, chartData, true, statusOrder.toArray(new String[0]));
return chartData; |