Add found bugs to database.
[cfb.git] / prod / net / jaekl / cfb / store / DbStore.java
1 package net.jaekl.cfb.store;
2
3 import java.sql.Connection;
4 import java.sql.SQLException;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import net.jaekl.cfb.analyze.Analysis;
9 import net.jaekl.cfb.db.CfbSchema;
10 import net.jaekl.cfb.db.Column;
11 import net.jaekl.cfb.db.Condition;
12 import net.jaekl.cfb.db.Operation;
13 import net.jaekl.cfb.db.Row;
14 import net.jaekl.cfb.db.Table;
15 import net.jaekl.cfb.db.TypeMismatchException;
16 import net.jaekl.cfb.db.driver.DbDriver;
17 import net.jaekl.cfb.xml.BugClass;
18 import net.jaekl.cfb.xml.BugInstance;
19 import net.jaekl.cfb.xml.BugMethod;
20 import net.jaekl.cfb.xml.SourceLine;
21 import net.jaekl.cfb.xml.messages.MessageCollection;
22
23 public class DbStore {
24         Connection m_con;
25         DbDriver m_driver;
26         MessageCollection m_msgColl;
27         
28         public DbStore(Connection con, DbDriver driver, MessageCollection msgColl) {
29                 m_con = con;
30                 m_driver = driver;
31                 m_msgColl = msgColl;
32         }
33         
34         public boolean put(Analysis analysis) throws SQLException, TypeMismatchException {
35                 if (null == analysis) {
36                         return false;
37                 }
38                 
39                 // ----------------------------------
40                 // Add a run record for this analysis
41                 
42                 long runId = m_driver.nextVal(m_con, CfbSchema.RUN_SEQ);
43                 Object[][] values = { 
44                                                                 {
45                                                                         Long.valueOf(runId),
46                                                                         analysis.getBuildNumber(),
47                                                                         analysis.getStart(),
48                                                                         analysis.getEnd() 
49                                                                 } 
50                                                         };
51                 int count = m_driver.insert(m_con, CfbSchema.RUNS, values);
52                 if (1 != count) {
53                         return false;
54                 }
55                 
56                 // -------------------------------------
57                 // Add a found record for each bug found
58                 
59                 List<BugInstance> bugs = analysis.getBugCollection().getBugs();
60                 values = new Object[bugs.size()][CfbSchema.FOUND.getNumColumns()];
61                 
62                 int row = 0;
63                 for (BugInstance bug : bugs)
64                 {
65                         Long foundId = Long.valueOf(m_driver.nextVal(m_con, CfbSchema.FOUND_SEQ));
66                         Long bugId = Long.valueOf(m_msgColl.getPattern(bug.getType()).getId());
67                         Long categoryId = Long.valueOf(m_msgColl.getCategory(bug.getCategory()).getId());
68                         Location[] locs = computeLocations(bug);
69                         Location firstLoc  = (locs.length > 0) ? locs[0] : null;
70                         Location secondLoc = (locs.length > 1) ? locs[1] : null;
71                         Location thirdLoc  = (locs.length > 2) ? locs[2] : null;
72                         
73                         values[row][0] = foundId;
74                         values[row][1] = bugId;
75                         values[row][2] = categoryId;
76                         values[row][3] = getLocId(firstLoc);
77                         values[row][4] = getLocId(secondLoc);
78                         values[row][5] = getLocId(thirdLoc);
79                         row++;
80                 }
81                 
82                 count = m_driver.insert(m_con, CfbSchema.FOUND, values);
83                 return (bugs.size() == count);
84         }
85         
86         Location[] computeLocations(BugInstance bug)
87         {
88                 ArrayList<Location> locs = new ArrayList<Location>();
89                 
90                 for (SourceLine line : bug.getLines()) {
91                         locs.add(new Location(line));
92                 }
93                 for (BugMethod method : bug.getMethods()) {
94                         locs.add(new Location(method));
95                 }
96                 for (BugClass clazz : bug.getClasses()) {
97                         locs.add(new Location(clazz));
98                 }
99                 
100                 return locs.toArray(new Location[locs.size()]);
101         }
102         
103         Long getLocId(Location loc) throws SQLException, TypeMismatchException 
104         {
105                 if (null == loc) {
106                         return null;
107                 }
108                 Long locId = findLocId(loc);
109                 if (null != locId) {
110                         return locId;
111                 }
112
113                 return storeLoc(loc);
114         }
115         
116         Long findLocId(Location loc) throws SQLException, TypeMismatchException
117         {
118                 Column[] columns = { CfbSchema.LOCATIONS.getColumn(CfbSchema.LOCID) };
119                 Table[] tables = { CfbSchema.LOCATIONS };
120                 Condition[] conditions = { 
121                                                 new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.CLASSNAME),
122                                                                loc.getClassName(),
123                                                                Operation.EQUAL 
124                                                              ),
125                                                 new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.METHODNAME),
126                                                                        loc.getMethodName(),
127                                                                        Operation.EQUAL
128                                                                      ),
129                                                 new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.STARTLINE),
130                                                                        loc.getStart(),
131                                                                        Operation.EQUAL
132                                                                      ),
133                                                 new Condition( CfbSchema.LOCATIONS.getColumn(CfbSchema.ENDLINE),
134                                                                        loc.getEnd(),
135                                                                        Operation.EQUAL
136                                                                      )
137                                         };
138                 List<Row> rows = m_driver.select(m_con, columns, tables, conditions);
139                 if (rows.size() > 0) {
140                         assert(1 == rows.size());       // should only have one match
141                         
142                         return rows.get(0).getLong(0);
143                 }
144                 
145                 return null;    // not found
146         }
147         
148         Long storeLoc(Location loc) throws SQLException
149         {
150                 long locId = m_driver.nextVal(m_con, CfbSchema.LOC_SEQ);
151                 
152                 Object[][] values = { { 
153                                                         Long.valueOf(locId),
154                                                         loc.getClassName(),
155                                                         loc.getMethodName(),
156                                                         Long.valueOf(loc.getStart()),
157                                                         Long.valueOf(loc.getEnd())
158                                                 } };
159                 m_driver.insert(m_con, CfbSchema.LOCATIONS, values);
160                 
161                 return Long.valueOf(locId);
162         }
163 }