001 package org.hackystat.projectbrowser.page.dailyprojectdata.complexity; 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.projectbrowser.ProjectBrowserApplication; 009 import org.hackystat.projectbrowser.page.dailyprojectdata.detailspanel.DailyProjectDetailsPanel; 010 import org.hackystat.sensorbase.resource.projects.jaxb.Project; 011 import org.hackystat.utilities.stacktrace.StackTrace; 012 import org.hackystat.dailyprojectdata.resource.complexity.jaxb.FileData; 013 014 /** 015 * Data structure for representing complexity information about a single project. 016 * This representation includes the Project, plus the number of methods in the project with 017 * complexity in each of five buckets: 0-10, 11-20, 21-30, 31-40, and 41+ 018 * 019 * @author Philip Johnson 020 * @author Shaoxuan Zhang 021 */ 022 public class ComplexityData 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<FileData>> buckets = new ArrayList<List<FileData>>(); 032 033 /** The total number of entries added across all buckets. */ 034 private int total = 0; 035 036 /** 037 * Creates a new complexityData instance. 038 * @param name The name of the Project associated with this instance. 039 */ 040 public ComplexityData(Project name) { 041 this.project = name; 042 for (int i = 0; i < 5; i++) { 043 buckets.add(new ArrayList<FileData>()); 044 } 045 } 046 047 048 /** 049 * Adds the complexity data in this FileData instance to the appropriate buckets. 050 * @param data The FileData. 051 */ 052 public void addEntry(FileData data) { 053 String methodData = data.getComplexityValues(); 054 List<Integer> complexities = getComplexities(methodData); 055 for (Integer complexity : complexities) { 056 addEntry(complexity, data); 057 this.total++; 058 } 059 } 060 061 /** 062 * Updates this ComplexityData instance with information about the number of complexitys for 063 * a specific class. 064 * @param complexityCount The number of complexitys. 065 * @param data The FileData containing this complexity count. 066 */ 067 public void addEntry(int complexityCount, FileData data) { 068 try { 069 if (complexityCount <= 5) { 070 buckets.get(0).add(data); 071 } 072 else if (complexityCount <= 10) { 073 buckets.get(1).add(data); 074 } 075 else if (complexityCount <= 15) { 076 buckets.get(2).add(data); 077 } 078 else if (complexityCount <= 20) { 079 buckets.get(3).add(data); 080 } 081 else { 082 buckets.get(4).add(data); 083 } 084 } 085 catch (Exception e) { 086 Logger logger = ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger(); 087 logger.info("Error adding an entry to complexity DPD: " + StackTrace.toString(e)); 088 } 089 } 090 091 /** 092 * Returns the current value of the specified bucket. 093 * @param bucket The bucket number, where 0 is the first one and 4 is the last one. 094 * @return The value inside the given bucket. 095 */ 096 public int getBucketValue(int bucket) { 097 return buckets.get(bucket).size(); 098 } 099 100 /** 101 * Returns the total number of entries across all buckets. 102 * @return The total number of entries. 103 */ 104 public int getTotal() { 105 return this.total; 106 } 107 108 /** 109 * Returns the total number of entries across all buckets as a string. 110 * @return The total number of entries. 111 */ 112 public String getTotalString() { 113 return String.valueOf(this.total); 114 } 115 116 /** 117 * Returns the bucket value as a percentage of the total number of entries across all buckets. 118 * @param bucket The bucket whose percentage is to be returned. 119 * @return The bucket as a percentage. 120 */ 121 public int getBucketPercentage(int bucket) { 122 if (getTotal() == 0) { 123 return 0; 124 } 125 else { 126 double percent = (double)getBucketValue(bucket) / (double)getTotal(); 127 return ((int) (percent * 100)); 128 } 129 } 130 131 /** 132 * Returns the current value of the specified bucket as a string. 133 * @param bucket The bucket number, where 0 is the first one and 4 is the last one. 134 * @return The value inside the given bucket. 135 */ 136 public String getBucketCountString(int bucket) { 137 return String.valueOf(getBucketValue(bucket)); 138 } 139 140 /** 141 * Returns the bucket percentage as a string. 142 * @param bucket The bucket. 143 * @return Its percentage as a string. 144 */ 145 public String getBucketPercentageString(int bucket) { 146 return getBucketPercentage(bucket) + "%"; 147 } 148 149 150 /** 151 * Return the project associated with this data. 152 * @return The project. 153 */ 154 public Project getProject() { 155 return project; 156 } 157 158 /** 159 * Returns a details panel containing information about this bucket. 160 * @param id The wicket id for this panel. 161 * @param bucket The bucket of interest. 162 * @param isCount True if the count should be returned, false if percentage. 163 * @return The DailyProjectDetailsPanel instance. 164 */ 165 public DailyProjectDetailsPanel getPanel(String id, int bucket, boolean isCount) { 166 DailyProjectDetailsPanel dpdPanel = 167 new DailyProjectDetailsPanel(id, "Complexity Data", 168 ((isCount) ? this.getBucketCountString(bucket) : this.getBucketPercentageString(bucket))); 169 dpdPanel.getModalWindow().setContent( 170 new ComplexityDetailsPanel(dpdPanel.getModalWindow().getContentId(), 171 buckets.get(bucket))); 172 173 return dpdPanel; 174 } 175 176 177 /** 178 * Takes the string containing method complexities and returns them as a List of Integers. 179 * This really should go into the DPD system. 180 * @param methodData The method data as a string. 181 * @return The method data as a list of integers. 182 */ 183 private List<Integer> getComplexities(String methodData) { 184 List<Integer> methodComplexities = new ArrayList<Integer>(); 185 try { 186 String[] numStringList = methodData.split(","); 187 for (String numString : numStringList) { 188 methodComplexities.add(Integer.parseInt(numString)); 189 } 190 } 191 catch (Exception e) { 192 Logger logger = ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger(); 193 logger.info("Failed to parse Complexity method data: " + methodData); 194 } 195 return methodComplexities; 196 } 197 }