KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > projtrack > Bug


1 /*
2   Copyright (C) 2003 Know Gate S.L. All rights reserved.
3                       C/Oņa, 107 1š2 28050 Madrid (Spain)
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8
9   1. Redistributions of source code must retain the above copyright
10      notice, this list of conditions and the following disclaimer.
11
12   2. The end-user documentation included with the redistribution,
13      if any, must include the following acknowledgment:
14      "This product includes software parts from hipergate
15      (http://www.hipergate.org/)."
16      Alternately, this acknowledgment may appear in the software itself,
17      if and wherever such third-party acknowledgments normally appear.
18
19   3. The name hipergate must not be used to endorse or promote products
20      derived from this software without prior written permission.
21      Products derived from this software may not be called hipergate,
22      nor may hipergate appear in their name, without prior written
23      permission.
24
25   This library is distributed in the hope that it will be useful,
26   but WITHOUT ANY WARRANTY; without even the implied warranty of
27   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
28
29   You should have received a copy of hipergate License with this code;
30   if not, visit http://www.hipergate.org or mail to info@hipergate.org
31 */

32
33 package com.knowgate.projtrack;
34
35 import com.knowgate.debug.DebugFile;
36
37 import com.knowgate.dataobjs.DB;
38 import com.knowgate.jdc.JDCConnection;
39 import com.knowgate.dataobjs.DBBind;
40 import com.knowgate.dataobjs.DBPersist;
41 import com.knowgate.dataobjs.DBSubset;
42 import com.knowgate.lucene.Indexer;
43 import com.knowgate.lucene.BugIndexer;
44
45 import com.knowgate.misc.Gadgets;
46
47 import java.util.HashMap JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.Properties JavaDoc;
50
51 import java.io.FileNotFoundException JavaDoc;
52 import java.io.IOException JavaDoc;
53
54 import java.sql.Connection JavaDoc;
55 import java.sql.SQLException JavaDoc;
56 import java.sql.CallableStatement JavaDoc;
57 import java.sql.PreparedStatement JavaDoc;
58 import java.sql.Statement JavaDoc;
59 import java.sql.ResultSet JavaDoc;
60 import java.sql.Timestamp JavaDoc;
61 import java.sql.Types JavaDoc;
62
63 /**
64  * <p>Bug or Project Incident</p>
65  * @author Sergio Montoro Ten
66  * @version 3.0
67  */

