package com.schneide.crap4j.reader;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import com.schneide.crap4j.crap.GenericCrapData;
import com.schneide.crap4j.crap.MethodCrapManager;
import com.schneide.crap4j.reader.model.ICrapDetails;
import com.schneide.crap4j.reader.model.ICrapReport;
import com.schneide.crap4j.reader.model.IMethod;
import com.schneide.crap4j.reader.model.IMethodCrapData;
import com.schneide.crap4j.reader.model.IOverallStatistics;
import com.schneide.crap4j.reader.util.NumericalParser;
public class ReportReader {
private final Reader reportData;
private final MethodCrapManager methodCrapManager;
private ParsedCrapReport parsedData;
public ReportReader(Reader reportData) {
super();
this.reportData = reportData;
this.methodCrapManager = new MethodCrapManager();
this.parsedData = null;
}
private class ParsedCrapReport implements ICrapReport {
private final ParsedCrap4JData data;
private final ParsedStatistics statistics;
public ParsedCrapReport(
ParsedStatistics statistics,
ParsedCrap4JData data) {
super();
this.statistics = statistics;
this.data = data;
}
//@Override
public ICrapDetails getDetails() {
return this.data;
}
//@Override
public IOverallStatistics getStatistics() {
return this.statistics;
}
}
private class ParsedStatistics implements IOverallStatistics {
private final String name;
private final int methodCount;
private final int crapMethodCount;
private final int crapLoad;
private final double totalCrap;
private final double crapMethodPercent;
public ParsedStatistics(
String name,
int methodCount,
int crapMethodCount,
int crapLoad,
double totalCrap,
double crapMethodPercent) {
super();
this.name = name;
this.methodCount = methodCount;
this.crapMethodCount = crapMethodCount;
this.crapLoad = crapLoad;
this.totalCrap = totalCrap;
this.crapMethodPercent = crapMethodPercent;
}
//@Override
public int getCrapLoad() {
return this.crapLoad;
}
//@Override
public int getCrapMethodCount() {
return this.crapMethodCount;
}
//@Override
public double getCrapMethodPercent() {
return this.crapMethodPercent;
}
//@Override
public int getMethodCount() {
return this.methodCount;
}
//@Override
public String getName() {
return this.name;
}
//@Override
public double getTotalCrap() {
return this.totalCrap;
}
}
private class ParsedCrap4JData implements ICrapDetails {
public ParsedCrap4JData() {
super();
}
//@Override
public MethodCrapManager getMethodCrapManager() {
return ReportReader.this.methodCrapManager;
}
}
public synchronized ICrapReport parseData() throws IOException {
if (null != this.parsedData) {
return this.parsedData;
}
try {
SAXBuilder saxBuilder = new SAXBuilder(false);
Document build = saxBuilder.build(this.reportData);
Element rootElement = build.getRootElement();
ParsedStatistics statistics = parseStatistics(rootElement);
ParsedCrap4JData details = parseDetails(rootElement);
this.parsedData = new ParsedCrapReport(statistics, details);
return this.parsedData;
} catch (JDOMException e) {
throw new IOException(e.getMessage());
}
}
private ParsedStatistics parseStatistics(Element rootElement) {
Element statsElement = rootElement.getChild("stats"); //$NON-NLS-1$
NumericalParser parser = new NumericalParser();
ParsedStatistics result = new ParsedStatistics(
readTextualContent(statsElement, "name"),
parser.parseInt(readTextualContent(statsElement, "methodCount")),
parser.parseInt(readTextualContent(statsElement, "crapMethodCount")),
parser.parseInt(readTextualContent(statsElement, "crapLoad")),
parser.parseDouble(readTextualContent(statsElement, "totalCrap")),
parser.parseDouble(readTextualContent(statsElement, "crapMethodPercent")));
return result;
}
@SuppressWarnings("unchecked")
private ParsedCrap4JData parseDetails(Element rootElement) {
Element methodsElement = rootElement.getChild("methods"); //$NON-NLS-1$
List methodElements = methodsElement.getChildren("method"); //$NON-NLS-1$
for (Object object : methodElements) {
IMethodCrapData crapData = parseMethodCrap((Element) object);
if (IRRELEVANT_ENTRY == crapData) {
continue;
}
this.methodCrapManager.addMethodCrapData(crapData);
}
return new ParsedCrap4JData();
}
private static final MethodCrapData IRRELEVANT_ENTRY = new MethodCrapData(null, 0.0d, 0, 0.0d, 0.0d);
private IMethodCrapData parseMethodCrap(Element methodElement) {
IMethod method = parseMethod(methodElement);
NumericalParser parser = new NumericalParser();
int crapLoad = parser.parseInt(readTextualContent(methodElement, "crapLoad")); //$NON-NLS-1$
if (0 == crapLoad) {
return IRRELEVANT_ENTRY;
}
double crap = parser.parseDouble(readTextualContent(methodElement, "crap")); //$NON-NLS-1$
double coverage = parser.parseDouble(readTextualContent(methodElement, "coverage")); //$NON-NLS-1$
double complexity = parser.parseDouble(readTextualContent(methodElement, "complexity")); //$NON-NLS-1$
return new MethodCrapData(method,
crap, crapLoad, coverage, complexity);
}
private String readTextualContent(Element element, String subTagName) {
String childText = element.getChildText(subTagName);
if (null == childText) {
System.err.println("Got null content for " + subTagName);
return null;
}
return childText.trim();
}
private static class MethodCrapData extends GenericCrapData<IMethod> implements IMethodCrapData {
public MethodCrapData(IMethod context, double crap, int crapLoad,
double coverage, double complexity) {
super(context, 0, 1, crap, crapLoad, coverage, complexity);
}
@Override
public int getCrappyMethods() {
if (isCrappy()) {
return 1;
}
return 0;
}
//@Override
public boolean isCrappy() {
return (getCrapLoad() > 0);
}
@Override
public double getCrapPercentage() {
if (isCrappy()) {
return 1.0d;
}
return 0.0d;
}
}
private IMethod parseMethod(Element methodElement) {
return new ParsedMethod(
readTextualContent(methodElement, "package"),
readTextualContent(methodElement, "className"),
readTextualContent(methodElement, "methodName"), //$NON-NLS-1$
readTextualContent(methodElement, "methodSignature"), //$NON-NLS-1$
readTextualContent(methodElement, "fullMethod")); //$NON-NLS-1$
}
private static class ParsedMethod implements IMethod {
private final String packageName;
private final String className;
private final String methodName;
private final String signature;
private final String fullMethod;
public ParsedMethod(
String packageName,
String className,
String methodName,
String signature,
String fullMethod) {
super();
this.packageName = packageName;
this.className = className;
this.methodName = methodName;
this.signature = signature;
this.fullMethod = fullMethod;
}
//@Override
public String getClassName() {
return this.className;
}
//@Override
public String getFullMethod() {
return this.fullMethod;
}
//@Override
public String getName() {
return this.methodName;
}
//@Override
public String getPackageName() {
return this.packageName;
}
//@Override
public String getSignature() {
return this.signature;
}
}
}