001    package org.hackystat.projectbrowser.page.dailyprojectdata.coverage;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005    import java.util.List;
006    import java.util.logging.Logger;
007    
008    import org.hackystat.dailyprojectdata.resource.coverage.jaxb.ConstructData;
009    import org.hackystat.projectbrowser.ProjectBrowserApplication;
010    import org.hackystat.projectbrowser.page.dailyprojectdata.detailspanel.DailyProjectDetailsPanel;
011    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
012    import org.hackystat.utilities.stacktrace.StackTrace;
013    
014    /**
015     * Data structure for representing coverage information about a single project. 
016     * This representation includes the Project, plus the number of classes in the project with 
017     * coverage in each of five buckets: 0-20%, 21-40%, 41-60%, 61-80%, and 81-100%.
018     * 
019     * @author Philip Johnson
020     * @author Shaoxuan Zhang
021     */
022    public class CoverageData implements Serializable {
023    
024      /** Support serialization. */
025      private static final long serialVersionUID = 1L;
026      
027      /** The project whose data is kept in this instance. */
028      private Project project;
029      
030      /** The five buckets for this data. */
031      private List<List<ConstructData>> buckets = new ArrayList<List<ConstructData>>();
032      
033      /** The total number of entries added across all buckets. */
034      private int total = 0;
035      
036      /**
037       * Creates a new CoverageData instance and initializes the buckets to zero.  
038       * @param name The name of the Project associated with this instance. 
039       */
040      public CoverageData(Project name) {
041        this.project = name;
042        for (int i = 0; i < 5; i++) {
043          buckets.add(new ArrayList<ConstructData>());
044        }
045      }
046      
047      /**
048       * Increments the given bucket by 1. 
049       * @param bucket The bucket number.
050       * @param data The Construct Data.  
051       */
052      private void incrementBucket(int bucket, ConstructData data) {
053        buckets.get(bucket).add(data);
054        this.total++;
055      }
056      
057      /**
058       * Updates this CoverageData instance with information about the covered/uncovered information
059       * for a given instance in the Project.  
060       * @param data The construct data. 
061       */
062      public void addEntry(ConstructData data) {
063        
064        int numCovered = data.getNumCovered();
065        int numUncovered = data.getNumUncovered();
066        // If no method level coverage, ignore.
067        if ((numCovered == 0) && (numUncovered == 0)) {
068          return;
069        }
070        try {
071          double percent = (double)numCovered / (double)(numCovered + numUncovered);
072          if (percent <= 0.20) {
073            incrementBucket(0, data);
074          }
075          else if (percent <= 0.40) {
076            incrementBucket(1, data);
077          }
078          else if (percent <= 0.60) {
079            incrementBucket(2, data);
080          }
081          else if (percent <= 0.80) {
082            incrementBucket(3, data);
083          }
084          else {
085            incrementBucket(4, data);
086          }
087        }
088        catch (Exception e) {
089          Logger logger = ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger();
090          logger.info("Error adding an entry to Coverage DPD: " + StackTrace.toString(e));
091        }
092      }
093      
094      /**
095       * Returns the current value of the specified bucket. 
096       * @param bucket The bucket number, where 0 is the first one and 4 is the last one. 
097       * @return The value inside the given bucket. 
098       */
099      public int getBucketValue(int bucket) {
100        return buckets.get(bucket).size();
101      }
102      
103      /**
104       * Returns the total number of entries across all buckets. 
105       * @return The total number of entries. 
106       */
107      public int getTotal() {
108        return this.total;
109      }
110      
111      /**
112       * Returns the total number of entries across all buckets as a string. 
113       * @return The total number of entries. 
114       */
115      public String getTotalString() {
116        return String.valueOf(this.total);
117      }
118      
119      /**
120       * Returns the bucket value as a percentage of the total number of entries across all buckets.
121       * Returns zero if there are no entries. 
122       * @param bucket The bucket whose percentage is to be returned.
123       * @return The bucket as a percentage.
124       */
125      public int getBucketPercentage(int bucket) {
126        if (getTotal() == 0) {
127          return 0;
128        }
129        else {
130          double percent = (double)getBucketValue(bucket) / (double)getTotal();
131          return ((int) (percent * 100));
132        }
133      }
134        
135      /**
136       * Returns the current value of the specified bucket as a string. 
137       * @param bucket The bucket number, where 0 is the first one and 4 is the last one. 
138       * @return The value inside the given bucket. 
139       */
140      public String getBucketCountString(int bucket) {
141        return String.valueOf(getBucketValue(bucket));
142      }
143      
144      /**
145       * Returns the bucket percentage as a string.
146       * @param bucket The bucket.
147       * @return Its percentage as a string.
148       */
149      public String getBucketPercentageString(int bucket) {
150        return getBucketPercentage(bucket) + "%";
151      }
152      
153     
154      /**
155       * Return the project associated with this data. 
156       * @return The project.
157       */
158      public Project getProject() {
159        return project;
160      }
161      
162      /**
163       * Returns a details panel containing information about this bucket.
164       * @param id The wicket id for this panel.
165       * @param bucket The bucket of interest. 
166       * @param isCount True if the count should be returned, false if percentage. 
167       * @return The DailyProjectDetailsPanel instance. 
168       */
169      public DailyProjectDetailsPanel getPanel(String id, int bucket, boolean isCount) {
170        DailyProjectDetailsPanel dpdPanel = 
171          new DailyProjectDetailsPanel(id, "Coverage Data", 
172              ((isCount) ? this.getBucketCountString(bucket) : this.getBucketPercentageString(bucket)));
173        dpdPanel.getModalWindow().setContent(
174            new CoverageDetailsPanel(dpdPanel.getModalWindow().getContentId(),
175            buckets.get(bucket)));
176            
177        return dpdPanel;
178      }
179    }