68 public class Bug extends DBPersist {
69
70   /**
71    * Create empty bug
72    */

73   public Bug() {
74     super(DB.k_bugs, "Bug");
75   }
76
77   // ----------------------------------------------------------
78

79   /**
80    * Load Bug from database.
81    * @param oConn Database Connection
82    * @param sIdBug GUID of Bug to be loaded.
83    * @throws SQLException
84    */

85   public Bug(JDCConnection oConn, String JavaDoc sIdBug) throws SQLException JavaDoc {
86     super(DB.k_bugs,"Bug");
87
88     Object JavaDoc aBug[] = { sIdBug };
89
90     load (oConn,aBug);
91   }
92
93   // ----------------------------------------------------------
94

95   /**
96    * Load Bug from database.
97    * @param oConn Database Connection
98    * @param iPgBug int Numeric identifier of bug to be loaded
99    * @param sWorkArea String GUID of WorkArea to which Bug belongs
100    * @throws SQLException
101    * @since 3.0
102    */

103   public Bug(JDCConnection oConn, int iPgBug, String JavaDoc sWorkArea) throws SQLException JavaDoc {
104     super(DB.k_bugs,"Bug");
105     Object JavaDoc aBug[] = { Bug.getIdFromPg(oConn, iPgBug, sWorkArea) };
106     if (null!=aBug[0]) load (oConn,aBug);
107   }
108
109   // ----------------------------------------------------------
110

111   /**
112    * <p>Delete Bug</p>
113    * Calls k_sp_del_bug stored procedure.
114    * @param oConn Database Connection
115    * @return boolean
116    * @throws SQLException
117    */

118   public boolean delete(JDCConnection oConn) throws SQLException JavaDoc {
119     return Bug.delete(oConn, getString(DB.gu_bug));
120   }
121
122   // ----------------------------------------------------------
123

124   /**
125    * <p>Delete Bug from database and from lucene index</p>
126    * @param oConn Database Connection
127    * @param oCnf Properties containing luceneindex path
128    * @return boolean
129    * @throws SQLException
130    * @throws IOException
131    * @throws NoSuchFieldException
132    * @throws IllegalAccessException
133    * @since 3.0
134    */

135   public boolean delete(JDCConnection oConn, Properties JavaDoc oCnf)
136     throws SQLException JavaDoc, IOException JavaDoc, NoSuchFieldException JavaDoc, IllegalAccessException JavaDoc {
137     return Bug.delete(oConn, getString(DB.gu_bug), oCnf);
138   }
139
140   // ----------------------------------------------------------
141

142   /**
143    * <p>Store Bug and write its change log</p>
144    * This method automatically assigns a new bug number (pg_bug) if one is not
145    * supplied by calling seq_k_bugs sequence
146    * It also updates last modified date (dt_modified) and sinve v2.2 writes changes
147    * to k_bugs_changelog if that table exists
148    * @param oConn JDCConnection
149    * @return boolean
150    * @throws SQLException
151    */

152   public boolean store(JDCConnection oConn) throws SQLException JavaDoc {
153     int iPgBug;
154     Timestamp JavaDoc dtNow;
155     Object JavaDoc oOldValue;
156     String JavaDoc sSQL;
157
158     if (DebugFile.trace) {
159       DebugFile.writeln("Begin Bug.store()");
160       DebugFile.incIdent();
161     }
162
163     dtNow = new Timestamp JavaDoc(DBBind.getTime());
164
165     if (!AllVals.containsKey(DB.gu_bug)) {
166       put(DB.gu_bug, Gadgets.generateUUID());
167       if (!AllVals.containsKey(DB.pg_bug)) {
168         iPgBug = Bug.getPgFromId(oConn, getString(DB.gu_bug));
169         if (-1==iPgBug) iPgBug = DBBind.nextVal(oConn, "seq_" + DB.k_bugs);
170         put(DB.pg_bug, iPgBug);
171       }
172     } else {
173       if (!AllVals.containsKey(DB.pg_bug)) {
174         iPgBug = Bug.getPgFromId(oConn, getString(DB.gu_bug));
175         if (-1==iPgBug) iPgBug = DBBind.nextVal(oConn, "seq_" + DB.k_bugs);
176         put(DB.pg_bug, iPgBug);
177       }
178       replace(DB.dt_modified, dtNow);
179       Bug oOld = new Bug ();
180       if (oOld.load(oConn, new Object JavaDoc[]{get(DB.gu_bug)})) {
181         if (DBBind.exists(oConn, DB.k_bugs_changelog,"U")) {
182           HashMap JavaDoc oLog = changelog(oOld);
183           sSQL = "INSERT INTO "+DB.k_bugs_changelog+" ("+DB.gu_bug+","+DB.pg_bug+","+DB.nm_column+","+DB.gu_writer+","+DB.tx_oldvalue+") VALUES (?,?,?,?,?)";
184           if (DebugFile.trace) DebugFile.writeln("PreparedStatement.prepareStatement("+sSQL+")");
185           PreparedStatement JavaDoc oWriteLog = oConn.prepareStatement(sSQL);
186           oWriteLog.setString(1, getString(DB.gu_bug));
187           oWriteLog.setInt (2, getInt(DB.pg_bug));
188           Iterator JavaDoc oIter = oLog.keySet().iterator();
189           while (oIter.hasNext()) {
190             String JavaDoc sColumnName = (String JavaDoc) oIter.next();
191             if (!sColumnName.equalsIgnoreCase(DB.dt_modified)) {
192               oWriteLog.setString(3, sColumnName);
193               oWriteLog.setString(4, getStringNull(DB.gu_writer,null));
194               oOldValue = oLog.get(sColumnName);
195               if (null==oOldValue)
196                 oWriteLog.setNull(5, Types.VARCHAR);
197               else
198                 oWriteLog.setString(5, Gadgets.left(oOldValue.toString(),255));
199               if (DebugFile.trace) DebugFile.writeln("PreparedStatement.executeUpdate("+sColumnName+")");
200               oWriteLog.executeUpdate();
201             }
202           } // wend
203
if (DebugFile.trace) DebugFile.writeln("PreparedStatement.close()");
204           oWriteLog.close();
205         } // fi (exists(k_bugs_changelog))
206
} // fi (load(gu_bug))
207
} // fi (AllVals.containsKey(gu_bug))
208

209     boolean bRetVal = super.store(oConn);
210
211     if (DebugFile.trace) {
212       DebugFile.decIdent();
213       DebugFile.writeln("End Bug.store()");
214     }
215     return bRetVal;
216   } // store
217

218   // ---------------------------------------------------------------------------
219

220   /**
221    * Store bug and add it to a Lucene index
222    * @param oConn JDCConnection
223    * @param oCnf Properties containing luceneindex path
224    * @return boolean
225    * @throws SQLException
226    * @throws IOException
227    * @throws ClassNotFoundException
228    * @throws NoSuchFieldException
229    * @throws IllegalAccessException
230    * @throws InstantiationException
231    * @since 3.0
232    */

233   public boolean storeAndIndex(JDCConnection oConn, Properties JavaDoc oCnf)
234     throws SQLException JavaDoc, IOException JavaDoc,ClassNotFoundException JavaDoc,NoSuchFieldException JavaDoc,
235            IllegalAccessException JavaDoc,InstantiationException JavaDoc {
236     if (DebugFile.trace) {
237       DebugFile.writeln("Begin Bug.storeAndIndex([JDCConnection], [Properties])");
238       DebugFile.incIdent();
239     }
240     boolean bStore = store(oConn);
241     if (bStore) {
242       String JavaDoc sLuceneIndex = oCnf.getProperty("luceneindex","");
243       if (sLuceneIndex.length()>0) {
244         String JavaDoc sWrkA = getWorkArea(oConn, getString(DB.gu_bug));
245         BugIndexer.addBug(oCnf, oConn, sWrkA, this);
246       }
247     }
248     if (DebugFile.trace) {
249       DebugFile.decIdent();
250       DebugFile.writeln("End Bug.storeAndIndex()");
251     }
252     return bStore;
253   } // storeAndIndex
254

255   /**
256    * Re-index bug
257    * @param oConn JDCConnection
258    * @param oCnf Properties
259    * @throws SQLException
260    * @throws IOException
261    * @throws ClassNotFoundException
262    * @throws NoSuchFieldException
263    * @throws IllegalAccessException
264    * @throws InstantiationException
265    * @since 3.0
266    */

267   public void reIndex(JDCConnection oConn, Properties JavaDoc oCnf)
268     throws SQLException JavaDoc, IOException JavaDoc,ClassNotFoundException JavaDoc,NoSuchFieldException JavaDoc,
269            IllegalAccessException JavaDoc,InstantiationException JavaDoc {
270     if (DebugFile.trace) {
271       DebugFile.writeln("Begin Bug.reIndex([JDCConnection], [Properties])");
272       DebugFile.incIdent();
273     }
274
275     String JavaDoc sLuceneIndex = oCnf.getProperty("luceneindex","");
276     if (sLuceneIndex.length()>0) {
277       String JavaDoc sWrkA = getWorkArea(oConn, getString(DB.gu_bug));
278       if (null!=sWrkA) {
279         Indexer.delete("k_bugs", sWrkA, oCnf, getString(DB.gu_bug));
280         BugIndexer.addBug(oCnf, oConn, sWrkA, this);
281       } // fi
282
} // fi
283

284     if (DebugFile.trace) {
285       DebugFile.decIdent();
286       DebugFile.writeln("End Bug.reIndex()");
287     }
288   } // reIndex
289

290   // ---------------------------------------------------------------------------
291

292   /**
293    * Insert attachment into k_bugs_attach table
294    * @param oConn JDCConnection
295    * @param sFilePath String Full path to local file
296    * @throws SQLException
297    * @throws FileNotFoundException
298    * @throws IOException
299    * @throws NullPointerException
300    * @since 3.0
301    */

302   public void attachFile(JDCConnection oConn, String JavaDoc sFilePath)
303     throws SQLException JavaDoc, FileNotFoundException JavaDoc, IOException JavaDoc, NullPointerException JavaDoc {
304
305     if (DebugFile.trace) {
306       DebugFile.writeln("Begin Bug.attachFile([JDCConnection],"+sFilePath+")");
307       DebugFile.incIdent();
308     }
309
310     BugAttachment.createFromFile(oConn, getString(DB.gu_bug), sFilePath);
311
312     if (DebugFile.trace) {
313       DebugFile.decIdent();
314       DebugFile.writeln("End Bug.attachFile()");
315     }
316   } // attachFile
317

318   // ---------------------------------------------------------------------------
319

320   /**
321    * Remove attachment from k_bugs_attach table
322    * @param oConn JDCConnection
323    * @param sFileName String
324    * @throws SQLException
325    */

326   public void removeAttachment(JDCConnection oConn, String JavaDoc sFileName)
327     throws SQLException JavaDoc {
328     BugAttachment.delete(oConn, getString(DB.gu_bug), sFileName);
329   } // removeAttachment
330

331   // ---------------------------------------------------------------------------
332

333   /**
334    * Get array of attachments
335    * @param oConn JDCConnection
336    * @return BugAttachment[] Array of BugAttachment objects or <b>null</b> if this Bug has no attachments
337    * @throws SQLException
338    * @since 3.0
339    */

340   public BugAttachment[] attachments(JDCConnection oConn)
341     throws SQLException JavaDoc {
342     DBSubset oAttachs = new DBSubset(DB.k_bugs_attach, DB.tx_file+","+DB.len_file, DB.gu_bug+"=?", 10);
343     int iAttachs = oAttachs.load(oConn, new Object JavaDoc[]{getString(DB.gu_bug)});
344     if (0==iAttachs)
345       return null;
346     else {
347       BugAttachment[] aAttachs = new BugAttachment[iAttachs];
348       for (int a=0; a<iAttachs; a++)
349         aAttachs[a] = new BugAttachment(getString(DB.gu_bug),oAttachs.getString(1,a), oAttachs.getInt(2,a));
350       return aAttachs;
351     }
352   } // attachments
353

354   // ---------------------------------------------------------------------------
355

356   /**
357    * Get change log for all the values of a bug
358    * @param oConn JDCConnection
359    * @return BugChangeLog[]
360    * @throws SQLException
361    * @since 3.0
362    */

363   public BugChangeLog[] changeLog(JDCConnection oConn)
364     throws SQLException JavaDoc {
365     BugChangeLog[] aBcl;
366     DBSubset oLog = new DBSubset(DB.k_bugs_changelog,
367                                  DB.gu_bug+","+DB.pg_bug+","+DB.nm_column+","+DB.dt_modified+","+DB.gu_writer+","+DB.tx_oldvalue,
368                                  DB.gu_bug+"=? ORDER BY 4", 10);
369     int iLog = oLog.load(oConn, new Object JavaDoc[]{getString(DB.gu_bug)});
370     if (0==iLog) {
371       aBcl = null;
372     } else {
373       aBcl = new BugChangeLog[iLog];
374       for (int l=0; l<iLog; l++) {
375         aBcl[l] = new BugChangeLog();
376         aBcl[l].putAll(oLog.getRowAsMap(l));
377         aBcl[l].setWriter(oConn, oLog.getStringNull(4,l,null));
378       } // next
379
} // fi
380
return aBcl;
381   } // changeLog
382

383   // ---------------------------------------------------------------------------
384

385   /**
386    * Get change log for a column of a bug
387    * @param oConn JDCConnection
388    * @param sColumnName String
389    * @return BugChangeLog[]
390    * @throws SQLException
391    * @since 3.0
392    */

393   public BugChangeLog[] changeLog(JDCConnection oConn, String JavaDoc sColumnName)
394     throws SQLException JavaDoc {
395     BugChangeLog[] aBcl;
396     DBSubset oLog = new DBSubset(DB.k_bugs_changelog,
397                                  DB.gu_bug+","+DB.pg_bug+","+DB.nm_column+","+DB.dt_modified+","+DB.gu_writer+","+DB.tx_oldvalue,
398                                  DB.gu_bug+"=? AND "+DB.nm_column+"=? ORDER BY 4", 10);
399     int iLog = oLog.load(oConn, new Object JavaDoc[]{getString(DB.gu_bug), sColumnName});
400     if (0==iLog) {
401       aBcl = null;
402     } else {
403       aBcl = new BugChangeLog[iLog];
404       for (int l=0; l<iLog; l++) {
405         aBcl[l] = new BugChangeLog();
406         aBcl[l].putAll(oLog.getRowAsMap(l));
407         aBcl[l].setWriter(oConn, oLog.getStringNull(4,l,null));
408       } // next
409
} // fi
410
return aBcl;
411   } // changeLog
412

413
414   // ***************************************************************************
415
// Static Methods
416

417   /**
418    * Get WorkArea to which bug belongs
419    * @param oConn JDCConnection
420    * @param sGuid String Bug GUID
421    * @return String WorkArea GUID
422    */

423   private static String JavaDoc getWorkArea(JDCConnection oConn, String JavaDoc sGuid)
424     throws SQLException JavaDoc {
425     String JavaDoc sWrkA;
426     if (DebugFile.trace) {
427       DebugFile.writeln("JDCConnection.prepareStatement(SELECT p."+DB.gu_owner+" FROM "+DB.k_projects+" p,"+DB.k_bugs+" b WHERE p."+DB.gu_project+"=b."+DB.gu_project+" AND b."+DB.gu_bug+"='"+sGuid+"'");
428     }
429     PreparedStatement JavaDoc oStmt = oConn.prepareStatement("SELECT p."+DB.gu_owner+" FROM "+DB.k_projects+" p,"+DB.k_bugs+" b WHERE p."+DB.gu_project+"=b."+DB.gu_project+" AND b."+DB.gu_bug+"=?",
430                                                      ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
431     oStmt.setString(1, sGuid);
432     ResultSet JavaDoc oRSet = oStmt.executeQuery();
433     if (oRSet.next())
434       sWrkA = oRSet.getString(1);
435     else
436       sWrkA = null;
437     oRSet.close();
438     oStmt.close();
439     return sWrkA;
440   } // getWorkArea
441

442   /**
443    * <p>Delete Bug.</p>
444    * Typically, bugs are never deleted, but their status is changed to some
445    * definitive solved or archived condition.<br>
446    * Calls k_sp_del_bug stored procedure.
447    * @param oConn Database Connection
448    * @param sBugGUID GUID of Bug to be deleted.
449    * @throws SQLException
450    */

451   public static boolean delete(JDCConnection oConn, String JavaDoc sBugGUID) throws SQLException JavaDoc {
452     boolean bRetVal;
453
454     if (oConn.getDataBaseProduct()==JDCConnection.DBMS_POSTGRESQL) {
455       if (DebugFile.trace) DebugFile.writeln("Connection.executeQuery(SELECT k_sp_del_bug ('" + sBugGUID + "'))");
456       Statement JavaDoc oStmt = oConn.createStatement();
457       ResultSet JavaDoc oRSet = oStmt.executeQuery("SELECT k_sp_del_bug ('" + sBugGUID + "')");
458       oRSet.close();
459       oStmt.close();
460       bRetVal = true;
461     }
462     else {
463       if (DebugFile.trace) DebugFile.writeln("Connection.prepareCall({ call k_sp_del_bug ('" + sBugGUID + "')})");
464       CallableStatement JavaDoc oCall = oConn.prepareCall("{call k_sp_del_bug ('" + sBugGUID + "')}");
465       bRetVal = oCall.execute();
466       oCall.close();
467     }
468
469     return bRetVal;
470   } // delete()
471

472   /**
473    * Delete bug from database and from Lucene index
474    * @param oConn JDCConnection
475    * @param sBugGUID String Bug GUID
476    * @param oCnf Properties containing luceneindex path
477    * @return boolean
478    * @throws SQLException
479    * @throws IOException
480    * @throws NoSuchFieldException
481    * @throws IllegalAccessException
482    * @since 3.0
483    */

484   public static boolean delete(JDCConnection oConn, String JavaDoc sBugGUID, Properties JavaDoc oCnf)
485       throws SQLException JavaDoc, IOException JavaDoc, NoSuchFieldException JavaDoc, IllegalAccessException JavaDoc {
486     String JavaDoc sLuceneIndex = oCnf.getProperty("luceneindex","");
487     if (sLuceneIndex.length()>0) {
488       String JavaDoc sWrkA = getWorkArea(oConn, sBugGUID);
489       if (null!=sWrkA) Indexer.delete("k_bugs", sWrkA, oCnf, sBugGUID);
490     }
491     return delete(oConn, sBugGUID);
492   } // delete
493

494   // ----------------------------------------------------------
495

496   /**
497    * <p>Get Bug Numeric Identifier from Global Unique Identifier.</p>
498    * Each Bug is assigned a GUID. But, as GUID are 32 characters hexadecimals
499    * string very difficult to remember, each bug is also automatically assigned
500    * to an integer identifier. The bug numeric identifier is an alternative
501    * primary key.
502    * @param oConn Database Connection
503    * @param sBugId Bug GUID
504    * @return Bug Integer Identifier
505    * @throws SQLException
506    */

507   public static int getPgFromId(JDCConnection oConn, String JavaDoc sBugId) throws SQLException JavaDoc {
508     int iRetVal;
509     PreparedStatement JavaDoc oStmt;
510     ResultSet JavaDoc oRSet;
511
512     oStmt = oConn.prepareStatement("SELECT " + DB.pg_bug + " FROM " + DB.k_bugs + " WHERE " + DB.gu_bug + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
513     oStmt.setString(1, sBugId);
514     oRSet = oStmt.executeQuery();
515     if (oRSet.next())
516       iRetVal = oRSet.getInt(1);
517     else
518       iRetVal = -1;
519     oRSet.close();
520     oStmt.close();
521     return iRetVal;
522   } // getPgFromId
523

524   // ----------------------------------------------------------
525

526   /**
527    * <p>Get Bug Unique Identifier from its numeric identifier.</p>
528    * Each Bug is assigned a GUID. But, as GUID are 32 characters hexadecimals
529    * string very difficult to remember, each bug is also automatically assigned
530    * to an integer identifier. The bug numeric identifier is an alternative
531    * primary key.
532    * @param oConn Database Connection
533    * @param iBugPg Bug numeric identifier
534    * @param sWorkArea GUID
535    * @return Bug GUID or <b>null</b> if no bug with such numeric identifier is found at given WorkArea
536    * @throws SQLException
537    * @since 2.2
538    */

539   public static String JavaDoc getIdFromPg(JDCConnection oConn, int iBugPg, String JavaDoc sWorkArea) throws SQLException JavaDoc {
540     String JavaDoc sRetVal;
541     PreparedStatement JavaDoc oStmt;
542     ResultSet JavaDoc oRSet;
543
544     oStmt = oConn.prepareStatement("SELECT " + DB.gu_bug + " FROM " + DB.k_bugs +
545                                    " b WHERE b." + DB.pg_bug + "=? AND EXISTS " +
546                                    " (SELECT p." + DB.gu_project + " FROM " + DB.k_projects + " p WHERE b." + DB.gu_project + "=p." + DB.gu_project + " AND p." + DB.gu_owner + "=?)",
547                                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
548     oStmt.setInt(1, iBugPg);
549     oStmt.setString(2, sWorkArea);
550     oRSet = oStmt.executeQuery();
551     if (oRSet.next())
552       sRetVal = oRSet.getString(1);
553     else
554       sRetVal = null;
555     oRSet.close();
556     oStmt.close();
557
558     return sRetVal;
559   } // getIdFromPg
560

561   // **********************************************************
562
// Constantes Publicas
563

564   public static final short ClassId = 82;
565 }
566
Popular Tags