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