import java.sql.Connection;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.List;
import net.jaekl.cfb.analyze.Analysis;
import net.jaekl.cfb.db.Condition;
import net.jaekl.cfb.db.Operation;
import net.jaekl.cfb.db.Row;
+import net.jaekl.cfb.db.Sort;
import net.jaekl.cfb.db.Table;
import net.jaekl.cfb.db.TypeMismatchException;
import net.jaekl.cfb.db.driver.DbDriver;
+import net.jaekl.cfb.xml.BugClass;
+import net.jaekl.cfb.xml.BugCollection;
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;
m_driver = driver;
m_msgColl = msgColl;
}
+
+ public Analysis getPrior(Analysis analysis) throws SQLException, TypeMismatchException {
+ if (null == analysis) {
+ return null;
+ }
+ Long priorId = getPriorId(analysis);
+ if (null == priorId) {
+ return null;
+ }
+
+ return getAnalysis(priorId);
+ }
- public boolean put(Analysis analysis) throws SQLException {
+ public boolean put(Analysis analysis) throws SQLException, TypeMismatchException {
if (null == analysis) {
return false;
}
int row = 0;
for (BugInstance bug : bugs)
{
- long foundId = m_driver.nextVal(m_con, CfbSchema.FOUND_SEQ);
- long bugId = m_msgColl.getPattern(bug.getType()).getId();
- // values[row] = { foundId, bugId, firstLocId, secondLocId, thirdLocId };
+ Long foundId = Long.valueOf(m_driver.nextVal(m_con, CfbSchema.FOUND_SEQ));
+ Long bugId = Long.valueOf(m_msgColl.getPattern(bug.getType()).getId());
+ Long categoryId = Long.valueOf(m_msgColl.getCategory(bug.getCategory()).getId());
+ Location[] locs = computeLocations(bug);
+ Location firstLoc = (locs.length > 0) ? locs[0] : null;
+ Location secondLoc = (locs.length > 1) ? locs[1] : null;
+ Location thirdLoc = (locs.length > 2) ? locs[2] : null;
+
+ values[row][0] = foundId;
+ values[row][1] = bugId;
+ values[row][2] = categoryId;
+ values[row][3] = getLocId(firstLoc);
+ values[row][4] = getLocId(secondLoc);
+ values[row][5] = getLocId(thirdLoc);
+ values[row][6] = getVarId(bug);
row++;
}
- return true;
+ count = m_driver.insert(m_con, CfbSchema.FOUND, values);
+ return (bugs.size() == count);
}
Location[] computeLocations(BugInstance bug)
{
- throw new UnsupportedOperationException("UNIMPLEMENTED");
+ ArrayList<Location> locs = new ArrayList<Location>();
+
+ /*
+ 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()) {
+ 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));
+ }
+
+ return locs.toArray(new Location[locs.size()]);
}
- long getLocId(SourceLine loc) throws SQLException, TypeMismatchException
+ Long getLocId(Location loc) throws SQLException, TypeMismatchException
{
- long locId = findLocId(loc);
- if (locId >= 0) {
+ if (null == loc) {
+ return null;
+ }
+ Long locId = findLocId(loc);
+ if (null != locId) {
return locId;
}
return storeLoc(loc);
}
- long findLocId(SourceLine loc) throws SQLException, TypeMismatchException
+ Long findLocId(Location loc) throws SQLException, TypeMismatchException
{
- Column[] columns = { CfbSchema.LOCATIONS.getColumn(CfbSchema.LOCID) };
+ Column[] columns = { CfbSchema.LOCID };
Table[] tables = { CfbSchema.LOCATIONS };
+
Condition[] conditions = {
- new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.CLASSNAME),
- loc.getClassName(),
- Operation.EQUAL
- ),
- new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.STARTLINE),
- loc.getStart(),
- Operation.EQUAL
- ),
- new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.ENDLINE),
- loc.getEnd(),
- Operation.EQUAL
- )
+ 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 )
};
List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
if (rows.size() > 0) {
return rows.get(0).getLong(0);
}
- return (-1); // not found
+ return null; // not found
}
- long storeLoc(SourceLine loc) throws SQLException
+ Long storeLoc(Location loc) throws SQLException
{
long locId = m_driver.nextVal(m_con, CfbSchema.LOC_SEQ);
Object[][] values = { {
- locId,
+ 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 locId;
+ 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);
+ }
+
+ Long getPriorId(Analysis analysis) throws SQLException, TypeMismatchException
+ {
+ Column[] columns = { CfbSchema.RUNID };
+ Table[] tables = { CfbSchema.RUNS };
+ Condition[] conditions = { new Condition( CfbSchema.STARTTIME, analysis.getStart(), Operation.LESS_THAN ) };
+ Sort[] sorts = { new Sort( CfbSchema.STARTTIME, Sort.Direction.DESCENDING ) };
+ int limit = 1;
+
+ List<Row> rows = m_driver.select(m_con, columns, tables, conditions, sorts, limit);
+ if (rows.size() < 1) {
+ return null;
+ }
+ return rows.get(0).getLong(0);
+ }
+
+ Analysis getAnalysis(Long priorId) throws SQLException, TypeMismatchException
+ {
+ Column[] columns = { CfbSchema.VERSION, CfbSchema.STARTTIME, CfbSchema.ENDTIME };
+ Table[] tables = { CfbSchema.RUNS };
+ Condition[] conditions = { new Condition( CfbSchema.RUNID, priorId, Operation.EQUAL ) };
+
+ List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
+ if (rows.size() < 1) {
+ return null;
+ }
+
+ Row row = rows.get(0);
+
+ String version = row.getString(0);
+ java.util.Date start= row.getDate(1);
+ java.util.Date end = row.getDate(2);
+
+ Analysis prior = new Analysis(version);
+ prior.setId(priorId.longValue());
+ prior.setStart(start);
+ prior.setEnd(end);
+
+ prior.setBugCollection(getBugCollection(priorId));
+
+ return prior;
+ }
+
+ BugCollection getBugCollection(Long priorId) throws SQLException, TypeMismatchException
+ {
+ throw new UnsupportedOperationException("Not yet implemented");
}
}