001    package org.hackystat.telemetry.analyzer.reducer.impl;
002    
003    import java.util.List;
004    
005    import org.hackystat.dailyprojectdata.client.DailyProjectDataClient;
006    import org.hackystat.dailyprojectdata.resource.issue.jaxb.IssueDailyProjectData;
007    import org.hackystat.dailyprojectdata.resource.issue.jaxb.IssueData;
008    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
009    import org.hackystat.telemetry.analyzer.model.TelemetryDataPoint;
010    import org.hackystat.telemetry.analyzer.model.TelemetryStream;
011    import org.hackystat.telemetry.analyzer.model.TelemetryStreamCollection;
012    import org.hackystat.telemetry.analyzer.reducer.TelemetryReducer;
013    import org.hackystat.telemetry.analyzer.reducer.TelemetryReducerException;
014    import org.hackystat.telemetry.analyzer.reducer.util.IntervalUtility;
015    import org.hackystat.telemetry.service.server.ServerProperties;
016    import org.hackystat.utilities.time.interval.Interval;
017    import org.hackystat.utilities.time.period.Day;
018    import org.hackystat.utilities.tstamp.Tstamp;
019    
020    
021    /**
022     * Returns a single stream providing Issue counts.
023     * <p>
024     * Options:
025     * <ol>
026     * <li> member: The project member whose commit counts are to be returned, or "*" for all members.
027     * </ol>
028     * 
029     * @author Shaoxuan Zhang, Philip Johnson
030     */
031    public class IssueReducer implements TelemetryReducer { 
032     
033      /**
034       * Computes and returns the required telemetry streams object.
035       *
036       * @param project The project.
037       * @param dpdClient The DPD Client.
038       * @param interval The interval.
039       * @param options The optional parameters.
040       *
041       * @return Telemetry stream collection.
042       * @throws TelemetryReducerException If there is any error.
043       */
044      public TelemetryStreamCollection compute(Project project, DailyProjectDataClient dpdClient, 
045          Interval interval, String[] options) throws TelemetryReducerException {
046        String member = null;
047        String issueStatus = null;
048        //process options
049        if (options.length > 2) {
050          throw new TelemetryReducerException("Commit reducer takes 1 optional parameters.");
051        }
052        if (options.length >= 1) {
053          member = options[0];
054        }
055    
056        if (options.length >= 2) {
057          issueStatus = options[1];
058        }
059        
060        // Find out the DailyProjectData host, throw error if not found.
061        String dpdHost = System.getProperty(ServerProperties.DAILYPROJECTDATA_FULLHOST_KEY);
062        if (dpdHost == null) {
063          throw new TelemetryReducerException("Null DPD host in CommitReducer");
064        }
065    
066        // now get the telemetry stream. 
067        try {
068          TelemetryStream telemetryStream = this.getIssueStream(dpdClient, project, interval,  
069              member, issueStatus, null);
070          TelemetryStreamCollection streams = new TelemetryStreamCollection(null, project, interval);
071          streams.add(telemetryStream);
072          return streams;
073        } 
074        catch (Exception e) {
075          throw new TelemetryReducerException(e);
076        }
077      }
078    
079      /**
080       * Gets the issue telemetry stream.
081       * 
082       * @param dpdClient The DailyProjectData client we will contact for the data. 
083       * @param project The project.
084       * @param interval The interval.
085       * @param member The member, or "*" for all members.
086       * @param streamTagValue The tag for the generated telemetry stream.
087       * @param issueStatus the status of the issues to be counted.
088       * 
089       * @return The telemetry stream as required.
090       * 
091       * @throws Exception If there is any error.
092       */
093      TelemetryStream getIssueStream(DailyProjectDataClient dpdClient, 
094          Project project, Interval interval, String member, String issueStatus, Object streamTagValue) 
095            throws Exception {
096        TelemetryStream telemetryStream = new TelemetryStream(streamTagValue);
097        List<IntervalUtility.Period> periods = IntervalUtility.getPeriods(interval);
098        
099        for (IntervalUtility.Period period : periods) {
100          Long value = this.getIssuesData(dpdClient, project, period.getStartDay(), period.getEndDay(),
101              member, issueStatus);
102          telemetryStream.addDataPoint(new TelemetryDataPoint(period.getTimePeriod(), value));
103        }
104        return telemetryStream;
105      }
106      
107      /**
108       * Returns a Issue value for the specified time interval, or null if no SensorData. 
109       * 
110       * @param dpdClient The DailyProjectData client we will use to get this data. 
111       * @param project The project.
112       * @param startDay The start day (inclusive).
113       * @param endDay The end day (inclusive).
114       * @param member The member email, or "*" for all members.
115       * @param issueStatus The status of the issue, open or closed.
116       * @throws TelemetryReducerException If anything goes wrong.
117       *
118       * @return The UnitTest count, or null if there is no UnitTest SensorData for that time period. 
119       */
120      Long getIssuesData(DailyProjectDataClient dpdClient, Project project, Day startDay, Day endDay, 
121          String member, String issueStatus) throws TelemetryReducerException {
122        try {
123          IssueDailyProjectData data = 
124            dpdClient.getIssue(project.getOwner(), project.getName(), 
125                Tstamp.makeTimestamp(endDay), issueStatus);
126          if (member == null || "*".equals(member)) {
127            return Long.valueOf(data.getIssueData().size());
128          }
129          else {
130            Long count = 0L;
131            for (IssueData issueData : data.getIssueData()) {
132              if (member.equals(issueData.getOwner())) {
133                count++;
134              }
135            }
136            return count;
137          }
138        }
139        catch (Exception ex) {
140          throw new TelemetryReducerException(ex);
141        }
142    
143      }
144    
145    }