/*
* Cobertura - http://cobertura.sourceforge.net/
*
* Copyright (C) 2010 Piotr Tabor
*
* Note: This file is dual licensed under the GPL and the Apache
* Source License (so that it can be used from both the main
* Cobertura classes and the ant tasks).
*
* Cobertura is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* Cobertura is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cobertura; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
package net.sourceforge.cobertura.coveragedata;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.cobertura.coveragedata.countermaps.AtomicCounterMap;
import net.sourceforge.cobertura.coveragedata.countermaps.CounterMap;
public class TouchCollector implements HasBeenInstrumented {
private static final CounterMap<LineTouchData> touchedLines = new AtomicCounterMap<LineTouchData>();
private static final CounterMap<SwitchTouchData> switchTouchData = new AtomicCounterMap<SwitchTouchData>();
private static final CounterMap<JumpTouchData> jumpTouchData = new AtomicCounterMap<JumpTouchData>();
private static AtomicInteger lastClassId = new AtomicInteger(1);
private static final Map<String, Integer> class2classId = new ConcurrentHashMap<String, Integer>();
private static final Map<Integer, String> classId2class = new ConcurrentHashMap<Integer, String>();
static {
ProjectData.initialize();
}
private static final int registerClassData(String name) {
Integer res = class2classId.get(name);
if (res == null) {
int new_id = lastClassId.incrementAndGet();
class2classId.put(name, new_id);
classId2class.put(new_id, name);
return new_id;
}
return res;
}
/**
* This method is only called by code that has been instrumented. It
* is not called by any of the Cobertura code or ant tasks.
*/
public static final void touchSwitch(String classId, int lineNumber, int switchNumber, int branch) {
switchTouchData.incrementValue(new SwitchTouchData(registerClassData(classId), lineNumber, switchNumber, branch));
}
/**
* This method is only called by code that has been instrumented. It
* is not called by any of the Cobertura code or ant tasks.
*/
public static final void touch(String classId, int lineNumber) {
touchedLines.incrementValue(new LineTouchData(registerClassData(classId), lineNumber));
}
/**
* This method is only called by code that has been instrumented. It
* is not called by any of the Cobertura code or ant tasks.
*/
public static final void touchJump(String classId, int lineNumber, int branchNumber, boolean branch) {
jumpTouchData.incrementValue(new JumpTouchData(registerClassData(classId), lineNumber, branchNumber, branch));
}
private static class LineTouchData implements HasBeenInstrumented {
int classId, lineNumber;
public LineTouchData(int classId, int lineNumber) {
this.classId = classId;
this.lineNumber = lineNumber;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + classId;
result = prime * result + lineNumber;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LineTouchData other = (LineTouchData) obj;
if (classId != other.classId)
return false;
if (lineNumber != other.lineNumber)
return false;
return true;
}
}
private static class SwitchTouchData extends LineTouchData implements HasBeenInstrumented {
int switchNumber, branch;
public SwitchTouchData(int classId, int lineNumber, int switchNumber, int branch) {
super(classId, lineNumber);
this.switchNumber = switchNumber;
this.branch = branch;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + branch;
result = prime * result + switchNumber;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
SwitchTouchData other = (SwitchTouchData) obj;
if (branch != other.branch)
return false;
if (switchNumber != other.switchNumber)
return false;
return true;
}
}
private static class JumpTouchData extends LineTouchData implements HasBeenInstrumented {
int branchNumber;
boolean branch;
public JumpTouchData(int classId, int lineNumber, int branchNumber, boolean branch) {
super(classId, lineNumber);
this.branchNumber = branchNumber;
this.branch = branch;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (branch ? 1231 : 1237);
result = prime * result + branchNumber;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
JumpTouchData other = (JumpTouchData) obj;
if (branch != other.branch)
return false;
if (branchNumber != other.branchNumber)
return false;
return true;
}
}
public static synchronized void applyTouchesOnProjectData(ProjectData projectData) {
System.out.println("Flushing results...");
Map<LineTouchData, Integer> touches = touchedLines.getFinalStateAndCleanIt();
for (Entry<LineTouchData, Integer> touch : touches.entrySet()) {
if (touch.getValue() > 0) {
getClassFor(touch.getKey(), projectData).touch(touch.getKey().lineNumber, touch.getValue());
}
}
Map<SwitchTouchData, Integer> switchTouches = switchTouchData.getFinalStateAndCleanIt();
for (Entry<SwitchTouchData, Integer> touch : switchTouches.entrySet()) {
if (touch.getValue() > 0) {
getClassFor(touch.getKey(), projectData).touchSwitch(
touch.getKey().lineNumber,
touch.getKey().switchNumber,
touch.getKey().branch, touch.getValue());
}
}
Map<JumpTouchData, Integer> jumpTouches = jumpTouchData.getFinalStateAndCleanIt();
for (Entry<JumpTouchData, Integer> touch : jumpTouches.entrySet()) {
if (touch.getValue() > 0) {
getClassFor(touch.getKey(), projectData).touchJump(
touch.getKey().lineNumber,
touch.getKey().branchNumber,
touch.getKey().branch, touch.getValue());
}
}
System.out.println("Flushing results done");
}
private static ClassData getClassFor(LineTouchData key, ProjectData projectData) {
// System.out.println("\nLooking for:"+key.classId+"\n");
return projectData.getOrCreateClassData(classId2class.get(key.classId));
}
}