Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/bdgp/apps/dagedit/dataadapter/JDBCDataAdapter.java


1   package org.bdgp.apps.dagedit.dataadapter;
2   
3   import java.util.*;
4   import java.sql.*;
5   import java.text.*;
6   import org.bdgp.apps.dagedit.datamodel.*;
7   import org.bdgp.io.*;
8   import org.bdgp.util.*;
9   
10  public class JDBCDataAdapter extends AbstractDataAdapter
11      implements DEDataAdapterI {
12      private static int PERCENT_INC = 1;
13  
14      private String driver;
15      private String url;
16      private String username;
17      private String password;
18      private boolean driverLoaded = false;
19  
20      private String saveComment = null;
21  
22      private Term root_term;
23      private Hashtable allterms_hash;
24      private Hashtable databaseIDHash;
25  
26      private DEDataAdapterI idAdapter = this;
27  
28      boolean repopulate;
29  
30      protected static TermRelationshipType ISA_TYPE = new TermRelationshipType("ISA", "is a");
31      protected static TermRelationshipType PARTOF_TYPE =
32    new TermRelationshipType("PARTOF", "part of");
33      protected static TermRelationshipType DEVELOPS_FROM =
34    new TermRelationshipType("DEVELOPS_FROM", "develops from");
35  
36      private Hashtable catHash;
37      private Vector catList;
38      private Hashtable relTypeHash;
39      private Vector relTypeList;
40  
41      java.util.Date lastModified;
42      String lastUser;
43      String lastComment;
44      String lastVersion;
45  
46      public Vector getRelationshipTypes() throws DataAdapterException {
47    if (relTypeList == null) {
48        try {
49      Connection con = getConnection();
50      Statement stmt = con.createStatement();
51      buildRelTypeList(stmt);
52        } catch (Exception e) {
53      throw new DataAdapterException(e, "Couldn't load categories");
54        }
55    }
56    return relTypeList;
57      }
58  
59      public void setRepopulate(boolean repopulate) {
60    this.repopulate = repopulate;
61      }
62  
63      public String getName() {
64    return "GO mySQL database format";
65      }
66  
67      public String getType() {
68    return "mySQL database";
69      }
70  
71      public String [] getIDs(Term root, Term term, String prefix, int length,
72            int count)
73    throws DataAdapterException {
74    if (idAdapter == this) {
75        try {
76      Connection con = getConnection();
77      Statement stmt = con.createStatement();
78      stmt.executeUpdate("LOCK TABLES godb_meta_data WRITE");
79      ResultSet rs = stmt.executeQuery("select current_id "+
80               "from godb_meta_data");
81      rs.next();
82      int id = rs.getInt(1);
83      stmt.executeUpdate("update godb_meta_data set current_id = "+
84             (id + count));
85      stmt.executeUpdate("UNLOCK TABLES");
86      String [] out = new String[count];
87      for(int i=0; i < count; i++)
88          out[i] = Term.formatID(prefix, (id++), length);
89      return out;
90        } catch (Exception e) {
91      throw new DataAdapterException(e, "Couldn't generate new id");
92        }
93    } else
94        return idAdapter.getIDs(root, term, prefix, length, count);
95      }
96  
97      public String [] getIDs(Term root, Term term, String prefix,
98            int min, int max, int length, int count) 
99    throws DataAdapterException {
100   if (idAdapter == this)
101       return getIDs(root, term, prefix, length, count);
102   else
103       return idAdapter.getIDs(root, term, prefix, min, max, length,
104             count);
105     }
106 
107     private Hashtable buildIDHash(Statement stmt,
108           Term root) throws SQLException {
109   Hashtable accessionHash = root.getAllDescendantsHash(true);
110   Hashtable idHash = new Hashtable();
111   ResultSet resultSet = stmt.
112       executeQuery("select id, acc from term where is_obsolete = 0");
113   while(resultSet.next()) {
114       int id = resultSet.getInt("id");
115       String acc = resultSet.getInt("acc")+"";
116       Term term = (Term) accessionHash.get(acc);
117       if (term != null) {
118     idHash.put(term, new Integer(id));
119       }
120   }
121   return idHash;
122     }
123 
124     protected void clearDatabase(Statement stmt) throws SQLException {
125   stmt.executeUpdate("delete from dbxref");
126   stmt.executeUpdate("delete from edit_session");
127   stmt.executeUpdate("delete from node_operation");
128   stmt.executeUpdate("delete from structure_edit");
129   stmt.executeUpdate("delete from structure_edit_src");
130   stmt.executeUpdate("delete from synonym_edit");
131   stmt.executeUpdate("delete from term");
132   stmt.executeUpdate("delete from term2term");
133   stmt.executeUpdate("delete from term_category");
134   stmt.executeUpdate("delete from term_category_edit");
135   stmt.executeUpdate("delete from term_comment");
136   stmt.executeUpdate("delete from term_dbxref");
137   stmt.executeUpdate("delete from term_dbxref_edit");
138   stmt.executeUpdate("delete from term_definition");
139   stmt.executeUpdate("delete from term_synonym");
140   stmt.executeUpdate("delete from term_text_edit");
141     }
142 
143     public class ConflictException extends DataAdapterException {
144   private Vector conflictMessages;
145 
146   public ConflictException(String message) {
147       super(message);
148       conflictMessages = new Vector();
149   }
150 
151   public Vector getConflictMessages() {
152       return conflictMessages;
153   }
154 
155   public void setConflictMessages(Vector messages) {
156       conflictMessages = messages;
157   }
158 
159   public void addConflictMessage(ConflictException message) {
160       conflictMessages.addElement(message);
161   }
162 
163   public String formatConflictMessage() {
164       return formatConflictMessage(0).toString();
165   }
166 
167   private String getNSpaces(int n) {
168       StringBuffer out = new StringBuffer();
169       for(int i=0; i < n; i++)
170     out.append(' ');
171       return out.toString();
172   }
173 
174   private String formatConflictMessage(int spaceDepth) {
175       StringBuffer out = new StringBuffer();
176       out.append(getNSpaces(spaceDepth));
177       out.append(getMessage()+"\n");
178 
179       for(int i=0; i < conflictMessages.size(); i++) {
180     ConflictException ex = (ConflictException) conflictMessages.
181         elementAt(i);
182     out.append(ex.formatConflictMessage(spaceDepth+4));
183       }
184       return out.toString();
185   }
186     }
187 
188     /**
189      * Checks to see if two GO trees are in conflict
190      */
191     protected void checkConflicts(DEEditHistory history, Term currentRoot)
192   throws ConflictException {
193 
194   Hashtable originalTerms = history.getOriginalRoot().
195       getAllDescendantsHash(true);
196   Hashtable currentTerms = currentRoot.
197       getAllDescendantsHash(true);
198 
199   Hashtable checkList = new Hashtable();
200 
201   Vector conflictMessages = new Vector();
202 
203   for(int i=0; i < history.size(); i++) {
204       HistoryItem item = history.getItemAt(i);
205       for(int j=0; j < item.getTouchedNodes().size(); j++) {
206     Term temp = (Term) item.getTouchedNodes().elementAt(j);
207     Term node = (Term) originalTerms.
208       get(temp.getID()+"");
209     if (node == null) {
210         continue;
211     }
212     checkList.put(node, item);
213     Enumeration e = node.getAllDescendants();
214     while(e.hasMoreElements()) {
215         temp = (Term) e.nextElement();
216         Term originalVersion = (Term) originalTerms.
217       get(temp.getID()+"");
218         checkList.put(originalVersion, item);
219     }
220     e = node.getAllAncestors();
221     while(e.hasMoreElements()) {
222         temp = (Term) e.nextElement();
223         Term originalVersion = (Term) originalTerms.
224       get(temp.getID()+"");
225         checkList.put(originalVersion, item);
226     }
227       }
228   }
229 
230   Enumeration e = checkList.keys();
231   while(e.hasMoreElements()) {
232       Term checkMe = (Term) e.nextElement();
233       Term currentVersion = (Term) currentTerms.
234     get(checkMe.getID()+"");
235       if (currentVersion == null) {
236     conflictMessages.
237         addElement(new ConflictException("Node "+checkMe+
238                  " is no longer "+
239                  "in the database!"));
240     continue;
241       }
242       try {
243     checkSameRelationships(checkMe, currentVersion);
244       } catch (ConflictException ex) {
245     conflictMessages.addElement(ex);
246       }
247   }
248   if (conflictMessages.size() > 0) {
249       ConflictException ex = new ConflictException("Conflict detected!");
250       ex.setConflictMessages(conflictMessages);
251       throw ex;
252   }
253     }
254 
255     private String getPrettyTermName(Term term) {
256   return "\""+term.getTerm()+"\" ("+term.getID()+")";
257     }
258 
259     protected void checkSameRelationships(Term oldTerm,
260             Term newTerm)
261   throws ConflictException {
262   Vector conflicts = new Vector();
263   Term hasMore;
264   Term hasFewer;
265   boolean oldBigger;
266   if (oldTerm.getParents().size() >= newTerm.getParents().size()) {
267       hasMore = oldTerm;
268       hasFewer = newTerm;
269       oldBigger = true;
270   } else {
271       hasMore = newTerm;
272       hasFewer = oldTerm;
273       oldBigger = false;
274   }
275   for(int i=0; i < hasMore.getParents().size(); i++) {
276       TermRelationship tr1 = (TermRelationship) hasMore.
277     getParents().elementAt(i);
278       boolean noMatch = true;
279       for(int j=0; j < hasFewer.getParents().size(); j++) {
280     TermRelationship tr2 = (TermRelationship) hasMore.
281         getParents().elementAt(j);
282     if (tr1.getParent().getID().equals(tr2.getParent().getID())) {
283         noMatch = false;
284         break;
285     }
286       }
287       if (noMatch) {
288     String message;
289     if (oldBigger) {
290         message = "When database was loaded, "+
291       getPrettyTermName(oldTerm)+" had parent "+
292       getPrettyTermName(tr1.getParent())+", but that "+
293       "parent no longer exists.";
294     } else {
295         message = "When database was loaded, "+
296       getPrettyTermName(oldTerm)+" did not have parent "+
297       getPrettyTermName(tr1.getParent())+", but the "+
298       "current version does.";
299     }
300     conflicts.addElement(new ConflictException(message));
301       }
302   }
303 
304   if (oldTerm.getChildren().size() >= newTerm.getChildren().size()) {
305       hasMore = oldTerm;
306       hasFewer = newTerm;
307       oldBigger = true;
308   } else {
309       hasMore = newTerm;
310       hasFewer = oldTerm;
311       oldBigger = false;
312   }
313   for(int i=0; i < hasMore.getChildren().size(); i++) {
314       TermRelationship tr1 = (TermRelationship) hasMore.
315     getChildren().elementAt(i);
316       boolean noMatch = true;
317       for(int j=0; j < hasFewer.getChildren().size(); j++) {
318     TermRelationship tr2 = (TermRelationship) hasMore.
319         getChildren().elementAt(j);
320     if (tr1.getChild().getID().equals(tr2.getChild().getID())) {
321         noMatch = false;
322         break;
323     }
324       }
325       if (noMatch) {
326     String message;
327     if (oldBigger) {
328         message = "When database was loaded, "+
329       getPrettyTermName(oldTerm)+" had child "+
330       getPrettyTermName(tr1.getChild())+", but that "+
331       "child no longer exists.";
332     } else {
333         message = "When database was loaded, "+
334       getPrettyTermName(oldTerm)+" did not have child "+
335       getPrettyTermName(tr1.getChild())+", but the "+
336       "current version does.";
337     }
338     conflicts.addElement(new ConflictException(message));
339       }
340   }
341   if (conflicts.size() > 0) {
342       ConflictException ex = new
343     ConflictException("conflicts detected in "+
344           "versions of"+
345           getPrettyTermName(oldTerm));
346       ex.setConflictMessages(conflicts);
347       throw ex;
348   }
349     }
350 
351     private class OperationWrapper {
352   public int id = -1;
353   public int session_id = -1;
354   public int structure_edit_id = -1;
355   public int type;
356   public Term term;
357   public Term result;
358   public Vector sources = new Vector();
359   
360   public String toString() {
361       return type+" operation on "+
362     (term == null ? "null" : term.getID()) +
363     "\n"+
364     "with sources "+sources+"\n"+
365     "produced "+(result == null ? "null" : result.getID())+"\n"+
366     
367     "session_id = "+session_id+", op_id = "+id+", structure_edit_id = "+structure_edit_id;
368   }
369     }
370 
371     private HistoryItem getHistoryItem(OperationWrapper ow) {
372   if (ow.type == HistoryItem.STRUCTURAL_MOVE) {
373       return new TermMoveHistoryItem(ow.term, ow.sources);
374   } else if (ow.type == HistoryItem.STRUCTURAL_COPY) {
375       return new TermCopyHistoryItem(ow.term, ow.sources);
376   } else if (ow.type == HistoryItem.STRUCTURAL_ADD) {
377       return new TermAddHistoryItem(ow.term, ow.result);
378   } else if (ow.type == HistoryItem.STRUCTURAL_DELETE) {
379       return new TermDeleteHistoryItem(ow.sources);
380   } else if (ow.type == HistoryItem.TEXT_EDIT) {
381       return new TermTextHistoryItem(ow.term);
382   } else if (ow.type == HistoryItem.STRUCTURAL_REBUILD) {
383       return new TermRebuildHistoryItem();
384   } else if (ow.type == HistoryItem.STRUCTURAL_SPLIT) {
385       return new TermSplitHistoryItem(ow.term, ow.result);
386   } else if (ow.type == HistoryItem.STRUCTURAL_MERGE) {
387       // this is probably wrong
388       return new TermMergeHistoryItem(ow.term,
389               (Term) ow.sources.elementAt(0));
390   } else if (ow.type == HistoryItem.STRUCTURAL_COMMITANDOBSOLETE) {
391       return new TermCommitAndObsoleteHistoryItem(ow.term, ow.result);
392   } else if (ow.type == HistoryItem.REL_CHANGE) {
393       TermRelationshipHistoryItem item =
394     new TermRelationshipHistoryItem(ow.sources);
395       // needs to be fixed
396       return item;
397   } else
398       return null;
399     }
400 
401     protected TermRelationshipType getTypeForInt(int type_id) {
402   Enumeration keys = relTypeHash.keys();
403   while(keys.hasMoreElements()) {
404       TermRelationshipType type = (TermRelationshipType)
405     keys.nextElement();
406       int id = ((Integer) relTypeHash.get(type)).intValue();
407       if (type_id == id)
408     return type;
409   }
410   return null;
411     }
412 
413     protected int getIntForType(TermRelationshipType type) {
414   Integer integer = (Integer) relTypeHash.get(type);
415   return integer.intValue();
416     }
417 
418     public Vector getHistories() throws DataAdapterException {
419 
420   try {
421       Vector out = new Vector();
422       Connection con = getConnection();
423       Statement stmt = con.createStatement();
424       Term root = getRoot(false).getRoot();
425 
426       Hashtable sessionHash = new Hashtable();
427 
428       ResultSet resultSet = stmt.
429     executeQuery("select * from edit_session order by mod_time");
430       while(resultSet.next()) {
431     int id = resultSet.getInt("id");
432     String person = resultSet.getString("person");
433     long dateInt = resultSet.getInt("mod_time");
434     java.util.Date date = new java.util.Date(dateInt*1000);
435     String comment = resultSet.getString("session_comment");
436 
437     DEEditHistory history = new DEEditHistory(root, false);
438     history.setUser(person);
439     history.setDate(date);
440     history.setComment(comment);
441     out.addElement(history);
442     sessionHash.put(new Integer(id), history);
443       }
444 
445       resultSet = stmt.
446     executeQuery("select * from node_operation order by id");
447 
448       Hashtable operationHash = new Hashtable();
449       Vector operationList = new Vector();
450 
451       while(resultSet.next()) {
452     int id = resultSet.getInt("id");
453     int type = resultSet.getInt("type");
454     int term_id = resultSet.getInt("term_id");
455     int session_id = resultSet.getInt("edit_session_id");
456 
457     OperationWrapper ow = new OperationWrapper();
458     ow.id = id;
459     ow.type = type;
460     ow.session_id = session_id;
461     Term term = (Term) allterms_hash.get(new Integer(term_id));
462     ow.term = term;
463 
464     operationHash.put(new Integer(id), ow);
465     operationList.addElement(ow);
466       }
467 
468       resultSet = stmt.
469     executeQuery("select * from structure_edit");
470 
471       Hashtable structureHash = new Hashtable();
472 
473       while(resultSet.next()) {
474     int id = resultSet.getInt("id");
475     int op_id = resultSet.getInt("operation_id");
476     Integer term_output_id = (Integer) resultSet.
477         getObject("term_output_id");
478     Term result = null;
479     if (term_output_id != null) {
480         result = (Term) allterms_hash.
481       get(term_output_id);
482     }
483     OperationWrapper ow = (OperationWrapper)
484         operationHash.get(new Integer(op_id));
485     ow.result = result;
486     ow.structure_edit_id = id;
487 
488     structureHash.put(new Integer(id), ow);
489       }
490 
491       resultSet = stmt.
492     executeQuery("select * from structure_edit_src where implied = 0");
493 
494       while(resultSet.next()) {
495     int struct_id = resultSet.getInt("structure_edit_id");
496     OperationWrapper ow = (OperationWrapper)
497         structureHash.get(new Integer(struct_id));
498 
499 
500     Integer source_parent_id = (Integer) resultSet.
501         getObject("source_parent_id");
502     int source_term_id = resultSet.
503         getInt("source_term_id");
504     Integer source_type = (Integer) resultSet.
505         getObject("source_type");
506 
507     Term sourceTerm = (Term) allterms_hash.
508         get(new Integer(source_term_id));
509 
510     if (source_parent_id != null &&
511         source_type != null) {
512         Term parentTerm = (Term) allterms_hash.
513       get(source_parent_id);
514         TermRelationship tr =
515       new TermRelationship(sourceTerm,
516                parentTerm,
517                getTypeForInt(source_type.intValue()));
518         ow.sources.addElement(tr);
519     } else
520         ow.sources.addElement(sourceTerm);
521       }
522 
523       for(int i=0; i < operationList.size(); i++) {
524     OperationWrapper ow = (OperationWrapper) operationList.
525         elementAt(i);
526     HistoryItem item = getHistoryItem(ow);
527     DEEditHistory history = (DEEditHistory) sessionHash.
528         get(new Integer(ow.session_id));
529     if (history != null)
530         history.addItem(item);
531       }
532 
533       return out;
534   } catch (Exception e) {
535       e.printStackTrace();
536       throw new DataAdapterException(e, e.getMessage());
537   }
538     }
539 
540     public DEEditHistory write(DEEditHistory history) throws DataAdapterException {
541   Statement stmt = null;
542   try {
543       boolean reloadNeeded = true;
544       Connection con = getConnection();
545       stmt = con.createStatement();
546       
547       if (!repopulate) {
548     fireProgressEvent(new ProgressEvent(this, new Double(0),
549                 "Checking for "+
550                 "conflicts..."));
551 
552     ResultSet resultSet = stmt.
553         executeQuery("select person, mod_time, session_comment, "+
554          "id from edit_session order by id desc "+
555          "limit 1");
556     
557     if (resultSet.next()) {
558         int timeInt = resultSet.getInt("mod_time");
559         lastModified = new java.util.Date(((long) timeInt)*1000);
560     } else {
561         lastModified = null;
562     }
563 
564     if (history.getDate() != null && lastModified != null &&
565         history.getDate().equals(lastModified)) {
566         reloadNeeded = false;
567         System.err.println("No need to check conflicts; "+
568                "checkout date is same as last save "+
569                "date");
570     } else {
571         Term currentRoot = null;
572         try {
573       currentRoot = getRoot(false).getRoot();
574         } catch (DataAdapterException ex) {
575       throw new
576           DataAdapterException(ex.getSubThrowable(),
577              "Could not read terms from"+
578              " database during conflict"+
579              " detection.");
580         }
581         checkConflicts(history, currentRoot);
582     }
583       }
584 
585       stmt.executeUpdate("LOCK TABLES "+
586              "category READ, "+
587              "dbxref WRITE, "+
588              "edit_session WRITE, "+
589              "godb_meta_data WRITE, "+
590              "node_operation WRITE, "+
591              "relationship_type WRITE, "+
592              "structure_edit WRITE, "+
593              "structure_edit_src WRITE, "+
594              "synonym_edit WRITE, "+
595              "term WRITE, "+
596              "term2term WRITE, "+
597              "term_category WRITE, "+
598              "term_category_edit WRITE, "+
599              "term_comment WRITE, "+
600              "term_dbxref WRITE, "+
601              "term_dbxref_edit WRITE, "+
602              "term_definition WRITE, "+
603              "term_synonym WRITE, "+
604              "term_text_edit WRITE");
605 
606       // Make mySQL wait for an explicit commit
607       stmt.executeUpdate("SET AUTOCOMMIT=0");
608       stmt.executeUpdate("BEGIN");
609 
610       catHash = getCategoryIndex(stmt);
611       relTypeHash = getRelTypeIndex(stmt);
612 
613       stmt.executeUpdate("insert into "+
614              "edit_session(person, mod_time, session_comment) "+
615              "values "+
616              "('"+username+"', UNIX_TIMESTAMP(), "+
617              formatString(saveComment)+")");
618       
619       ResultSet resultSet = stmt.
620     executeQuery("select LAST_INSERT_ID()");
621       resultSet.next();
622       int session_id = resultSet.getInt(1);
623 
624       if (repopulate) {
625     fireProgressEvent(new ProgressEvent(this, new Double(0),
626                 "Clearing database..."));
627 
628     clearDatabase(stmt);
629 
630     databaseIDHash = new Hashtable();
631 
632     int root_id = writeSubtree(stmt, history.getRoot(), true);
633 
634     stmt.executeUpdate("insert into "+
635            "node_operation(type, term_id,"+
636            "edit_session_id) "+
637            "values "+
638            "("+HistoryItem.STRUCTURAL_REBUILD+","+
639            root_id+","+session_id+")");
640 
641     stmt.executeUpdate("update term "+
642            "set is_root = 1 "+
643            "where id = "+root_id);
644 
645     resultSet = stmt.executeQuery("select MAX(acc)+1 "+
646                 "from term");
647     resultSet.next();
648     int seed_acc = resultSet.getInt(1);
649 
650     stmt.executeUpdate("update godb_meta_data "+
651            "set current_id = "+seed_acc+","+
652            "date_created = UNIX_TIMESTAMP(),"+
653            "created_by = '"+username+"',"+
654            "creation_comment = "+
655            formatString(saveComment));
656 
657       } else {
658     databaseIDHash = buildIDHash(stmt, history.getRoot());
659     int historySize = history.size();
660     for(int i=0; i < historySize; i++) {
661         if ((historySize * PERCENT_INC < 100) ||
662       (i % (historySize * PERCENT_INC / 100) == 0)) {
663       fireProgressEvent(new ProgressEvent(this,
664              new Double(100 * i / historySize),
665              "Writing edit history..."));
666         }
667 
668         HistoryItem item = history.getItemAt(i);
669         if (item instanceof TermTextHistoryItem)
670       write(stmt, session_id, (TermTextHistoryItem) item);
671         else if (item instanceof TermCommitAndObsoleteHistoryItem)
672       write(stmt, session_id,
673             (TermCommitAndObsoleteHistoryItem) item);
674         else if (item instanceof TermAddHistoryItem)
675       write(stmt, session_id, (TermAddHistoryItem) item);
676         else if (item instanceof TermDeleteHistoryItem)
677       write(stmt, session_id, (TermDeleteHistoryItem) item);
678         else if (item instanceof TermMoveHistoryItem)
679       write(stmt, session_id, (TermMoveHistoryItem) item);
680         else if (item instanceof TermCopyHistoryItem)
681       write(stmt, session_id, (TermCopyHistoryItem) item);
682         else if (item instanceof TermRelationshipHistoryItem)
683       write(stmt, session_id,
684             (TermRelationshipHistoryItem) item);
685         else if (item instanceof TermSplitHistoryItem)
686       write(stmt, session_id,
687             (TermSplitHistoryItem) item);
688         else if (item instanceof TermMergeHistoryItem)
689       write(stmt, session_id,
690             (TermMergeHistoryItem) item);
691         else
692       System.err.println("Ignoring history item "+item);
693     }
694       }
695       stmt.executeUpdate("COMMIT");
696       stmt.executeUpdate("UNLOCK TABLES");
697       fireProgressEvent(new ProgressEvent(this, new Double(0),
698             "Loading current "+
699             "database..."));
700       if (reloadNeeded)
701     return getRoot();
702       else {
703     resultSet = stmt.
704         executeQuery("select person, mod_time, session_comment, "+
705          "id from edit_session order by id desc "+
706          "limit 1");
707     resultSet.next();
708     int timeInt = resultSet.getInt("mod_time");
709     lastModified = new java.util.Date(((long) timeInt)*1000);
710     history.setUser(username);
711     history.setDate(lastModified);
712     history.setComment(formatString(saveComment));
713     history.setVersion("next version");
714     return history;
715       }    
716   } catch (DataAdapterException e) {
717       try {
718     if (stmt != null) {
719         stmt.executeUpdate("ROLLBACK");
720         stmt.executeUpdate("UNLOCK TABLES");
721     }
722       } catch (Exception ex) {
723     System.err.println("Couldn't even roll back!");
724     ex.printStackTrace();
725       }
726       e.printStackTrace();
727       throw e;
728   } catch (Exception e) {
729       e.printStackTrace();
730       try {
731     if (stmt != null) {
732         stmt.executeUpdate("ROLLBACK");
733         stmt.executeUpdate("UNLOCK TABLES");
734     }
735       } catch (Exception ex) {
736     System.err.println("Couldn't even roll back!");
737     ex.printStackTrace();
738       }
739       throw new DataAdapterException(e, e.getMessage());
740   }
741     }
742 
743     public void delegateToIDAdapter(DEDataAdapterI idAdapter) {
744   this.idAdapter = idAdapter;
745     }
746 
747     public void write(Statement stmt,
748           int session_id,
749           TermMergeHistoryItem item)
750   throws SQLException {
751 
752   int target_id = getDatabaseIDForTerm(stmt, item.getTarget());
753   int slave_id = getDatabaseIDForTerm(stmt, item.getSlave());
754 
755   stmt.executeUpdate("insert into "+
756          "node_operation(type, term_id, edit_session_id) "+
757          "values "+
758          "("+item.getType()+","+
759          target_id+","+
760          session_id+")");
761 
762   ResultSet resultSet = stmt.
763       executeQuery("select LAST_INSERT_ID()");
764   resultSet.next();
765   int operation_id = resultSet.getInt(1);
766 
767   stmt.executeUpdate("insert into "+
768          "structure_edit(operation_id, term_id,"+
769          "term_output_id) "+
770          "values "+
771          "("+operation_id+","+target_id+",null)");
772   resultSet = stmt.
773       executeQuery("select LAST_INSERT_ID()");
774   resultSet.next();
775   int edit_id = resultSet.getInt(1);
776 
777   stmt.executeUpdate("insert into "+
778          "structure_edit_src(structure_edit_id,"+
779          "source_term_id) values "+
780          "("+edit_id+","+slave_id+")");
781 
782   
783   stmt.executeUpdate("delete from term2term "+
784          "where term1_id = "+slave_id+" OR "+
785          "term2_id = "+slave_id);
786 
787   stmt.executeUpdate("update term "+
788          "set is_obsolete = 1 "+
789          "where id = "+slave_id);
790 
791   Term slave = item.getOriginalSlave();
792   Term master = item.getOriginalMaster();
793 
794   TermTextHistoryItem textEdits = item.getTextEdits();
795   for(int i=0; i < textEdits.getChanges().size(); i++) {
796       Object o = textEdits.getChanges().elementAt(i);
797       if (o instanceof TermTextHistoryItem.SynonymEdit) {
798     writeSynonyms(stmt,
799             master,
800             (TermTextHistoryItem.SynonymEdit) o,
801             operation_id);
802       } else if (o instanceof TermTextHistoryItem.DbxrefEdit) {
803     writeDbxrefs(stmt,
804           master,
805           (TermTextHistoryItem.DbxrefEdit) o,
806           operation_id);
807       }
808   }
809 
810   for(int i=0; i < slave.getChildren().size(); i++) {
811       TermRelationship slaveChild =
812     (TermRelationship) slave.getChildren().elementAt(i);
813 
814       int slave_child_id =
815     getDatabaseIDForTerm(stmt,
816              slaveChild.getChild());
817       
818       stmt.executeUpdate("insert term2term(relationship_type_id,"+
819              "term1_id, term2_id) values "+
820              "("+getIntForType(slaveChild.getType())+","+
821              target_id+","+slave_child_id+")");
822   }
823 
824   for(int i=0; i < slave.getParents().size(); i++) {
825       TermRelationship slaveParent =
826     (TermRelationship) slave.getParents().elementAt(i);
827 
828       int slave_parent_id =
829     getDatabaseIDForTerm(stmt,
830              slaveParent.getParent());
831 
832       stmt.executeUpdate("insert term2term(relationship_type_id,"+
833              "term1_id, term2_id) values "+
834              "("+getIntForType(slaveParent.getType())+","+
835              slave_parent_id+","+target_id+")");
836   }
837 
838     }
839 
840     public void write(Statement stmt,
841           int session_id,
842           TermCommitAndObsoleteHistoryItem item)
843   throws SQLException {
844 
845   int target_id = getDatabaseIDForTerm(stmt, item.getTarget());
846 
847 
848   stmt.executeUpdate("insert into "+
849          "node_operation(type, term_id, edit_session_id) "+
850          "values "+
851          "('"+item.getType()+"',"+
852          target_id+","+
853          session_id+")");
854 
855   ResultSet resultSet = stmt.
856       executeQuery("select LAST_INSERT_ID()");
857   resultSet.next();
858   int operation_id = resultSet.getInt(1);
859 
860 
861   int result_id = writeTermAndRelationships(stmt, item.
862               getOriginalResult());
863 
864   stmt.executeUpdate("insert into "+
865          "structure_edit(operation_id, term_id,"+
866          "term_output_id) "+
867          "values "+
868          "("+operation_id+","+target_id+","+result_id+")");
869 
870   stmt.executeUpdate("delete from term2term "+
871          "where term1_id = "+target_id+" OR "+
872          "      term2_id = "+target_id);
873 
874   stmt.executeUpdate("update term "+
875          "set is_obsolete = 1 "+
876          "where id = "+target_id);
877     }
878 
879     protected void writeRelationships(Statement stmt, Term term)
880   throws SQLException {
881   int term_id = getDatabaseIDForTerm(stmt, term);
882   for(int i=0; i < term.getParents().size(); i++) {
883       TermRelationship tr = (TermRelationship) term.getParents().
884     elementAt(i);
885       int parent_id = getDatabaseIDForTerm(stmt, tr.getParent());
886       if (parent_id != -1)
887     stmt.executeUpdate("insert into term2term"+
888            "(relationship_type_id, term1_id, "+
889            "term2_id) values "+
890            "("+getIntForType(tr.getType())+","+
891            parent_id+","+term_id+")");
892   }
893 
894   for(int i=0; i < term.getChildren().size(); i++) {
895       TermRelationship tr = (TermRelationship) term.getChildren().
896     elementAt(i);
897       int child_id = getDatabaseIDForTerm(stmt, tr.getChild());
898       if (child_id != -1) {
899     String sql = "insert into term2term"+
900         "(relationship_type_id, term1_id, term2_id) "+
901         "values "+
902         "("+getIntForType(tr.getType())+","+
903         term_id+","+child_id+")";
904     stmt.executeUpdate(sql);
905       }
906   }
907     }
908 
909     protected int writeSubtree(Statement stmt, Term term,
910              boolean fireProgressEvents)
911   throws SQLException {
912   int root_id = -1;
913   Hashtable descendants = term.getAllDescendantsHash(true);
914 
915   int total = descendants.size() * 2;
916 
917   Enumeration e = descendants.elements();
918 
919   int writes = 0;
920   while(e.hasMoreElements()) {
921       Term t = (Term) e.nextElement();
922       int term_id = writeTerm(stmt, t);
923       if (term == t)
924     root_id = term_id;
925       writes++;
926       if (fireProgressEvents &&
927     ((total * PERCENT_INC < 100) ||
928      (writes % (total * PERCENT_INC / 100) == 0))) {
929     fireProgressEvent(
930            new ProgressEvent(this,
931            new Double(100 * writes / total),
932            "Repopulating database..."));
933       }
934   }
935   e = descendants.elements();
936   while(e.hasMoreElements()) {
937       Term t = (Term) e.nextElement();
938       int term_id = getDatabaseIDForTerm(stmt, t);
939       for(int i=0; i < t.getChildren().size(); i++) {
940     TermRelationship tr = (TermRelationship) t.getChildren().
941         elementAt(i);
942     int child_id = getDatabaseIDForTerm(stmt, tr.getChild());
943     if (child_id != -1) {
944         String sql = "insert into term2term"+
945       "(relationship_type_id, term1_id, term2_id) "+
946       "values "+
947       "("+getIntForType(tr.getType())+","+
948       term_id+","+child_id+")";
949         stmt.executeUpdate(sql);
950     }
951       }
952       writes++;
953       if (fireProgressEvents &&
954     ((total * PERCENT_INC < 100) ||
955      (writes % (total * PERCENT_INC / 100) == 0))) {
956     fireProgressEvent(
957            new ProgressEvent(this,
958            new Double(100 * writes / total),
959            "Repopulating database..."));
960       }
961   }
962   return root_id;
963     }
964 
965     protected int writeTermAndRelationships(Statement stmt, Term term)
966   throws SQLException {
967   int term_id = writeTerm(stmt, term);
968   writeRelationships(stmt, term);
969   return term_id;
970     }
971 
972     protected int writeTerm(Statement stmt, Term term) throws SQLException {
973   
974   if (term.getID() == null) {
975       try {
976     String prefix = "GO";
977     if (term.getIDPrefix() != null)
978         prefix = term.getIDPrefix();
979     String [] ids = idAdapter.getIDs(null, null,
980              prefix, 7,
981              1);
982     if (ids.length > 0)
983         term.setID(ids[0]);
984       } catch (DataAdapterException e) {
985     System.err.println("This should never, ever happen");
986       }
987   }
988       
989   String sql = "insert into term(name, term_type, acc,"+
990       "is_obsolete, is_root) values "+
991       "("+formatString(term.getTerm())+","+
992       "'who cares',"+
993       term.getIDSuffix()+",0,0)";
994 
995   stmt.executeUpdate(sql);
996 
997   ResultSet resultSet = stmt.
998       executeQuery("select LAST_INSERT_ID()");
999   resultSet.next();
1000  int term_id = resultSet.getInt(1);
1001
1002  for(int i=0; i < term.getDbxrefs().size(); i++) {
1003      Dbxref ref = (Dbxref) term.getDbxrefs().elementAt(i);
1004      String typeString = Dbxref.
1005    getTypeStringFromInt(ref.getType());
1006
1007      sql = "select id "+
1008    "from dbxref "+
1009    "where "+
1010    "xref_key = "+
1011    formatString(ref.getID())+" AND "+
1012    "xref_keytype = "+
1013    formatString(typeString)+" AND "+
1014    "xref_dbname = "+
1015    formatString(ref.getDatabase());
1016
1017      resultSet = stmt.executeQuery(sql);
1018
1019      int dbxref_id = -1;
1020      if (resultSet.next()) {
1021    dbxref_id = resultSet.getInt(1);
1022      } else {
1023    sql = "insert into dbxref "+
1024        "(xref_key, xref_keytype, xref_dbname) "+
1025        "values "+
1026        "("+formatString(ref.getID())+","+
1027        formatString(typeString)+","+
1028        formatString(ref.getDatabase())+")";
1029
1030    stmt.executeUpdate(sql);
1031
1032    resultSet = stmt.
1033        executeQuery("select LAST_INSERT_ID()");
1034    resultSet.next();
1035    dbxref_id = resultSet.getInt(1);
1036      }
1037      stmt.executeUpdate("insert into term_dbxref "+
1038             "(term_id, dbxref_id) "+
1039             "values "+
1040             "("+term_id+","+dbxref_id+")");
1041  }
1042
1043  for(int i=0; i < term.getSynonyms().size(); i++) {
1044      Synonym s = (Synonym) term.getSynonyms().elementAt(i);
1045      stmt.executeUpdate("insert into term_synonym(term_id, term_synonym, acc_synonym) "+
1046             "values "+
1047             "("+term_id+","+
1048             formatString(s.getText())+","+
1049             formatString(s.getID())+")");
1050  }
1051
1052  if (term.getDefinition() != null && term.getDefinition().length() > 0) {
1053      stmt.executeUpdate("insert into term_definition(term_id,"+
1054             "term_definition) "+
1055             "values "+
1056             "("+term_id+","+
1057             formatString(term.getDefinition())+")");
1058  }
1059
1060  if (term.getComment() != null && term.getComment().length() > 0) {
1061      stmt.executeUpdate("insert into term_comment(term_id,"+
1062             "comment_text) "+
1063             "values "+
1064             "("+term_id+","+
1065             formatString(term.getComment())+")");
1066  }
1067
1068  stmt.executeUpdate("delete from term_category "+
1069         "where term_id = "+term_id);
1070
1071  for(int i=0; i < term.getCategories().size(); i++) {
1072      TermCategory cat = (TermCategory)
1073    term.getCategories().elementAt(i);
1074      int catID = ((Integer) catHash.get(cat.getName())).intValue();
1075      stmt.executeUpdate("insert into term_category "+
1076             "(term_id, category_id) values "+
1077             "("+term_id+", "+catID+")");
1078      
1079  }
1080
1081  return term_id;
1082    }
1083
1084    public void write(Statement stmt,
1085          int session_id,
1086          TermSplitHistoryItem item) throws SQLException {
1087
1088  int target_id = getDatabaseIDForTerm(stmt, item.getTarget());
1089
1090  stmt.executeUpdate("insert into "+
1091         "node_operation(type, term_id, edit_session_id) "+
1092         "values "+
1093         "('"+item.getType()+"',"+
1094         target_id+","+
1095         session_id+")");
1096
1097  ResultSet resultSet = stmt.
1098      executeQuery("select LAST_INSERT_ID()");
1099  resultSet.next();
1100  int operation_id = resultSet.getInt(1);
1101
1102  int term_id = writeTermAndRelationships(stmt,
1103            item.getOriginalResult());
1104
1105  stmt.executeUpdate("insert into "+
1106         "structure_edit(operation_id, term_id,"+
1107         "term_output_id) "+
1108         "values "+
1109         "("+operation_id+","+target_id+","+term_id+")");
1110    }
1111
1112    public void write(Statement stmt,
1113          int session_id,
1114          TermCopyHistoryItem item) throws SQLException {
1115
1116  int target_id = getDatabaseIDForTerm(stmt, item.getTarget());
1117
1118  stmt.executeUpdate("insert into "+
1119         "node_operation(type, term_id, edit_session_id) "+
1120         "values "+
1121         "('"+item.getType()+"',"+
1122         target_id+","+
1123         session_id+")");
1124
1125  ResultSet resultSet = stmt.
1126      executeQuery("select LAST_INSERT_ID()");
1127  resultSet.next();
1128  int operation_id = resultSet.getInt(1);
1129
1130  stmt.executeUpdate("insert into "+
1131         "structure_edit(operation_id, term_id,"+
1132         "term_output_id) "+
1133         "values "+
1134         "("+operation_id+","+target_id+", null)");
1135  resultSet = stmt.
1136      executeQuery("select LAST_INSERT_ID()");
1137  resultSet.next();
1138  int structure_edit_id = resultSet.getInt(1);
1139
1140  for(int i=0; i < item.getTerms().size(); i++) {
1141      Term term = (Term) item.
1142    getTerms().elementAt(i);
1143
1144      int term_id = getDatabaseIDForTerm(stmt, term);
1145
1146      stmt.executeUpdate("insert into term2term "+
1147             "(relationship_type_id, term1_id, term2_id, "+
1148             " is_obsolete) values "+
1149             "("+getIntForType(ISA_TYPE)+","+target_id+","+
1150             term_id+",0)");
1151      stmt.executeUpdate("insert into structure_edit_src"+
1152             "(structure_edit_id, source_parent_id,"+
1153             "source_term_id) values "+
1154             "("+structure_edit_id+",null,"+
1155             term_id+")");
1156  }
1157    }
1158
1159    public void write(Statement stmt,
1160          int session_id,
1161          TermMoveHistoryItem item) throws SQLException {
1162
1163  int target_id = getDatabaseIDForTerm(stmt, item.getTarget());
1164
1165  stmt.executeUpdate("insert into "+
1166         "node_operation(type, term_id, edit_session_id) "+
1167         "values "+
1168         "('"+item.getType()+"',"+
1169         target_id+","+
1170         session_id+")");
1171
1172  ResultSet resultSet = stmt.
1173      executeQuery("select LAST_INSERT_ID()");
1174  resultSet.next();
1175  int operation_id = resultSet.getInt(1);
1176
1177  stmt.executeUpdate("insert into "+
1178         "structure_edit(operation_id, term_id,"+
1179         "term_output_id) "+
1180         "values "+
1181         "("+operation_id+","+target_id+", null)");
1182  resultSet = stmt.
1183      executeQuery("select LAST_INSERT_ID()");
1184  resultSet.next();
1185  int structure_edit_id = resultSet.getInt(1);
1186
1187  for(int i=0; i < item.getMovedRelationships().size(); i++) {
1188      TermRelationship tr = (TermRelationship) item.
1189    getMovedRelationships().elementAt(i);
1190
1191      int parent_id = getDatabaseIDForTerm(stmt, tr.getParent());
1192      int item_id = getDatabaseIDForTerm(stmt, tr.getChild());
1193
1194      stmt.executeUpdate("delete from term2term "+
1195             "where term1_id = "+parent_id+" AND "+
1196             "term2_id = "+item_id+" AND "+
1197             "relationship_type_id = "+getIntForType(tr.getType()));
1198      stmt.executeUpdate("insert into term2term "+
1199             "(relationship_type_id, term1_id, term2_id, "+
1200             " is_obsolete) values "+
1201             "("+getIntForType(tr.getType())+","+target_id+","+
1202             item_id+",0)");
1203      stmt.executeUpdate("insert into structure_edit_src"+
1204             "(structure_edit_id, source_parent_id,"+
1205             "source_term_id, source_type) values "+
1206             "("+structure_edit_id+","+parent_id+","+
1207             item_id+","+getIntForType(tr.getType())+")");
1208  }
1209    }
1210
1211    private void buildImpliedDeletes(Term term,
1212             Vector deleted,
1213             Vector impliedDeletes) {
1214  for(int i=0; i < term.getParents().size(); i++) {
1215      TermRelationship tr = (TermRelationship) term.getParents().
1216    elementAt(i);
1217      if (!deleted.contains(tr) && !impliedDeletes.contains(tr))
1218    return;
1219  }
1220  for(int i=0; i < term.getChildren().size(); i++) {
1221      TermRelationship tr = (TermRelationship) term.getChildren().
1222    elementAt(i);
1223      if (!deleted.contains(tr))
1224    impliedDeletes.addElement(tr);
1225  }
1226  for(int i=0; i < term.getChildren().size(); i++) {
1227      TermRelationship tr = (TermRelationship) term.getChildren().
1228    elementAt(i);
1229      b