| 1 | |
package net.sf.statcvs.reports; |
| 2 | |
|
| 3 | |
import java.util.Iterator; |
| 4 | |
import java.util.List; |
| 5 | |
import java.util.TreeMap; |
| 6 | |
import java.util.regex.Matcher; |
| 7 | |
import java.util.regex.Pattern; |
| 8 | |
|
| 9 | |
import net.sf.statcvs.Messages; |
| 10 | |
import net.sf.statcvs.model.Commit; |
| 11 | |
import net.sf.statcvs.model.Repository; |
| 12 | |
import net.sf.statcvs.output.ConfigurationOptions; |
| 13 | |
import net.sf.statcvs.output.ReportConfig; |
| 14 | |
import net.sf.statcvs.reportmodel.IntegerColumn; |
| 15 | |
import net.sf.statcvs.reportmodel.SimpleTextColumn; |
| 16 | |
import net.sf.statcvs.reportmodel.Table; |
| 17 | |
import net.sf.statcvs.util.IntegerMap; |
| 18 | |
|
| 19 | |
|
| 20 | |
|
| 21 | |
|
| 22 | |
|
| 23 | |
|
| 24 | |
|
| 25 | |
public class CloudCommitTableReport implements TableReport { |
| 26 | |
private static final String ENGLISH_EXCLUSIONS = "\\d+|an|the|me|my|we|you|he|she|it|are|is|am|will|shall|should|would|had|have|has|was|were|be|been|this|that|there|" |
| 27 | |
+ "|who|when|how|where|which|already|after|by|on|or|so|some|commit|also|got|get|do|don't|from|all|but|yet|to|in|does|doesn't" |
| 28 | |
+ "out|of|for|if|yes|no|not|may|might|can|could|at|as|with|without|some|more|lot|lots|than|then|adding|added|work|they|used|still|show|must|into|same"; |
| 29 | 0 | private Table table = null; |
| 30 | |
private final ReportConfig config; |
| 31 | |
private final Repository content; |
| 32 | 0 | private final IntegerMap cloudMap = new IntegerMap(); |
| 33 | |
private Pattern excluded; |
| 34 | |
|
| 35 | |
|
| 36 | |
|
| 37 | |
|
| 38 | |
|
| 39 | |
|
| 40 | 0 | public CloudCommitTableReport(final ReportConfig config) { |
| 41 | 0 | content = config.getRepository(); |
| 42 | 0 | this.config = config; |
| 43 | 0 | } |
| 44 | |
|
| 45 | |
|
| 46 | |
|
| 47 | |
|
| 48 | |
public void calculate() { |
| 49 | 0 | if (this.table != null) { |
| 50 | 0 | return; |
| 51 | |
} |
| 52 | 0 | if (excluded == null) { |
| 53 | 0 | excluded = Pattern.compile(ConfigurationOptions.getConfigStringProperty("cloud.exclusionRegExp", ENGLISH_EXCLUSIONS), Pattern.CASE_INSENSITIVE); |
| 54 | |
} |
| 55 | 0 | final String summary = Messages.getString("CLOUD_TABLE_TITLE"); |
| 56 | 0 | table = new Table(summary); |
| 57 | 0 | final SimpleTextColumn wordColumn = new SimpleTextColumn(Messages.getString("CLOUD_WORD_COL")); |
| 58 | 0 | final IntegerColumn frequencyColumn = new IntegerColumn(Messages.getString("CLOUD_COUNT_COL")); |
| 59 | 0 | frequencyColumn.setShowPercentages(true); |
| 60 | 0 | table.addColumn(wordColumn); |
| 61 | 0 | table.addColumn(frequencyColumn); |
| 62 | 0 | table.setKeysInFirstColumn(true); |
| 63 | |
|
| 64 | 0 | calculate(content.getCommits()); |
| 65 | 0 | int lines = 0; |
| 66 | 0 | final Integer minFrequency = ConfigurationOptions.getConfigIntegerProperty("cloud.minFrequency", new Integer(5)); |
| 67 | 0 | final Integer maxNumbers = ConfigurationOptions.getConfigIntegerProperty("cloud.maxWordNumberInTable", new Integer(50)); |
| 68 | 0 | final Iterator it = cloudMap.iteratorSortedByValueReverse(); |
| 69 | 0 | double maxFreq = -1; |
| 70 | 0 | while (it.hasNext()) { |
| 71 | 0 | final String word = (String) it.next(); |
| 72 | 0 | final int frequency = cloudMap.get(word); |
| 73 | |
|
| 74 | 0 | if (maxFreq < 0) { |
| 75 | 0 | maxFreq = Math.log(frequency); |
| 76 | |
} |
| 77 | |
|
| 78 | 0 | if (frequency < minFrequency.intValue()) { |
| 79 | 0 | break; |
| 80 | |
} |
| 81 | |
|
| 82 | |
|
| 83 | |
|
| 84 | 0 | wordColumn.addValue(word); |
| 85 | 0 | frequencyColumn.addValue(frequency); |
| 86 | 0 | lines++; |
| 87 | 0 | if (lines >= maxNumbers.intValue()) { |
| 88 | 0 | break; |
| 89 | |
} |
| 90 | 0 | } |
| 91 | |
|
| 92 | 0 | } |
| 93 | |
|
| 94 | |
private void calculate(final List commits) { |
| 95 | 0 | final Iterator it = commits.iterator(); |
| 96 | 0 | final Integer minSize = ConfigurationOptions.getConfigIntegerProperty("cloud.minLengthForWord", new Integer(4)); |
| 97 | 0 | while (it.hasNext()) { |
| 98 | 0 | final Commit commit = (Commit) it.next(); |
| 99 | 0 | if (commit.getAuthor() == null || !this.config.isDeveloper(commit.getAuthor())) { |
| 100 | 0 | continue; |
| 101 | |
} |
| 102 | |
|
| 103 | 0 | final String comment = commit.getComment(); |
| 104 | |
|
| 105 | 0 | if (comment != null && comment.length() > minSize.intValue()) { |
| 106 | 0 | final String[] split = comment.split("\\W+"); |
| 107 | 0 | for (int i = 0; i < split.length; i++) { |
| 108 | 0 | final String word = split[i]; |
| 109 | 0 | if (word != null && word.length() >= minSize.intValue()) { |
| 110 | |
|
| 111 | 0 | tryToAdd(word.toLowerCase()); |
| 112 | |
} |
| 113 | |
} |
| 114 | |
} |
| 115 | 0 | } |
| 116 | |
|
| 117 | 0 | } |
| 118 | |
|
| 119 | |
private void tryToAdd(final String word) { |
| 120 | 0 | final Matcher m = excluded.matcher(word); |
| 121 | 0 | if (m.matches()) { |
| 122 | 0 | return; |
| 123 | |
} |
| 124 | 0 | mergeIfRequired(word, "ed", 1); |
| 125 | 0 | mergeIfRequired(word, "ing", 3); |
| 126 | 0 | mergeIfRequired(word, "es", 1); |
| 127 | 0 | mergeIfRequired(word, "s", 1); |
| 128 | |
|
| 129 | |
|
| 130 | |
|
| 131 | 0 | } |
| 132 | |
|
| 133 | |
private void mergeIfRequired(final String word, final String suffix, final int toRemove) { |
| 134 | |
|
| 135 | 0 | cloudMap.addInt(word, 1); |
| 136 | |
|
| 137 | 0 | if (word.endsWith(suffix)) { |
| 138 | 0 | final String chopped = word.substring(0, word.length() - toRemove); |
| 139 | 0 | if (cloudMap.contains(chopped)) { |
| 140 | 0 | cloudMap.addInt(chopped, cloudMap.get(word)); |
| 141 | 0 | cloudMap.remove(word); |
| 142 | |
} |
| 143 | |
} |
| 144 | 0 | } |
| 145 | |
|
| 146 | |
|
| 147 | |
|
| 148 | |
|
| 149 | |
public Table getTable() { |
| 150 | 0 | return table; |
| 151 | |
} |
| 152 | |
|
| 153 | |
public String getRawContent() { |
| 154 | 0 | final StringBuffer buffer = new StringBuffer(); |
| 155 | 0 | buffer.append("<p>"); |
| 156 | |
|
| 157 | 0 | int lines = 0; |
| 158 | 0 | final Iterator it = cloudMap.iteratorSortedByValueReverse(); |
| 159 | 0 | final Integer minFrequency = ConfigurationOptions.getConfigIntegerProperty("cloud.minFrequency", new Integer(5)); |
| 160 | 0 | final Integer maxNumbers = ConfigurationOptions.getConfigIntegerProperty("cloud.maxWordNumberInCloud", new Integer(100)); |
| 161 | 0 | double maxFreq = -1; |
| 162 | 0 | final TreeMap tm = new TreeMap(); |
| 163 | 0 | while (it.hasNext()) { |
| 164 | 0 | final String word = (String) it.next(); |
| 165 | 0 | final int frequency = cloudMap.get(word); |
| 166 | |
|
| 167 | 0 | if (maxFreq < 0) { |
| 168 | 0 | maxFreq = Math.log(frequency); |
| 169 | |
} |
| 170 | |
|
| 171 | 0 | if (frequency < minFrequency.intValue()) { |
| 172 | 0 | break; |
| 173 | |
} |
| 174 | |
|
| 175 | 0 | final long fontSize = Math.round(Math.min(-2 + Math.log(frequency) * 10 / maxFreq, 8)); |
| 176 | |
|
| 177 | |
|
| 178 | |
|
| 179 | 0 | final StringBuffer buffer1 = new StringBuffer(); |
| 180 | 0 | buffer1.append("<font size=\"").append(fontSize).append("\">").append(word).append(" </font> "); |
| 181 | 0 | tm.put(word, buffer1.toString()); |
| 182 | |
|
| 183 | 0 | lines++; |
| 184 | 0 | if (lines >= maxNumbers.intValue()) { |
| 185 | 0 | break; |
| 186 | |
} |
| 187 | 0 | } |
| 188 | |
|
| 189 | 0 | final Iterator it2 = tm.values().iterator(); |
| 190 | 0 | while (it2.hasNext()) { |
| 191 | 0 | buffer.append(it2.next()); |
| 192 | |
} |
| 193 | |
|
| 194 | 0 | buffer.append("</p>"); |
| 195 | 0 | return buffer.toString(); |
| 196 | |
} |
| 197 | |
} |