Source code: org/bdgp/apps/dagedit/datamodel/TermModel.java
1 package org.bdgp.apps.dagedit.datamodel;
2
3 import javax.swing.tree.*;
4 import javax.swing.event.*;
5 import javax.swing.undo.*;
6 import org.bdgp.cv.datamodel.*;
7 import org.bdgp.apps.dagedit.gui.Controller;
8 import org.bdgp.apps.dagedit.gui.event.*;
9 import org.bdgp.util.*;
10 import org.bdgp.io.*;
11 import org.bdgp.swing.*;
12 import java.util.*;
13 import java.io.Serializable;
14
15 public class TermModel extends PathTreeModel
16 implements MutableDAGModel, Serializable {
17 protected Term root;
18 protected Controller controller;
19 protected Vector listeners;
20 protected static org.bdgp.util.Comparator termSorter;
21
22 protected DETermReloadListener reloadListener = new DETermReloadListener() {
23 public void reload(DETermReloadEvent e) {
24 if (!e.getSource().equals(TermModel.this))
25 TermModel.this.reload();
26 }
27 };
28
29 public DETermReloadListener getReloadListener() {
30 return reloadListener;
31 }
32
33 protected static class CaseSensitiveTermSorter implements
34 org.bdgp.util.Comparator {
35
36 public int compare(Object a, Object b) {
37 Term terma = ((TermRelationship) a).getChild();
38 Term termb = ((TermRelationship) b).getChild();
39
40 int compval = terma.getTerm().compareTo(termb.getTerm());
41 if (compval < 0)
42 return -1;
43 else if (compval > 0)
44 return 1;
45 else
46 return 0;
47 }
48 }
49
50 protected static class CaseInsensitiveTermSorter implements
51 org.bdgp.util.Comparator {
52
53 public int compare(Object a, Object b) {
54 Term terma = ((TermRelationship) a).getChild();
55 Term termb = ((TermRelationship) b).getChild();
56
57 int compval = terma.getTerm().compareToIgnoreCase(termb.getTerm());
58 if (compval < 0)
59 return -1;
60 else if (compval > 0)
61 return 1;
62 else
63 return 0;
64 }
65 }
66
67 public TermModel(Controller in) {
68 this.listeners = new Vector();
69 setController(in);
70 setRootTerm(new Term("no data loaded"));
71 }
72
73 public TermModel(Term root, Controller in) {
74 this(in);
75 setRootTerm(root);
76 }
77
78 public void setRootTerm(Term root) {
79 this.root = root;
80 setRoot(new TermRelationship(root, null, null));
81 reload();
82 }
83
84 public void setController(Controller in) {
85 controller = in;
86 controller.addListener(new ReconfigListener() {
87 public void configReloaded(ReconfigEvent e) {
88 setSortMode(true);
89 }
90 });
91 setSortMode(false);
92 }
93
94 protected void setSortMode(boolean fireReload) {
95 if (controller.caseSensitiveSort())
96 termSorter = new CaseSensitiveTermSorter();
97 else
98 termSorter = new CaseInsensitiveTermSorter();
99 if (fireReload)
100 controller.fireReload(new DETermReloadEvent(this));
101 }
102
103 public TreePath [] copy(TreePath [] sources,
104 TreePath dest) {
105 DEEdit edit = new DEEdit("Copy", controller);
106
107 Term destNode = ((TermRelationship) dest.getLastPathComponent()).
108 getChild();
109 HistoryItem item = new TermCopyHistoryItem(destNode, sources);
110
111 TreePath [] out = new TreePath[sources.length];
112
113 StateEdit addChildrenEdit = new StateEdit(destNode);
114
115 for(int i=0; i < sources.length; i++) {
116 TermRelationship tr = (TermRelationship)
117 sources[i].getLastPathComponent();
118 Term sourceNode = tr.getChild();
119
120 StateEdit addParentEdit = new StateEdit(sourceNode);
121
122 destNode.addChild(sourceNode, tr.getType());
123
124 out[i] = dest.pathByAddingChild(tr);
125
126 addParentEdit.end();
127 edit.addEdit(addParentEdit);
128
129 }
130 addChildrenEdit.end();
131 edit.addEdit(addChildrenEdit);
132 edit.end();
133 edit.setHistoryItem(item);
134 controller.getUndoManager().addEdit(edit);
135 reloadAndFire();
136 edit.setSelections(sources, out);
137 return out;
138 }
139
140 public Object merge(TreePath master,
141 TreePath slave) {
142
143 DEEdit edit = new DEEdit("Merge", controller);
144
145 TreePath [] oldSelection = new TreePath[2];
146 oldSelection[0] = master;
147 oldSelection[1] = slave;
148
149 TermRelationship masterRel = (TermRelationship) master.
150 getLastPathComponent();
151 TermRelationship slaveRel = (TermRelationship) slave.
152 getLastPathComponent();
153
154 Term masterNode = masterRel.getChild();
155 Term slaveNode = slaveRel.getChild();
156
157 HistoryItem item = new TermMergeHistoryItem(masterNode,
158 slaveNode);
159
160 TermTextHistoryItem textEdits = new TermTextHistoryItem(masterNode,
161 new Vector());
162
163 StateEdit masterNodeEdit = new StateEdit(masterNode);
164 StateEdit slaveNodeEdit = new StateEdit(slaveNode);
165
166 // make a copy of slave's parent Vector
167 Vector slaveParents = (Vector) slaveNode.getParents().clone();
168
169 // remove the slave node from all slave parents, and replace it
170 // with the master node
171 for(int i=0; i < slaveParents.size(); i++) {
172 TermRelationship tr = (TermRelationship) slaveParents.elementAt(i);
173 Term slaveParent = tr.getParent();
174 StateEdit slaveParentEdit = new StateEdit(slaveParent);
175
176 slaveParent.removeChild(slaveNode);
177 slaveParent.addChild(masterNode, tr.getType());
178 slaveParentEdit.end();
179 edit.addEdit(slaveParentEdit);
180 }
181
182 // remove the slave node as parents of slave node's children,
183 // and add them to the master node
184 for(int i=0; i < slaveNode.getChildren().size(); i++) {
185 TermRelationship tr = (TermRelationship) slaveNode.
186 getChildren().elementAt(i);
187 Term slaveChild = tr.getChild();
188 StateEdit slaveChildEdit = new StateEdit(slaveChild);
189 slaveChild.removeParent(slaveNode);
190 masterNode.addChild(slaveChild, tr.getType());
191 slaveChildEdit.end();
192 edit.addEdit(slaveChildEdit);
193 }
194 slaveNode.removeAllChildren();
195
196 for(int i=0; i < slaveNode.getDbxrefs().size(); i++) {
197 Dbxref ref = (Dbxref) slaveNode.getDbxrefs().elementAt(i);
198 if (!masterNode.getDbxrefs().contains(ref)) {
199 Dbxref copy = (Dbxref) ref.clone();
200 masterNode.addDbxref(copy);
201 textEdits.addDbxref(copy.getDatabase(),
202 copy.getID(),
203 copy.getDesc(),
204 copy.getType());
205 }
206 }
207
208 for(int i=0; i < slaveNode.getSynonyms().size(); i++) {
209 Synonym ref = (Synonym) slaveNode.getSynonyms().elementAt(i);
210 if (!masterNode.getSynonyms().contains(ref)) {
211 Synonym copy = (Synonym) ref.clone();
212 masterNode.addSynonym(copy);
213 textEdits.addSynonym(copy);
214 }
215 }
216
217 masterNode.addSynonym(new Synonym(slaveNode.getID(),
218 slaveNode.getTerm()));
219
220 textEdits.addSynonym(new Synonym(slaveNode.getID(),
221 slaveNode.getTerm()));
222
223 ((TermMergeHistoryItem) item).setTextEdits(textEdits);
224
225 masterNodeEdit.end();
226 slaveNodeEdit.end();
227 edit.addEdit(masterNodeEdit);
228 edit.addEdit(slaveNodeEdit);
229 edit.end();
230 reloadAndFire();
231
232 TreePath [] newSelection = {master};
233
234 edit.setHistoryItem(item);
235 edit.setSelections(oldSelection, newSelection);
236 controller.getUndoManager().addEdit(edit);
237
238 return masterNode;
239 }
240
241 public TreePath addChild(TreePath target, Object child) {
242 return null;
243 }
244
245 public void delete(TreePath [] sources) {
246 HistoryItem item = new TermDeleteHistoryItem(sources);
247 DEEdit edit = new DEEdit("Delete", controller);
248 for(int i=0; i < sources.length; i++) {
249 TermRelationship tr = (TermRelationship) sources[i].
250 getLastPathComponent();
251 Term parent = tr.getParent();
252 Term child = tr.getChild();
253
254 StateEdit delChildEdit = new StateEdit(parent);
255 StateEdit delParentEdit = new StateEdit(child);
256
257 parent.removeChild(child);
258
259 delChildEdit.end();
260 delParentEdit.end();
261
262 edit.addEdit(delChildEdit);
263 edit.addEdit(delParentEdit);
264 }
265 edit.end();
266 edit.setHistoryItem(item);
267 controller.getUndoManager().addEdit(edit);
268 controller.fireTermSelect(new DETermSelectEvent(this, new Vector()));
269 if (sources.length > 0)
270 reloadAndFire();
271 edit.setSelections(sources, new TreePath[0]);
272 }
273
274 public void reload() {
275 populateModel();
276 trimModel(controller.getFilter());
277 sortModel();
278 fireTreeStructureChanged(new TreeModelEvent(this, new TreePath(root)));
279 }
280
281 protected void sortModel() {
282 Enumeration e = parentage.elements();
283 while(e.hasMoreElements()) {
284 Vector v = (Vector) e.nextElement();
285 v = VectorUtil.sort(v, termSorter);
286 }
287 }
288
289 public void reloadAndFire() {
290 // reload();
291 controller.fireReload(new DETermReloadEvent(this));
292 }
293
294 public TreePath [] move(TreePath [] sources,
295 TreePath dest) {
296 DEEdit edit = new DEEdit("Move", controller);
297
298 Term destNode = ((TermRelationship) dest.getLastPathComponent()).
299 getChild();
300
301 HistoryItem item = new TermMoveHistoryItem(destNode, sources);
302
303 TreePath [] out = new TreePath[sources.length];
304
305 StateEdit addChildrenEdit = new StateEdit(destNode);
306
307 for(int i=0; i < sources.length; i++) {
308 TermRelationship tr = (TermRelationship) sources[i].
309 getLastPathComponent();
310 Term sourceNode = tr.getChild();
311 Term parentNode = tr.getParent();
312
313 StateEdit removeParentEdit = new StateEdit(sourceNode);
314 StateEdit removeChildEdit = new StateEdit(parentNode);
315
316 parentNode.removeChild(sourceNode);
317 destNode.addChild(sourceNode, tr.getType());
318
319 out[i] = dest.pathByAddingChild(tr);
320
321 removeParentEdit.end();
322 removeChildEdit.end();
323 edit.addEdit(removeParentEdit);
324 edit.addEdit(removeChildEdit);
325
326
327 }
328 addChildrenEdit.end();
329 edit.addEdit(addChildrenEdit);
330 edit.end();
331 edit.setHistoryItem(item);
332 controller.getUndoManager().addEdit(edit);
333 reloadAndFire();
334 edit.setSelections(sources, out);
335 return out;
336 }
337
338 public void changeTermRelationship(TreePath [] sources,
339 TermRelationshipType type) {
340 TermRelationshipHistoryItem item =
341 new TermRelationshipHistoryItem(sources);
342 DEEdit edit = new DEEdit("Change relationship", controller);
343 for(int i=0; i < sources.length; i++) {
344 TermRelationship tr = (TermRelationship) sources[i].
345 getLastPathComponent();
346
347 Term parent = tr.getParent();
348 Term child = tr.getChild();
349
350 StateEdit delChildEdit = new StateEdit(parent);
351 StateEdit delParentEdit = new StateEdit(child);
352
353 tr.setType(type);
354 /*
355 tr = child.getRelationshipToParent(parent);
356 tr.setType(type);
357 */
358 delChildEdit.end();
359 delParentEdit.end();
360
361 edit.addEdit(delChildEdit);
362 edit.addEdit(delParentEdit);
363 }
364 edit.end();
365 item.setRelType(type);
366 edit.setHistoryItem(item);
367 controller.getUndoManager().addEdit(edit);
368 if (sources.length > 0)
369 reloadAndFire();
370 edit.setSelections(sources, sources);
371 }
372
373 public Object [] split(TreePath target) {
374 DEEdit edit = new DEEdit("Split", controller);
375 TermRelationship targetRel = (TermRelationship) target.
376 getLastPathComponent();
377 Term term = targetRel.getChild();
378 Term newTerm = new Term("<new term>");
379
380 try {
381 String [] ids = controller.getIDAdapter().
382 getIDs(root,
383 term,
384 controller.getDefaultPrefix(),
385 controller.getMinID(),
386 controller.getMaxID(),
387 controller.getIDLength(),
388 1);
389 if (ids.length > 0)
390 newTerm.setID(ids[0]);
391 else
392 newTerm.setID(null);
393 } catch (DataAdapterException e) {
394 newTerm.setID(null);
395 }
396
397 StateEdit newNodeEdit = new StateEdit(newTerm);
398
399 // copy children of term into newTerm
400 for(int i=0; i < term.getChildren().size(); i++) {
401 TermRelationship tr = (TermRelationship) term.
402 getChildren().elementAt(i);
403 Term child = tr.getChild();
404 StateEdit childEdit = new StateEdit(child);
405 newTerm.addChild(child, tr.getType());
406 childEdit.end();
407 edit.addEdit(childEdit);
408 }
409
410 // add newTerm into all parents of term
411 for(int i=0; i < term.getParents().size(); i++) {
412 TermRelationship tr = (TermRelationship) term.
413 getParents().elementAt(i);
414 Term parent = tr.getParent();
415 StateEdit parentEdit = new StateEdit(parent);
416 parent.addChild(newTerm, tr.getType());
417 parentEdit.end();
418 edit.addEdit(parentEdit);
419 }
420
421 for(int i=0; i < term.getDbxrefs().size(); i++) {
422 Dbxref ref = (Dbxref) term.getDbxrefs().elementAt(i);
423 Dbxref copy = (Dbxref) ref.clone();
424 newTerm.addDbxref(copy);
425 }
426
427 for(int i=0; i < term.getDefDbxrefs().size(); i++) {
428 Dbxref ref = (Dbxref) term.getDefDbxrefs().elementAt(i);
429 Dbxref copy = (Dbxref) ref.clone();
430 newTerm.addDefDbxref(copy);
431 }
432
433 for(int i=0; i < term.getSynonyms().size(); i++) {
434 Synonym ref = (Synonym) term.getSynonyms().elementAt(i);
435 Synonym copy = (Synonym) ref.clone();
436 newTerm.addSynonym(copy);
437 }
438
439 newNodeEdit.end();
440 edit.addEdit(newNodeEdit);
441 edit.end();
442
443 HistoryItem item = new TermSplitHistoryItem(term, newTerm);
444 edit.setHistoryItem(item);
445
446 controller.getUndoManager().addEdit(edit);
447 reloadAndFire();
448
449 TermRelationship newTermRel = new
450 TermRelationship(newTerm,
451 targetRel.getParent(),
452 targetRel.getType());
453
454 TreePath [] oldSelection = new TreePath[1];
455 oldSelection[0] = target;
456 TreePath [] newSelection = new TreePath[2];
457 newSelection[0] = target;
458 newSelection[1] = target.getParentPath().pathByAddingChild(newTermRel);
459
460 edit.setSelections(oldSelection, newSelection);
461
462 Object [] out = new Object[2];
463 out[0] = newTerm;
464 out[1] = term;
465
466 return out;
467 }
468
469 public TreePath add(TreePath target) {
470 DEEdit edit = new DEEdit("Add", controller);
471 TermRelationship parentRel = (TermRelationship) target.
472 getLastPathComponent();
473 Term term = parentRel.getChild();
474 Term newTerm = new Term("<new term>");
475
476 HistoryItem item = new TermAddHistoryItem(term, newTerm);
477
478 try {
479 String [] ids = controller.getIDAdapter().
480 getIDs(root,
481 term,
482 controller.getDefaultPrefix(),
483 controller.getMinID(),
484 controller.getMaxID(),
485 controller.getIDLength(),
486 1);
487 if (ids.length > 0)
488 newTerm.setID(ids[0]);
489 else
490 newTerm.setID(null);
491 } catch (DataAdapterException e) {
492 newTerm.setID(null);
493 }
494
495 StateEdit termEdit = new StateEdit(term);
496
497 TermRelationshipType trt = null;
498 if (controller != null)
499 trt = controller.getDefaultRelationshipType();
500
501 term.addChild(newTerm, trt);
502 TermRelationship newRelationship = new TermRelationship(newTerm,
503 term,
504 trt);
505 termEdit.end();
506
507 edit.addEdit(termEdit);
508 edit.end();
509 edit.setHistoryItem(item);
510 controller.getUndoManager().addEdit(edit);
511 reloadAndFire();
512
513 TreePath newPath = target.pathByAddingChild(newRelationship);
514
515 TreePath [] oldSelection = new TreePath[1];
516 oldSelection[0] = target;
517 TreePath [] newSelection = new TreePath[1];
518 newSelection[0] = newPath;
519
520 edit.setSelections(oldSelection, newSelection);
521
522 return newPath;
523 }
524
525 public int getParentCount(Object node) {
526 if (node instanceof Term) {
527 return ((Term) node).getParents().size();
528 } else
529 return -1;
530 }
531
532 public Object getParent(Object node, int index) {
533 if (node instanceof Term) {
534 return ((Term) node).getParents().elementAt(index);
535 } else
536 return null;
537 }
538
539 public int getIndexOfParent(Object child, Object parent) {
540 if (child instanceof Term) {
541 return ((Term) child).getParents().indexOf(parent);
542 } else
543 return -1;
544 }
545
546
547
548 protected void populateModel() {
549 parentage.clear();
550 TermRelationship tr = (TermRelationship) getRoot();
551 populateModel(tr);
552 }
553
554 protected void populateModel(TermRelationship rel) {
555 if (parentage.containsKey(rel))
556 return;
557 for(int i=0; i < rel.getChild().getChildren().size(); i++) {
558 TermRelationship tr = (TermRelationship) rel.getChild().
559 getChildren().elementAt(i);
560 addChild(rel, tr);
561 populateModel(tr);
562 }
563 }
564
565 protected void trimModel(VectorFilter filter) {
566 if (filter == null)
567 return;
568 Enumeration e = getAllLeaves();
569 HashSet set = new HashSet();
570 while(e.hasMoreElements()) {
571 TermRelationship tr = (TermRelationship) e.nextElement();
572 if (!filter.satisfies(tr)) {
573 trimNode(filter, tr, set);
574 }
575 }
576 }
577
578 private void trimNode(VectorFilter filter, Term term, HashSet set) {
579 for(int i=0; i < term.getParents().size(); i++) {
580 TermRelationship tr = (TermRelationship) term.getParents().
581 elementAt(i);
582 trimNode(filter, tr, set);
583 }
584 }
585
586 private void trimNode(VectorFilter filter,
587 TermRelationship tr,
588 HashSet set) {
589 if (!set.contains(tr) &&
590 !filter.satisfies(tr) &&
591 getChildCount(tr) == 0) {
592 set.add(tr);
593 for(int i=0; i < tr.getParent().getParents().size(); i++) {
594 TermRelationship parentRel = (TermRelationship) tr.getParent().
595 getParents().elementAt(i);
596 removeChild(parentRel, tr);
597 trimNode(filter, parentRel.getChild(), set);
598 }
599 }
600 }
601
602 public void addTreeModelListener(TreeModelListener l) {
603 listeners.addElement(l);
604 }
605
606 protected void fireTreeStructureChanged(TreeModelEvent e) {
607 for(int i=0; i < listeners.size(); i++) {
608 TreeModelListener tml = (TreeModelListener) listeners.elementAt(i);
609 tml.treeStructureChanged(e);
610 }
611 }
612
613 public void removeTreeModelListener(TreeModelListener l) {
614 listeners.removeElement(l);
615 }
616
617 public void valueForPathChanged(TreePath path, Object newVal) {
618 }
619 }