import net.jaekl.cfb.xml.BugClass;
import net.jaekl.cfb.xml.BugInstance;
import net.jaekl.cfb.xml.BugMethod;
+import net.jaekl.cfb.xml.LocalVariable;
import net.jaekl.cfb.xml.SourceLine;
import net.jaekl.cfb.xml.messages.MessageCollection;
values[row][3] = getLocId(firstLoc);
values[row][4] = getLocId(secondLoc);
values[row][5] = getLocId(thirdLoc);
+ values[row][6] = getVarId(bug);
row++;
}
{
ArrayList<Location> locs = new ArrayList<Location>();
- for (SourceLine line : bug.getLines()) {
- locs.add(new Location(line));
+ /*
+ Somewhat unfortunate special case.
+ The primary "location" for a bug instance is split between tags.
+ Most bugs have a pattern like this:
+ <BugInstance>
+ ...
+ <Method>
+ <SourceLine .../>
+ </Method>
+ ...
+ <SourceLine .../>
+ </BugInstance>
+
+ The primary location for a bug is given by the <Method> with no role attribute,
+ but the <SourceLine/> inside that method describes the whole range of lines
+ covered by that Method, not the spot where the bug is located--that is given
+ by the <SourceLine/> that is a direct child fo the <BugInstance/>.
+ */
+
+ BugMethod primaryMethod = null;
+ SourceLine primaryLine = null;
+
+ for (BugMethod method : bug.getMethods()) {
+ if (null != method.getRole()) {
+ primaryMethod = method;
+ break;
+ }
+ }
+ if (bug.getLines().size() > 0) {
+ primaryLine = bug.getLines().get(0);
+ }
+
+ if ((null != primaryMethod) && (null != primaryLine)) {
+ locs.add(new Location(primaryMethod, primaryLine));
}
+
for (BugMethod method : bug.getMethods()) {
- locs.add(new Location(method));
+ if (primaryMethod != method) {
+ locs.add(new Location(method));
+ }
+ }
+ for (SourceLine line : bug.getLines()) {
+ if (primaryLine != line) {
+ locs.add(new Location(line));
+ }
}
for (BugClass clazz : bug.getClasses()) {
locs.add(new Location(clazz));
{
Column[] columns = { CfbSchema.LOCID };
Table[] tables = { CfbSchema.LOCATIONS };
+
Condition[] conditions = {
new Condition( CfbSchema.CLASSNAME, loc.getClassName(), Operation.EQUAL ),
new Condition( CfbSchema.METHODNAME, loc.getMethodName(), Operation.EQUAL ),
+ new Condition( CfbSchema.METHODROLE, loc.getMethodRole(), Operation.EQUAL ),
new Condition( CfbSchema.STARTLINE, loc.getStart(), Operation.EQUAL ),
new Condition( CfbSchema.ENDLINE, loc.getEnd(), Operation.EQUAL )
};
Long.valueOf(locId),
loc.getClassName(),
loc.getMethodName(),
+ loc.getMethodRole(),
Long.valueOf(loc.getStart()),
Long.valueOf(loc.getEnd())
} };
- m_driver.insert(m_con, CfbSchema.LOCATIONS, values);
+ int count = m_driver.insert(m_con, CfbSchema.LOCATIONS, values);
+ if (1 != count) {
+ return null;
+ }
return Long.valueOf(locId);
}
+
+ Long getVarId(BugInstance bug) throws SQLException, TypeMismatchException
+ {
+ if (null == bug) {
+ return null;
+ }
+
+ List<LocalVariable> vars = bug.getVariables();
+ if ((null == vars) || (0 == vars.size())) {
+ return null;
+ }
+
+ return getVarId(vars.get(0));
+ }
+
+ Long getVarId(LocalVariable var) throws SQLException, TypeMismatchException
+ {
+ if (null == var) {
+ return null;
+ }
+
+ Long result = findVarId(var);
+
+ if (null != result) {
+ return result;
+ }
+
+ return storeVar(var);
+ }
+
+ Long findVarId(LocalVariable var) throws SQLException, TypeMismatchException
+ {
+ Column[] columns = { CfbSchema.VARID_PK };
+ Table[] tables = { CfbSchema.VARIABLES };
+
+ Condition[] conditions = {
+ new Condition( CfbSchema.NAME, var.getName(), Operation.EQUAL ),
+ new Condition( CfbSchema.VARROLE, var.getRole(), Operation.EQUAL )
+ };
+ List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
+ if (rows.size() > 0) {
+ assert(1 == rows.size()); // should only have one match
+
+ return rows.get(0).getLong(0);
+ }
+
+ return null; // not found
+ }
+
+ Long storeVar(LocalVariable var) throws SQLException
+ {
+ long varId = m_driver.nextVal(m_con, CfbSchema.VARIABLE_SEQ);
+
+ Object[][] values = { {
+ Long.valueOf(varId),
+ var.getName(),
+ var.getRole()
+ } };
+ int count = m_driver.insert(m_con, CfbSchema.VARIABLES, values);
+ if (1 != count) {
+ return null;
+ }
+
+ return Long.valueOf(varId);
+ }
}