1 56 package org.objectstyle.cayenne.modeler; 57 58 import java.io.File ; 59 import java.util.ArrayList ; 60 import java.util.Comparator ; 61 import java.util.Enumeration ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 65 import javax.swing.JTree ; 66 import javax.swing.event.TreeSelectionEvent ; 67 import javax.swing.event.TreeSelectionListener ; 68 import javax.swing.tree.DefaultMutableTreeNode ; 69 import javax.swing.tree.MutableTreeNode ; 70 import javax.swing.tree.TreePath ; 71 import javax.swing.tree.TreeSelectionModel ; 72 73 import org.apache.commons.beanutils.PropertyUtils; 74 import org.apache.log4j.Logger; 75 import org.objectstyle.cayenne.access.DataDomain; 76 import org.objectstyle.cayenne.access.DataNode; 77 import org.objectstyle.cayenne.map.DataMap; 78 import org.objectstyle.cayenne.map.DbEntity; 79 import org.objectstyle.cayenne.map.Entity; 80 import org.objectstyle.cayenne.map.ObjEntity; 81 import org.objectstyle.cayenne.map.Procedure; 82 import org.objectstyle.cayenne.map.event.DataMapEvent; 83 import org.objectstyle.cayenne.map.event.DataMapListener; 84 import org.objectstyle.cayenne.map.event.DataNodeEvent; 85 import org.objectstyle.cayenne.map.event.DataNodeListener; 86 import org.objectstyle.cayenne.map.event.DbEntityListener; 87 import org.objectstyle.cayenne.map.event.DomainEvent; 88 import org.objectstyle.cayenne.map.event.DomainListener; 89 import org.objectstyle.cayenne.map.event.EntityEvent; 90 import org.objectstyle.cayenne.map.event.ObjEntityListener; 91 import org.objectstyle.cayenne.map.event.ProcedureEvent; 92 import org.objectstyle.cayenne.map.event.ProcedureListener; 93 import org.objectstyle.cayenne.map.event.QueryEvent; 94 import org.objectstyle.cayenne.map.event.QueryListener; 95 import org.objectstyle.cayenne.modeler.event.DataMapDisplayEvent; 96 import org.objectstyle.cayenne.modeler.event.DataMapDisplayListener; 97 import org.objectstyle.cayenne.modeler.event.DataNodeDisplayEvent; 98 import org.objectstyle.cayenne.modeler.event.DataNodeDisplayListener; 99 import org.objectstyle.cayenne.modeler.event.DbEntityDisplayListener; 100 import org.objectstyle.cayenne.modeler.event.DomainDisplayEvent; 101 import org.objectstyle.cayenne.modeler.event.DomainDisplayListener; 102 import org.objectstyle.cayenne.modeler.event.EntityDisplayEvent; 103 import org.objectstyle.cayenne.modeler.event.ObjEntityDisplayListener; 104 import org.objectstyle.cayenne.modeler.event.ProcedureDisplayEvent; 105 import org.objectstyle.cayenne.modeler.event.ProcedureDisplayListener; 106 import org.objectstyle.cayenne.modeler.event.QueryDisplayEvent; 107 import org.objectstyle.cayenne.modeler.event.QueryDisplayListener; 108 import org.objectstyle.cayenne.modeler.util.CellRenderers; 109 import org.objectstyle.cayenne.modeler.util.Comparators; 110 import org.objectstyle.cayenne.project.Project; 111 import org.objectstyle.cayenne.query.Query; 112 113 116 public class ProjectTreeView extends JTree implements DomainDisplayListener, 117 DomainListener, DataMapDisplayListener, DataMapListener, DataNodeDisplayListener, 118 DataNodeListener, ObjEntityListener, ObjEntityDisplayListener, DbEntityListener, 119 DbEntityDisplayListener, QueryListener, QueryDisplayListener, ProcedureListener, 120 ProcedureDisplayListener { 121 122 private static final Logger logObj = Logger.getLogger(ProjectTreeView.class); 123 124 protected ProjectController mediator; 125 protected TreeSelectionListener treeSelectionListener; 126 127 public ProjectTreeView(ProjectController mediator) { 128 super(); 129 this.mediator = mediator; 130 131 initView(); 132 initController(); 133 initFromModel(Application.getProject()); 134 } 135 136 private void initView() { 137 setCellRenderer(CellRenderers.treeRenderer()); 138 } 139 140 private void initController() { 141 treeSelectionListener = new TreeSelectionListener () { 142 143 public void valueChanged(TreeSelectionEvent e) { 144 processSelection(e.getPath()); 145 } 146 }; 147 148 addTreeSelectionListener(treeSelectionListener); 149 150 mediator.addDomainListener(this); 151 mediator.addDomainDisplayListener(this); 152 mediator.addDataNodeListener(this); 153 mediator.addDataNodeDisplayListener(this); 154 mediator.addDataMapListener(this); 155 mediator.addDataMapDisplayListener(this); 156 mediator.addObjEntityListener(this); 157 mediator.addObjEntityDisplayListener(this); 158 mediator.addDbEntityListener(this); 159 mediator.addDbEntityDisplayListener(this); 160 mediator.addProcedureListener(this); 161 mediator.addProcedureDisplayListener(this); 162 mediator.addQueryListener(this); 163 mediator.addQueryDisplayListener(this); 164 } 165 166 private void initFromModel(Project project) { 167 ProjectTreeModel model = new ProjectTreeModel(project); 169 setRootVisible(false); 170 setModel(model); 171 172 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 174 Enumeration level = model.getRootNode().children(); 175 while (level.hasMoreElements()) { 176 DefaultMutableTreeNode node = (DefaultMutableTreeNode ) level.nextElement(); 177 TreePath path = new TreePath (node.getPath()); 178 expandPath(path); 179 } 180 } 181 182 185 ProjectTreeModel getProjectModel() { 186 return (ProjectTreeModel) getModel(); 187 } 188 189 192 public String convertValueToText( 193 Object value, 194 boolean selected, 195 boolean expanded, 196 boolean leaf, 197 int row, 198 boolean hasFocus) { 199 200 while (value instanceof DefaultMutableTreeNode ) { 202 value = ((DefaultMutableTreeNode ) value).getUserObject(); 203 } 204 205 if (value instanceof String ) { 207 return value.toString(); 208 } 209 210 if (value instanceof Project) { 212 File f = ((Project) value).getMainFile(); 213 return (f != null) ? f.getPath() : ""; 214 } 215 216 try { 218 return (value != null) ? String.valueOf(PropertyUtils.getProperty( 219 value, 220 "name")) : ""; 221 222 } 223 catch (Exception e) { 224 String objectClass = (value == null) ? "(unknown)" : value 225 .getClass() 226 .getName(); 227 logObj.warn("Exception reading property 'name', class " + objectClass, e); 228 return ""; 229 } 230 } 231 232 public void currentDomainChanged(DomainDisplayEvent e) { 233 if ((e.getSource() == this || !e.isDomainChanged()) && !e.isRefired()){ 234 return; 235 } 236 237 showNode(new Object [] { 238 e.getDomain() 239 }); 240 } 241 242 public void currentDataNodeChanged(DataNodeDisplayEvent e) { 243 if ((e.getSource() == this || !e.isDataNodeChanged()) && !e.isRefired()){ 244 return; 245 } 246 247 showNode(new Object [] { 248 e.getDomain(), e.getDataNode() 249 }); 250 } 251 252 public void currentDataMapChanged(DataMapDisplayEvent e) { 253 if ((e.getSource() == this || !e.isDataMapChanged()) && !e.isRefired()){ 254 return; 255 } 256 257 showNode(new Object [] { 258 e.getDomain(), e.getDataMap() 259 }); 260 } 261 262 public void currentObjEntityChanged(EntityDisplayEvent e) { 263 e.setEntityChanged(true); 264 currentEntityChanged(e); 265 } 266 267 public void currentDbEntityChanged(EntityDisplayEvent e) { 268 e.setEntityChanged(true); 269 currentEntityChanged(e); 270 } 271 272 protected void currentEntityChanged(EntityDisplayEvent e) { 273 if ((e.getSource() == this || !e.isEntityChanged()) && !e.isRefired()) { 274 return; 275 } 276 277 showNode(new Object [] { 278 e.getDomain(), e.getDataMap(), e.getEntity() 279 }); 280 } 281 282 public void currentProcedureChanged(ProcedureDisplayEvent e) { 283 if ((e.getSource() == this || !e.isProcedureChanged()) && !e.isRefired()){ 284 return; 285 } 286 287 showNode(new Object [] { 288 e.getDomain(), e.getDataMap(), e.getProcedure() 289 }); 290 } 291 292 public void currentQueryChanged(QueryDisplayEvent e) { 293 if ((e.getSource() == this || !e.isQueryChanged()) && !e.isRefired()){ 294 return; 295 } 296 297 showNode(new Object [] { 298 e.getDomain(), e.getDataMap(), e.getQuery() 299 }); 300 } 301 302 public void procedureAdded(ProcedureEvent e) { 303 304 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath( 305 new Object [] { 306 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap() 307 }); 308 309 if (node == null) { 310 return; 311 } 312 313 Procedure procedure = e.getProcedure(); 314 DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode (procedure, false); 315 positionNode(node, currentNode, Comparators.getDataMapChildrenComparator()); 316 showNode(currentNode); 317 } 318 319 public void procedureChanged(ProcedureEvent e) { 320 if (e.isNameChange()) { 321 Object [] path = new Object [] { 322 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 323 e.getProcedure() 324 }; 325 326 updateNode(path); 327 positionNode(path, Comparators.getDataMapChildrenComparator()); 328 showNode(path); 329 } 330 } 331 332 public void procedureRemoved(ProcedureEvent e) { 333 334 removeNode(new Object [] { 335 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 336 e.getProcedure() 337 }); 338 } 339 340 public void queryAdded(QueryEvent e) { 341 342 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath( 343 new Object [] { 344 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap() 345 }); 346 347 if (node == null) { 348 return; 349 } 350 351 Query query = e.getQuery(); 352 DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode (query, false); 353 positionNode(node, currentNode, Comparators.getDataMapChildrenComparator()); 354 showNode(currentNode); 355 } 356 357 public void queryChanged(QueryEvent e) { 358 359 if (e.isNameChange()) { 360 Object [] path = new Object [] { 361 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 362 e.getQuery() 363 }; 364 365 updateNode(path); 366 positionNode(path, Comparators.getDataMapChildrenComparator()); 367 showNode(path); 368 } 369 } 370 371 public void queryRemoved(QueryEvent e) { 372 removeNode(new Object [] { 373 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 374 e.getQuery() 375 }); 376 } 377 378 public void domainChanged(DomainEvent e) { 379 380 Object [] path = new Object [] { 381 e.getDomain() 382 }; 383 384 updateNode(path); 385 386 if (e.isNameChange()) { 387 positionNode(path, Comparators.getNamedObjectComparator()); 388 showNode(path); 389 } 390 } 391 392 public void domainAdded(DomainEvent e) { 393 DataDomain dataDomain = e.getDomain(); 394 DefaultMutableTreeNode newNode = ProjectTreeModel.wrapProjectNode(dataDomain); 395 396 positionNode(null, newNode, Comparators.getNamedObjectComparator()); 397 showNode(newNode); 398 } 399 400 public void domainRemoved(DomainEvent e) { 401 removeNode(new Object [] { 402 e.getDomain() 403 }); 404 } 405 406 public void dataNodeChanged(DataNodeEvent e) { 407 408 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath( 409 new Object [] { 410 mediator.getCurrentDataDomain(), e.getDataNode() 411 }); 412 413 if (node != null) { 414 415 if (e.isNameChange()) { 416 positionNode((DefaultMutableTreeNode ) node.getParent(), node, Comparators 417 .getDataDomainChildrenComparator()); 418 showNode(node); 419 } 420 else { 421 422 getProjectModel().nodeChanged(node); 423 424 426 Object [] maps = e.getDataNode().getDataMaps().toArray(); 427 int mapCount = maps.length; 428 429 if (mapCount > node.getChildCount()) { 431 432 for (int i = 0; i < mapCount; i++) { 433 boolean found = false; 434 for (int j = 0; j < node.getChildCount(); j++) { 435 DefaultMutableTreeNode child = (DefaultMutableTreeNode ) node 436 .getChildAt(j); 437 if (maps[i] == child.getUserObject()) { 438 found = true; 439 break; 440 } 441 } 442 443 if (!found) { 444 DefaultMutableTreeNode newMapNode = new DefaultMutableTreeNode ( 445 maps[i], 446 false); 447 positionNode(node, newMapNode, Comparators 448 .getNamedObjectComparator()); 449 break; 450 } 451 } 452 } 453 else if (mapCount < node.getChildCount()) { 455 for (int j = 0; j < node.getChildCount(); j++) { 456 boolean found = false; 457 DefaultMutableTreeNode child; 458 child = (DefaultMutableTreeNode ) node.getChildAt(j); 459 Object obj = child.getUserObject(); 460 for (int i = 0; i < mapCount; i++) { 461 if (maps[i] == obj) { 462 found = true; 463 break; 464 } 465 } 466 if (!found) { 467 removeNode(child); 468 break; 469 } 470 } 471 } 472 } 473 } 474 } 475 476 public void dataNodeAdded(DataNodeEvent e) { 477 if (e.getSource() == this) { 478 return; 479 } 480 481 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath( 482 new Object [] { 483 mediator.getCurrentDataDomain() 484 }); 485 486 if (node == null) { 487 return; 488 } 489 490 DataNode dataNode = e.getDataNode(); 491 DefaultMutableTreeNode currentNode = ProjectTreeModel.wrapProjectNode(dataNode); 492 positionNode(node, currentNode, Comparators.getDataDomainChildrenComparator()); 493 showNode(currentNode); 494 } 495 496 public void dataNodeRemoved(DataNodeEvent e) { 497 if (e.getSource() == this) { 498 return; 499 } 500 501 removeNode(new Object [] { 502 mediator.getCurrentDataDomain(), e.getDataNode() 503 }); 504 } 505 506 public void dataMapChanged(DataMapEvent e) { 507 508 Object [] path = new Object [] { 509 mediator.getCurrentDataDomain(), e.getDataMap() 510 }; 511 512 updateNode(path); 513 514 if (e.isNameChange()) { 515 positionNode(path, Comparators.getDataDomainChildrenComparator()); 516 showNode(path); 517 } 518 } 519 520 public void dataMapAdded(DataMapEvent e) { 521 DefaultMutableTreeNode domainNode = getProjectModel().getNodeForObjectPath( 522 new Object [] { 523 mediator.getCurrentDataDomain() 524 }); 525 526 DefaultMutableTreeNode newMapNode = ProjectTreeModel.wrapProjectNode(e 527 .getDataMap()); 528 positionNode(domainNode, newMapNode, Comparators.getDataDomainChildrenComparator()); 529 showNode(newMapNode); 530 } 531 532 public void dataMapRemoved(DataMapEvent e) { 533 DataMap map = e.getDataMap(); 534 DataDomain domain = mediator.getCurrentDataDomain(); 535 536 removeNode(new Object [] { 537 domain, map 538 }); 539 540 Iterator nodes = new ArrayList (domain.getDataNodes()).iterator(); 542 while (nodes.hasNext()) { 543 removeNode(new Object [] { 544 domain, nodes.next(), map 545 }); 546 } 547 } 548 549 public void objEntityChanged(EntityEvent e) { 550 entityChanged(e); 551 } 552 553 public void objEntityAdded(EntityEvent e) { 554 entityAdded(e); 555 } 556 557 public void objEntityRemoved(EntityEvent e) { 558 entityRemoved(e); 559 } 560 561 public void dbEntityChanged(EntityEvent e) { 562 entityChanged(e); 563 } 564 565 public void dbEntityAdded(EntityEvent e) { 566 entityAdded(e); 567 } 568 569 public void dbEntityRemoved(EntityEvent e) { 570 entityRemoved(e); 571 } 572 573 581 protected void entityChanged(EntityEvent e) { 582 if (e.isNameChange()) { 583 Object [] path = new Object [] { 584 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 585 e.getEntity() 586 }; 587 588 updateNode(path); 589 positionNode(path, Comparators.getDataMapChildrenComparator()); 590 showNode(path); 591 } 592 } 593 594 598 protected void entityAdded(EntityEvent e) { 599 600 Entity entity = e.getEntity(); 601 602 DefaultMutableTreeNode mapNode = getProjectModel().getNodeForObjectPath( 603 new Object [] { 604 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap() 605 }); 606 607 if (mapNode == null) { 608 return; 609 } 610 611 DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode (entity, false); 612 positionNode(mapNode, currentNode, Comparators.getDataMapChildrenComparator()); 613 } 615 616 620 protected void entityRemoved(EntityEvent e) { 621 if (e.getSource() == this) { 622 return; 623 } 624 625 removeNode(new Object [] { 627 mediator.getCurrentDataDomain(), mediator.getCurrentDataMap(), 628 e.getEntity() 629 }); 630 } 631 632 636 protected void removeNode(DefaultMutableTreeNode toBeRemoved) { 637 638 Object selectedNode = null; 640 641 TreePath selectionPath = getSelectionPath(); 642 if (selectionPath != null) { 643 selectedNode = selectionPath.getLastPathComponent(); 644 } 645 646 if (toBeRemoved == selectedNode) { 647 648 DefaultMutableTreeNode newSelection = toBeRemoved.getNextSibling(); 650 if (newSelection == null) { 651 newSelection = toBeRemoved.getPreviousSibling(); 652 653 if (newSelection == null) { 655 newSelection = (DefaultMutableTreeNode ) toBeRemoved.getParent(); 656 657 if (newSelection == null) { 659 660 newSelection = toBeRemoved.getNextNode(); 661 if (newSelection == null) { 662 663 newSelection = toBeRemoved.getPreviousNode(); 664 } 665 } 666 } 667 } 668 669 showNode(newSelection); 670 } 671 672 getProjectModel().removeNodeFromParent(toBeRemoved); 674 } 675 676 677 protected void showNode(DefaultMutableTreeNode node) { 678 TreePath path = new TreePath (node.getPath()); 679 scrollPathToVisible(path); 680 setSelectionPath(path); 681 } 682 683 protected void showNode(Object [] path) { 684 if (path == null) { 685 return; 686 } 687 688 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath(path); 689 690 if (node == null) { 691 return; 692 } 693 694 this.showNode(node); 695 } 696 697 protected void updateNode(Object [] path) { 698 if (path == null) { 699 return; 700 } 701 702 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath(path); 703 if (node != null) { 704 getProjectModel().nodeChanged(node); 705 } 706 } 707 708 protected void removeNode(Object [] path) { 709 if (path == null) { 710 return; 711 } 712 713 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath(path); 714 if (node != null) { 715 removeNode(node); 716 } 717 } 718 719 724 public void processSelection(TreePath path) { 725 if (path == null) { 726 return; 727 } 728 729 DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode ) path 730 .getLastPathComponent(); 731 732 Object [] data = getUserObjects(currentNode); 733 if (data.length == 0) { 734 mediator.fireDomainDisplayEvent(new DomainDisplayEvent(this, null)); 736 return; 737 } 738 739 Object obj = data[data.length - 1]; 740 if (obj instanceof DataDomain) { 741 mediator 742 .fireDomainDisplayEvent(new DomainDisplayEvent(this, (DataDomain) obj)); 743 } 744 else if (obj instanceof DataMap) { 745 if (data.length == 3) { 746 mediator.fireDataMapDisplayEvent(new DataMapDisplayEvent( 747 this, 748 (DataMap) obj, 749 (DataDomain) data[data.length - 3], 750 (DataNode) data[data.length - 2])); 751 } 752 else if (data.length == 2) { 753 mediator.fireDataMapDisplayEvent(new DataMapDisplayEvent( 754 this, 755 (DataMap) obj, 756 (DataDomain) data[data.length - 2])); 757 } 758 } 759 else if (obj instanceof DataNode) { 760 if (data.length == 2) { 761 mediator.fireDataNodeDisplayEvent(new DataNodeDisplayEvent( 762 this, 763 (DataDomain) data[data.length - 2], 764 (DataNode) obj)); 765 } 766 } 767 else if (obj instanceof Entity) { 768 EntityDisplayEvent e = new EntityDisplayEvent(this, (Entity) obj); 769 e.setUnselectAttributes(true); 770 if (data.length == 4) { 771 e.setDataMap((DataMap) data[data.length - 2]); 772 e.setDomain((DataDomain) data[data.length - 4]); 773 e.setDataNode((DataNode) data[data.length - 3]); 774 } 775 else if (data.length == 3) { 776 e.setDataMap((DataMap) data[data.length - 2]); 777 e.setDomain((DataDomain) data[data.length - 3]); 778 } 779 780 if (obj instanceof ObjEntity) { 781 mediator.fireObjEntityDisplayEvent(e); 782 } 783 else if (obj instanceof DbEntity) { 784 mediator.fireDbEntityDisplayEvent(e); 785 } 786 } 787 else if (obj instanceof Procedure) { 788 ProcedureDisplayEvent e = new ProcedureDisplayEvent( 789 this, 790 (Procedure) obj, 791 (DataMap) data[data.length - 2], 792 (DataDomain) data[data.length - 3]); 793 mediator.fireProcedureDisplayEvent(e); 794 } 795 else if (obj instanceof Query) { 796 QueryDisplayEvent e = new QueryDisplayEvent( 797 this, 798 (Query) obj, 799 (DataMap) data[data.length - 2], 800 (DataDomain) data[data.length - 3]); 801 mediator.fireQueryDisplayEvent(e); 802 } 803 } 804 805 809 private Object [] getUserObjects(DefaultMutableTreeNode node) { 810 List list = new ArrayList (); 811 while (!node.isRoot()) { 812 list.add(0, node.getUserObject()); 813 node = (DefaultMutableTreeNode ) node.getParent(); 814 } 815 return list.toArray(); 816 } 817 818 private void positionNode(Object [] path, Comparator comparator) { 819 if (path == null) { 820 return; 821 } 822 823 DefaultMutableTreeNode node = getProjectModel().getNodeForObjectPath(path); 824 if (node == null) { 825 return; 826 } 827 828 positionNode(null, node, comparator); 829 } 830 831 private void positionNode( 832 MutableTreeNode parent, 833 DefaultMutableTreeNode treeNode, 834 Comparator comparator) { 835 836 removeTreeSelectionListener(treeSelectionListener); 837 try { 838 getProjectModel().positionNode(parent, treeNode, comparator); 839 } 840 finally { 841 addTreeSelectionListener(treeSelectionListener); 842 } 843 } 844 } | Popular Tags |