package hudson.plugins.cppncss.parser; import hudson.model.AbstractBuild; import hudson.util.IOException2; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.*; import java.util.*; /** * TODO javadoc. * * @author Stephen Connolly * @author Shaohua Wen * @since 25-Feb-2008 21:33:40 */ public class Statistic implements Serializable { // ------------------------------ FIELDS ------------------------------ private AbstractBuild<?, ?> owner; private String name; private long functions; private long ncss; private long ccn; private String parentElement; // -------------------------- STATIC METHODS -------------------------- public static StatisticsResult parse(File inFile) throws IOException, XmlPullParserException { StatisticsResult result = new StatisticsResult(); Collection<Statistic> fileResults = new ArrayList<Statistic>(); Collection<Statistic> functionResults = new ArrayList<Statistic>(); FileInputStream fis = null; BufferedInputStream bis = null; try { fis = new FileInputStream(inFile); bis = new BufferedInputStream(fis); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); XmlPullParser parser = factory.newPullParser(); parser.setInput(bis, null); // check that the first tag is <cppncss> expectNextTag(parser, "cppncss"); // skip until we get to the <measure> tag while (parser.getDepth() > 0 && (parser.getEventType() != XmlPullParser.START_TAG || !"measure".equals(parser.getName()))) { parser.next(); } int depth = parser.getDepth(); //skip until we get to <item> tag while(parser.getDepth() > 1 && (parser.getEventType() != XmlPullParser.START_TAG || !"item".equals(parser.getName()))) { parser.next(); } while(parser.getDepth() >= depth) { if(parser.getDepth() == 3 && parser.getEventType() == XmlPullParser.START_TAG && "item".equals(parser.getName())){ String functionName = parser.getAttributeValue(0); Map<String, String> data = new HashMap<String, String>(); data.put("name", functionName); String[] functionValueNames = {"Nr.","NCSS","CCN"}; int subIndex = 0; String lastTag = null; String lastText = null; while (parser.getDepth() >= 3) { parser.next(); switch (parser.getEventType()) { case XmlPullParser.START_TAG: lastTag = parser.getName(); break; case XmlPullParser.TEXT: lastText = parser.getText(); break; case XmlPullParser.END_TAG: subIndex ++; if (parser.getDepth() == 4 && lastTag != null && lastText != null) { data.put(functionValueNames[subIndex - 1 ], lastText); } lastTag = null; lastText = null; break; } } Statistic s = new Statistic(data.get("name")); if(data.get("name").indexOf(" at ") > 0){ String fileStr = data.get("name").substring(data.get("name").indexOf(" at ")+4); String file = fileStr.substring(0,fileStr.lastIndexOf(":")); s.setParentElement(file); } s.setNcss(Long.valueOf(data.get(functionValueNames[1]))); s.setCcn(Long.valueOf(data.get(functionValueNames[2]))); functionResults.add(s); } parser.next(); } // skip until we get to the <measure> tag while (parser.getDepth() > 0 && (parser.getEventType() != XmlPullParser.START_TAG || !"measure".equals(parser.getName()))) { parser.next(); } //skip until we get to <item> tag while(parser.getDepth() > 1 && (parser.getEventType() != XmlPullParser.START_TAG || !"item".equals(parser.getName()))) { parser.next(); } depth = parser.getDepth(); while(parser.getDepth() >= depth) { if(parser.getDepth() == 3 && parser.getEventType() == XmlPullParser.START_TAG && "item".equals(parser.getName())){ String fileName = parser.getAttributeValue(0); Map<String, String> data = new HashMap<String, String>(); data.put("name", fileName); String[] fileValueNames = {"Nr.","NCSS","CCN","Functions"}; int subIndex = 0; String lastTag = null; String lastText = null; while (parser.getDepth() >= 3) { parser.next(); switch (parser.getEventType()) { case XmlPullParser.START_TAG: lastTag = parser.getName(); break; case XmlPullParser.TEXT: lastText = parser.getText(); break; case XmlPullParser.END_TAG: subIndex ++; if (parser.getDepth() == 4 && lastTag != null && lastText != null) { data.put(fileValueNames[subIndex - 1 ], lastText); } lastTag = null; lastText = null; break; } } Statistic s = new Statistic(data.get("name")); s.setNcss(Long.valueOf(data.get(fileValueNames[1]))); s.setCcn(Long.valueOf(data.get(fileValueNames[2]))); s.setFunctions(Long.valueOf(data.get(fileValueNames[3]))); fileResults.add(s); } parser.next(); } } catch (XmlPullParserException e) { throw new IOException2(e); } finally { if (bis != null) { bis.close(); } if (fis != null) { fis.close(); } } result.setFunctionResults(functionResults); result.setFileResults(fileResults); return result; } private static boolean skipToTag(XmlPullParser parser, String tagName) throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() == XmlPullParser.END_TAG) { return false; } if (parser.getEventType() != XmlPullParser.START_TAG) { parser.next(); continue; } if (parser.getName().equals(tagName)) { return true; } skipTag(parser); } } private static void skipTag(XmlPullParser parser) throws IOException, XmlPullParserException { parser.next(); endElement(parser); } private static void expectNextTag(XmlPullParser parser, String tag) throws IOException, XmlPullParserException { while (true) { if (parser.getEventType() != XmlPullParser.START_TAG) { parser.next(); continue; } if (parser.getName().equals(tag)) { return; } throw new IOException("Expecting tag " + tag); } } private static void endElement(XmlPullParser parser) throws IOException, XmlPullParserException { int depth = parser.getDepth(); while (parser.getDepth() >= depth) { parser.next(); } } public static Statistic total(Collection<Statistic>... results) { Collection<Statistic> merged = merge(results); Statistic total = new Statistic(""); for (Statistic individual : merged) { total.add(individual); } return total; } public void add(Statistic r) { functions += r.functions; ncss += r.ncss; ccn += r.ccn; } public static Collection<Statistic> merge(Collection<Statistic>... results) { Collection<Statistic> newResults = new ArrayList<Statistic>(); if (results.length == 0) { return Collections.emptySet(); } else if (results.length == 1) { return results[0]; } else { List<String> indivNames = new ArrayList<String>(); for (Collection<Statistic> result : results) { for (Statistic individual : result) { if (!indivNames.contains(individual.name)) { indivNames.add(individual.name); } } } for (String indivName : indivNames) { Statistic indivStat = new Statistic(indivName); for (Collection<Statistic> result : results) { for (Statistic individual : result) { if (indivName.equals(individual.name)) { indivStat.add(individual); } } } newResults.add(indivStat); } return newResults; } } // --------------------------- CONSTRUCTORS --------------------------- public Statistic(String name) { this.name = name; } // --------------------- GETTER / SETTER METHODS --------------------- public void setCcn(long ccn) { this.ccn = ccn; } public long getCcn() { return ccn; } public long getFunctions() { return functions; } public void setFunctions(long functions) { this.functions = functions; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getNcss() { return ncss; } public void setNcss(long ncss) { this.ncss = ncss; } public AbstractBuild<?, ?> getOwner() { return owner; } public void setOwner(AbstractBuild<?, ?> owner) { this.owner = owner; } public void setParentElement(String parentElement) { this.parentElement = parentElement; } public String getParentElement(){ return parentElement; } // ------------------------ CANONICAL METHODS ------------------------ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Statistic statistic = (Statistic) o; if (ccn != statistic.ccn) return false; if (functions != statistic.functions) return false; if (ncss != statistic.ncss) return false; if (!name.equals(statistic.name)) return false; if (owner != null ? !owner.equals(statistic.owner) : statistic.owner != null) return false; return true; } public int hashCode() { int result; result = (owner != null ? owner.hashCode() : 0); result = 31 * result + name.hashCode(); return result; } public String toString() { return "Statistic{" + "name='" + name + '\'' + ", ccn=" + ccn + ", functions=" + functions + ", ncss=" + ncss + '}'; } public String toSummary() { return "<ul>" + diff(0, ccn, "ccn") + diff(0, functions, "functions") + diff(0, ncss, "ncss") + "</ul>"; } private static String diff(long a, long b, String name) { if (a == b) { return ""; } else if (a < b) { return "<li>" + name + " (+" + (b - a) + ")</li>"; } else { // if (a < b) return "<li>" + name + " (-" + (a - b) + ")</li>"; } } public String toSummary(Statistic totals) { return "<ul>" + diff(totals.ccn, ccn, "ccn") + diff(totals.functions, functions, "functions") + diff(totals.ncss, ncss, "ncss") + "</ul>"; } public void set(Statistic that) { this.name = that.name; this.ccn = that.ccn; this.functions = that.functions; this.ncss = that.ncss; } }