package org.erlide.cover.core;
import java.io.File;
import java.util.Iterator;
import org.erlide.cover.api.IConfiguration;
import org.erlide.cover.views.model.FunctionStats;
import org.erlide.cover.views.model.ICoverageObject;
import org.erlide.cover.views.model.LineResult;
import org.erlide.cover.views.model.ModuleSet;
import org.erlide.cover.views.model.ModuleStats;
import org.erlide.cover.views.model.ObjectType;
import org.erlide.cover.views.model.StatsTreeModel;
import org.erlide.cover.views.model.StatsTreeObject;
import org.erlide.engine.ErlangEngine;
import org.erlide.runtime.events.ErlEvent;
import org.erlide.runtime.events.ErlangEventHandler;
import org.erlide.util.ErlLogger;
import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.google.common.eventbus.Subscribe;
/**
* Handler for coverage events
*
* @author Aleksandra Lipiec <aleksandra.lipiec@erlang.solutions.com>
*
*/
public class CoverEventHandler extends ErlangEventHandler {
private static final String EVENT_NAME = "cover_event";
private static final String COVER_FIN = "cover_fin";
private static final String COVER_ERROR = "cover_error";
private static final String COVER_RES = "module_res";
private final Logger log; // log
private final CoverBackend coverBackend; // cover backend
public CoverEventHandler(final CoverBackend coverBackend) {
super(EVENT_NAME);
this.coverBackend = coverBackend;
log = Activator.getDefault();
}
@Subscribe
public void handleEvent(final ErlEvent event) {
if (!event.getTopic().equals(getTopic())) {
return;
}
OtpErlangTuple tuple = null;
final OtpErlangObject data = event.getEvent();
if (gotResults(data)) {
for (final ICoverObserver obs : coverBackend.getListeners()) {
obs.eventOccured(new CoverEvent(CoverStatus.UPDATE));
}
} else if ((tuple = getErrorReason(data)) != null) {
final String place = tuple.elementAt(1).toString();
final String type = tuple.elementAt(2).toString();
final String info = tuple.elementAt(3).toString();
for (final ICoverObserver obs : coverBackend.getListeners()) {
obs.eventOccured(new CoverEvent(CoverStatus.ERROR,
String.format("Error at %s while %s: %s\n", place, type, info)));
}
} else if (data.toString().equals(COVER_FIN)
&& coverBackend.getAnnotationMaker() != null) {
coverBackend.getAnnotationMaker().addAnnotations();
}
}
/**
* When coverage results came
*
* @param msg
* @return
*/
private boolean gotResults(final OtpErlangObject msg) {
if (msg instanceof OtpErlangTuple) {
final OtpErlangTuple resTuple = (OtpErlangTuple) msg;
if (resTuple.elementAt(0) instanceof OtpErlangAtom
&& ((OtpErlangAtom) resTuple.elementAt(0)).atomValue()
.equals(COVER_RES)) {
final String moduleName = resTuple.elementAt(1).toString();
String htmlPath = resTuple.elementAt(2).toString();
htmlPath = htmlPath.substring(1, htmlPath.length() - 1);
final int allLines = Integer.parseInt(resTuple.elementAt(3).toString());
final int coveredLines = Integer
.parseInt(resTuple.elementAt(4).toString());
final double percent = Double
.parseDouble(resTuple.elementAt(5).toString());
log.info(String.format("Module %s %s %d %d %f", moduleName, htmlPath,
allLines, coveredLines, percent));
final ModuleStats moduleStats = new ModuleStats();
moduleStats.setLabel(moduleName);
moduleStats.setHtmlPath(htmlPath);
moduleStats.setLiniesCount(allLines);
moduleStats.setCoverCount(coveredLines);
// calculate md5
try {
final File file = new File(ErlangEngine.getInstance().getModel()
.findModule(moduleName).getFilePath());
moduleStats.setMd5(MD5Checksum.getMD5(file));
} catch (final Exception e) {
ErlLogger.error(e);
}
//
prepLineResults((OtpErlangList) resTuple.elementAt(6), moduleStats);
prepFuncResults((OtpErlangList) resTuple.elementAt(7), moduleStats);
addModuleToTree(moduleStats);
ModuleSet.add(moduleStats);
return true;
}
return false;
}
return false;
}
// adds module to the statistics tree
private void addModuleToTree(final ModuleStats moduleStats) {
ICoverageObject root = StatsTreeModel.getInstance().getRoot();
final IConfiguration config = CoveragePerformer.getPerformer().getConfig();
final String ppath = ErlangEngine.getInstance().getModelUtilService()
.getProject(config.getProject()).getWorkspaceProject().getLocation()
.toString();
String mpath = config.getModule(moduleStats.getLabel()).getFilePath();
mpath = mpath.substring(ppath.length());
log.info(ppath);
log.info(mpath);
final String[] parts = mpath.split("/");
root.setLiniesCount(root.getLinesCount() + moduleStats.getLinesCount());
root.setCoverCount(root.getCoverCount() + moduleStats.getCoverCount());
for (int i = 1; i < parts.length - 1; i++) {
ICoverageObject tmp = root.findChild(parts[i]);
if (tmp == null) {
tmp = new StatsTreeObject(ObjectType.FOLDER);
tmp.setLabel(parts[i]);
}
tmp.setLiniesCount(tmp.getLinesCount() + moduleStats.getLinesCount());
tmp.setCoverCount(tmp.getCoverCount() + moduleStats.getCoverCount());
root.addChild(parts[i], tmp);
root = tmp;
}
root.addChild(moduleStats.getLabel(), moduleStats);
}
private void prepFuncResults(final OtpErlangList funcList, final ModuleStats stats) {
final Iterator<OtpErlangObject> it = funcList.iterator();
while (it.hasNext()) {
final OtpErlangTuple res = (OtpErlangTuple) it.next();
final FunctionStats func = new FunctionStats();
final String name = res.elementAt(1).toString();
final int arity = Integer.parseInt(res.elementAt(2).toString());
final int allLines = Integer.parseInt(res.elementAt(3).toString());
final int coveredLines = Integer.parseInt(res.elementAt(4).toString());
func.setLabel(name);
func.setLiniesCount(allLines);
func.setCoverCount(coveredLines);
func.setArity(arity);
stats.addChild(func.getLabel(), func);
}
}
private void prepLineResults(final OtpErlangList lineList, final ModuleStats stats) {
final Iterator<OtpErlangObject> it = lineList.iterator();
while (it.hasNext()) {
final OtpErlangTuple res = (OtpErlangTuple) it.next();
final int num = Integer.parseInt(res.elementAt(1).toString());
final int calls = Integer.parseInt(res.elementAt(2).toString());
final LineResult lineRes = new LineResult(num, calls);
stats.addLine(lineRes);
}
}
private OtpErlangTuple getErrorReason(final OtpErlangObject message) {
if (message instanceof OtpErlangTuple) {
final OtpErlangTuple tuple = (OtpErlangTuple) message;
if (tuple.elementAt(0) instanceof OtpErlangAtom
&& ((OtpErlangAtom) tuple.elementAt(0)).atomValue()
.equals(COVER_ERROR)) {
return tuple;
}
}
return null;
}
}