| 1 56 package org.objectstyle.cayenne.modeler; 57 58 import java.awt.Component ; 59 import java.util.ArrayList ; 60 import java.util.EventListener ; 61 import java.util.EventObject ; 62 import java.util.Iterator ; 63 64 import javax.swing.event.EventListenerList ; 65 66 import org.objectstyle.cayenne.CayenneRuntimeException; 67 import org.objectstyle.cayenne.access.DataDomain; 68 import org.objectstyle.cayenne.access.DataNode; 69 import org.objectstyle.cayenne.map.DataMap; 70 import org.objectstyle.cayenne.map.DbAttribute; 71 import org.objectstyle.cayenne.map.DbEntity; 72 import org.objectstyle.cayenne.map.DbRelationship; 73 import org.objectstyle.cayenne.map.ObjAttribute; 74 import org.objectstyle.cayenne.map.ObjEntity; 75 import org.objectstyle.cayenne.map.ObjRelationship; 76 import org.objectstyle.cayenne.map.Procedure; 77 import org.objectstyle.cayenne.map.ProcedureParameter; 78 import org.objectstyle.cayenne.map.event.AttributeEvent; 79 import org.objectstyle.cayenne.map.event.DataMapEvent; 80 import org.objectstyle.cayenne.map.event.DataMapListener; 81 import org.objectstyle.cayenne.map.event.DataNodeEvent; 82 import org.objectstyle.cayenne.map.event.DataNodeListener; 83 import org.objectstyle.cayenne.map.event.DbAttributeListener; 84 import org.objectstyle.cayenne.map.event.DbEntityListener; 85 import org.objectstyle.cayenne.map.event.DbRelationshipListener; 86 import org.objectstyle.cayenne.map.event.DomainEvent; 87 import org.objectstyle.cayenne.map.event.DomainListener; 88 import org.objectstyle.cayenne.map.event.EntityEvent; 89 import org.objectstyle.cayenne.map.event.ObjAttributeListener; 90 import org.objectstyle.cayenne.map.event.ObjEntityListener; 91 import org.objectstyle.cayenne.map.event.ObjRelationshipListener; 92 import org.objectstyle.cayenne.map.event.ProcedureEvent; 93 import org.objectstyle.cayenne.map.event.ProcedureListener; 94 import org.objectstyle.cayenne.map.event.ProcedureParameterEvent; 95 import org.objectstyle.cayenne.map.event.ProcedureParameterListener; 96 import org.objectstyle.cayenne.map.event.QueryEvent; 97 import org.objectstyle.cayenne.map.event.QueryListener; 98 import org.objectstyle.cayenne.map.event.RelationshipEvent; 99 import org.objectstyle.cayenne.modeler.action.NavigateBackwardAction; 100 import org.objectstyle.cayenne.modeler.action.NavigateForwardAction; 101 import org.objectstyle.cayenne.modeler.action.RevertAction; 102 import org.objectstyle.cayenne.modeler.action.SaveAction; 103 import org.objectstyle.cayenne.modeler.event.AttributeDisplayEvent; 104 import org.objectstyle.cayenne.modeler.event.DataMapDisplayEvent; 105 import org.objectstyle.cayenne.modeler.event.DataMapDisplayListener; 106 import org.objectstyle.cayenne.modeler.event.DataNodeDisplayEvent; 107 import org.objectstyle.cayenne.modeler.event.DataNodeDisplayListener; 108 import org.objectstyle.cayenne.modeler.event.DbAttributeDisplayListener; 109 import org.objectstyle.cayenne.modeler.event.DbEntityDisplayListener; 110 import org.objectstyle.cayenne.modeler.event.DbRelationshipDisplayListener; 111 import org.objectstyle.cayenne.modeler.event.DisplayEvent; 112 import org.objectstyle.cayenne.modeler.event.DomainDisplayEvent; 113 import org.objectstyle.cayenne.modeler.event.DomainDisplayListener; 114 import org.objectstyle.cayenne.modeler.event.EntityDisplayEvent; 115 import org.objectstyle.cayenne.modeler.event.ObjAttributeDisplayListener; 116 import org.objectstyle.cayenne.modeler.event.ObjEntityDisplayListener; 117 import org.objectstyle.cayenne.modeler.event.ObjRelationshipDisplayListener; 118 import org.objectstyle.cayenne.modeler.event.ProcedureDisplayEvent; 119 import org.objectstyle.cayenne.modeler.event.ProcedureDisplayListener; 120 import org.objectstyle.cayenne.modeler.event.ProcedureParameterDisplayEvent; 121 import org.objectstyle.cayenne.modeler.event.ProcedureParameterDisplayListener; 122 import org.objectstyle.cayenne.modeler.event.QueryDisplayEvent; 123 import org.objectstyle.cayenne.modeler.event.QueryDisplayListener; 124 import org.objectstyle.cayenne.modeler.event.RelationshipDisplayEvent; 125 import org.objectstyle.cayenne.modeler.pref.DataMapDefaults; 126 import org.objectstyle.cayenne.modeler.pref.DataNodeDefaults; 127 import org.objectstyle.cayenne.modeler.util.CayenneController; 128 import org.objectstyle.cayenne.modeler.util.CircularArray; 129 import org.objectstyle.cayenne.pref.Domain; 130 import org.objectstyle.cayenne.project.Project; 131 import org.objectstyle.cayenne.query.Query; 132 import org.objectstyle.cayenne.util.IDUtil; 133 134 143 public class ProjectController extends CayenneController { 144 145 149 public class ControllerState { 150 private boolean isRefiring; 151 private DisplayEvent event; 152 private DataDomain domain; 153 private DataNode node; 154 private DataMap map; 155 private ObjEntity objEntity; 156 private DbEntity dbEntity; 157 private ObjAttribute objAttr; 158 private DbAttribute dbAttr; 159 private ObjRelationship objRel; 160 private DbRelationship dbRel; 161 private Procedure procedure; 162 private ProcedureParameter procedureParameter; 163 private Query query; 164 165 public ControllerState(){ 166 domain = null; 167 node = null; 168 map = null; 169 170 objEntity = null; 171 objAttr = null; 172 objRel = null; 173 174 dbEntity = null; 175 dbAttr = null; 176 dbRel = null; 177 178 procedure = null; 179 procedureParameter = null; 180 181 query = null; 182 183 event = null; 184 isRefiring = false; 185 } 186 187 193 public boolean isEquivalent(ControllerState val){ 194 if (val == null) return false; 195 196 if (event instanceof EntityDisplayEvent && val.event instanceof EntityDisplayEvent){ 197 if (((EntityDisplayEvent)val.event).getEntity() instanceof ObjEntity){ 198 return objEntity == val.objEntity; 199 } 200 else { 201 return dbEntity == val.dbEntity; 202 } 203 } 204 else if (event instanceof ProcedureDisplayEvent && val.event instanceof ProcedureDisplayEvent){ 205 return procedure == val.procedure; 206 } 207 else if (event instanceof QueryDisplayEvent && val.event instanceof QueryDisplayEvent){ 208 return query == val.query; 209 } 210 else if (event.getClass() == DataMapDisplayEvent.class && event.getClass() == val.event.getClass()){ 211 return map == val.map; 212 } 213 else if (event.getClass() == DataNodeDisplayEvent.class && event.getClass() == val.event.getClass()){ 214 return node == val.node; 215 } 216 else if (event.getClass() == DomainDisplayEvent.class && event.getClass() == val.event.getClass()){ 217 return domain == val.domain; 218 } 219 return false; 220 } 221 } 222 223 protected EventListenerList listenerList; 224 protected boolean dirty; 225 226 protected Project project; 227 protected Domain projectPreferences; 228 229 protected ControllerState currentState; 230 protected CircularArray controllerStateHistory; 231 protected int maxHistorySize = 20; 232 233 public ProjectController(CayenneModelerController parent) { 234 super(parent); 235 this.listenerList = new EventListenerList (); 236 controllerStateHistory = new CircularArray(maxHistorySize); 237 currentState = new ControllerState(); 238 } 239 240 public Component getView() { 241 return parent.getView(); 242 } 243 244 public Project getProject() { 245 return project; 246 } 247 248 public void setProject(Project currentProject) { 249 this.project = currentProject; 250 this.projectPreferences = null; 251 } 252 253 256 public Domain getApplicationPreferenceDomain() { 257 return getApplication().getPreferenceDomain(); 258 } 259 260 264 public Domain getPreferenceDomainForProject() { 265 Project project = getProject(); 266 if (project == null) { 267 throw new CayenneRuntimeException("No Project selected"); 268 } 269 270 if (projectPreferences == null) { 271 String key = project.isLocationUndefined() ? new String (IDUtil 272 .pseudoUniqueByteSequence16()) : project 273 .getMainFile() 274 .getAbsolutePath(); 275 276 projectPreferences = getApplicationPreferenceDomain().getSubdomain( 277 Project.class).getSubdomain(key); 278 } 279 280 return projectPreferences; 281 } 282 283 287 public Domain getPreferenceDomainForDataDomain() { 288 DataDomain dataDomain = getCurrentDataDomain(); 289 if (dataDomain == null) { 290 throw new CayenneRuntimeException("No DataDomain selected"); 291 } 292 293 return getPreferenceDomainForProject() 294 .getSubdomain(DataDomain.class) 295 .getSubdomain(dataDomain.getName()); 296 } 297 298 302 public DataMapDefaults getDataMapPreferences() { 303 DataMap map = getCurrentDataMap(); 304 if (map == null) { 305 throw new CayenneRuntimeException("No DataMap selectd"); 306 } 307 308 return (DataMapDefaults) getPreferenceDomainForDataDomain().getDetail( 309 map.getName(), 310 DataMapDefaults.class, 311 true); 312 } 313 314 318 public DataNodeDefaults getDataNodePreferences() { 319 DataNode node = getCurrentDataNode(); 320 if (node == null) { 321 throw new CayenneRuntimeException("No DataNode selected"); 322 } 323 324 return (DataNodeDefaults) getPreferenceDomainForDataDomain().getDetail( 325 node.getName(), 326 DataNodeDefaults.class, 327 true); 328 } 329 330 public void projectOpened() { 331 CayenneModelerFrame frame = (CayenneModelerFrame) getView(); 332 addDataNodeDisplayListener(frame); 333 addDataMapDisplayListener(frame); 334 addObjEntityDisplayListener(frame); 335 addDbEntityDisplayListener(frame); 336 addObjAttributeDisplayListener(frame); 337 addDbAttributeDisplayListener(frame); 338 addObjRelationshipDisplayListener(frame); 339 addDbRelationshipDisplayListener(frame); 340 addQueryDisplayListener(frame); 341 addProcedureDisplayListener(frame); 342 addProcedureParameterDisplayListener(frame); 343 } 344 345 public void reset() { 346 clearState(); 347 setDirty(false); 348 listenerList = new EventListenerList (); 349 controllerStateHistory.clear(); 350 } 351 352 358 public void setHistorySize(int newSize){ 359 controllerStateHistory.resize(newSize); 360 } 361 362 public boolean isDirty() { 363 return dirty; 364 } 365 366 367 private void clearState() { 368 if (currentState.isRefiring) return; 370 371 currentState = new ControllerState(); 372 } 373 374 private void saveState(DisplayEvent e){ 375 if (!controllerStateHistory.contains(currentState)){ 376 currentState.event = e; 377 controllerStateHistory.add(currentState); 378 } 379 } 380 381 protected void refreshNamespace() { 382 DataDomain domain = getCurrentDataDomain(); 383 if (domain != null) { 384 domain.getEntityResolver().clearCache(); 385 } 386 } 387 388 private void removeFromHistory(EventObject e) { 389 int count = controllerStateHistory.size(); 390 ArrayList removeList = new ArrayList (); 391 392 for (int i = 0; i < count; i++) { 393 ControllerState cs = (ControllerState) controllerStateHistory.get(i); 394 395 EventObject csEvent = cs.event; 396 397 if (csEvent == null) { 398 continue; 399 } 400 401 if (e instanceof EntityEvent && csEvent instanceof EntityDisplayEvent) { 402 if (((EntityEvent) e).getEntity() == ((EntityDisplayEvent) csEvent) 403 .getEntity()) { 404 removeList.add(cs); 405 } 406 } 407 else if (e instanceof ProcedureEvent 408 && csEvent instanceof ProcedureDisplayEvent) { 409 if (((ProcedureEvent) e).getProcedure() == ((ProcedureDisplayEvent) csEvent) 410 .getProcedure()) { 411 removeList.add(cs); 412 } 413 } 414 else if (e instanceof QueryEvent && csEvent instanceof QueryDisplayEvent) { 415 if (((QueryEvent) e).getQuery() == ((QueryDisplayEvent) csEvent) 416 .getQuery()) { 417 removeList.add(cs); 418 } 419 } 420 else if (e instanceof DataMapEvent && csEvent instanceof DataMapDisplayEvent) { 421 if (((DataMapEvent) e).getDataMap() == ((DataMapDisplayEvent) csEvent) 422 .getDataMap()) { 423 removeList.add(cs); 424 } 425 } 426 else if (e instanceof DataNodeEvent 427 && csEvent instanceof DataNodeDisplayEvent) { 428 if (((DataNodeEvent) e).getDataNode() == ((DataNodeDisplayEvent) csEvent) 429 .getDataNode()) { 430 removeList.add(cs); 431 } 432 } 433 else if (e instanceof DomainEvent && csEvent instanceof DomainDisplayEvent) { 434 if (((DomainEvent) e).getDomain() == ((DomainDisplayEvent) csEvent) 435 .getDomain()) { 436 removeList.add(cs); 437 } 438 } 439 } 440 Iterator it = removeList.iterator(); 441 while (it.hasNext()) { 442 controllerStateHistory.remove(it.next()); 443 } 444 } 445 446 public DataNode getCurrentDataNode() { 447 return currentState.node; 448 } 449 450 public DataDomain getCurrentDataDomain() { 451 return currentState.domain; 452 } 453 454 public DataMap getCurrentDataMap() { 455 return currentState.map; 456 } 457 458 public ObjEntity getCurrentObjEntity() { 459 return currentState.objEntity; 460 } 461 462 public DbEntity getCurrentDbEntity() { 463 return currentState.dbEntity; 464 } 465 466 public ObjAttribute getCurrentObjAttribute() { 467 return currentState.objAttr; 468 } 469 470 public DbAttribute getCurrentDbAttribute() { 471 return currentState.dbAttr; 472 } 473 474 public ObjRelationship getCurrentObjRelationship() { 475 return currentState.objRel; 476 } 477 478 public DbRelationship getCurrentDbRelationship() { 479 return currentState.dbRel; 480 } 481 482 public Query getCurrentQuery() { 483 return currentState.query; 484 } 485 486 public Procedure getCurrentProcedure() { 487 return currentState.procedure; 488 } 489 490 public ProcedureParameter getCurrentProcedureParameter() { 491 return currentState.procedureParameter; 492 } 493 494 public void addDomainDisplayListener(DomainDisplayListener listener) { 495 listenerList.add(DomainDisplayListener.class, listener); 496 } 497 498 public void addDomainListener(DomainListener listener) { 499 listenerList.add(DomainListener.class, listener); 500 } 501 502 public void addDataNodeDisplayListener(DataNodeDisplayListener listener) { 503 listenerList.add(DataNodeDisplayListener.class, listener); 504 } 505 506 public void addDataNodeListener(DataNodeListener listener) { 507 listenerList.add(DataNodeListener.class, listener); 508 } 509 510 public void addDataMapDisplayListener(DataMapDisplayListener listener) { 511 listenerList.add(DataMapDisplayListener.class, listener); 512 } 513 514 public void addDataMapListener(DataMapListener listener) { 515 listenerList.add(DataMapListener.class, listener); 516 } 517 518 public void addDbEntityListener(DbEntityListener listener) { 519 listenerList.add(DbEntityListener.class, listener); 520 } 521 522 public void addObjEntityListener(ObjEntityListener listener) { 523 listenerList.add(ObjEntityListener.class, listener); 524 } 525 526 public void addDbEntityDisplayListener(DbEntityDisplayListener listener) { 527 listenerList.add(DbEntityDisplayListener.class, listener); 528 } 529 530 public void addObjEntityDisplayListener(ObjEntityDisplayListener listener) { 531 listenerList.add(ObjEntityDisplayListener.class, listener); 532 } 533 534 public void addDbAttributeListener(DbAttributeListener listener) { 535 listenerList.add(DbAttributeListener.class, listener); 536 } 537 538 public void addDbAttributeDisplayListener(DbAttributeDisplayListener listener) { 539 listenerList.add(DbAttributeDisplayListener.class, listener); 540 } 541 542 public void addObjAttributeListener(ObjAttributeListener listener) { 543 listenerList.add(ObjAttributeListener.class, listener); 544 } 545 546 public void addObjAttributeDisplayListener(ObjAttributeDisplayListener listener) { 547 listenerList.add(ObjAttributeDisplayListener.class, listener); 548 } 549 550 public void addDbRelationshipListener(DbRelationshipListener listener) { 551 listenerList.add(DbRelationshipListener.class, listener); 552 } 553 554 public void addDbRelationshipDisplayListener(DbRelationshipDisplayListener listener) { 555 listenerList.add(DbRelationshipDisplayListener.class, listener); 556 } 557 558 public void addObjRelationshipListener(ObjRelationshipListener listener) { 559 listenerList.add(ObjRelationshipListener.class, listener); 560 } 561 562 public void addObjRelationshipDisplayListener(ObjRelationshipDisplayListener listener) { 563 listenerList.add(ObjRelationshipDisplayListener.class, listener); 564 } 565 566 public void addQueryDisplayListener(QueryDisplayListener listener) { 567 listenerList.add(QueryDisplayListener.class, listener); 568 } 569 570 public void addQueryListener(QueryListener listener) { 571 listenerList.add(QueryListener.class, listener); 572 } 573 574 public void addProcedureDisplayListener(ProcedureDisplayListener listener) { 575 listenerList.add(ProcedureDisplayListener.class, listener); 576 } 577 578 public void addProcedureListener(ProcedureListener listener) { 579 listenerList.add(ProcedureListener.class, listener); 580 } 581 582 public void addProcedureParameterListener(ProcedureParameterListener listener) { 583 listenerList.add(ProcedureParameterListener.class, listener); 584 } 585 586 public void addProcedureParameterDisplayListener( 587 ProcedureParameterDisplayListener listener) { 588 listenerList.add(ProcedureParameterDisplayListener.class, listener); 589 } 590 591 public void fireDomainDisplayEvent(DomainDisplayEvent e) { 592 boolean changed = e.getDomain() != currentState.domain; 593 if (!changed){ 594 changed = currentState.node != null 595 || currentState.map != null 596 || currentState.dbEntity != null 597 || currentState.objEntity != null 598 || currentState.procedure != null 599 || currentState.query != null; 600 } 601 602 603 if (!e.isRefired()){ 604 e.setDomainChanged(changed); 605 if (changed){ 606 clearState(); 607 currentState.domain = e.getDomain(); 608 } 609 } 610 611 if (changed){ 612 saveState(e); 613 } 614 615 EventListener [] list = listenerList.getListeners(DomainDisplayListener.class); 616 for (int i = 0; i < list.length; i++) { 617 DomainDisplayListener temp = (DomainDisplayListener) list[i]; 618 temp.currentDomainChanged(e); 619 } 620 621 ((CayenneModelerController) parent).dataDomainSelectedAction(currentState.domain); 622 } 623 624 628 public void fireDomainEvent(DomainEvent e) { 629 setDirty(true); 630 631 if (e.getId() == DomainEvent.REMOVE) { 632 refreshNamespace(); 633 removeFromHistory(e); 634 } 635 636 EventListener [] list = listenerList.getListeners(DomainListener.class); 637 for (int i = 0; i < list.length; i++) { 638 DomainListener temp = (DomainListener) list[i]; 639 switch (e.getId()) { 640 case DomainEvent.ADD: 641 temp.domainAdded(e); 642 break; 643 case DomainEvent.CHANGE: 644 temp.domainChanged(e); 645 break; 646 case DomainEvent.REMOVE: 647 temp.domainRemoved(e); 648 break; 649 default: 650 throw new IllegalArgumentException ("Invalid DomainEvent type: " 651 + e.getId()); 652 } 653 } 654 } 655 656 public void fireDataNodeDisplayEvent(DataNodeDisplayEvent e) { 657 boolean changed = e.getDataNode() != currentState.node; 658 659 if (!changed){ 660 changed = currentState.map != null 661 || currentState.dbEntity != null 662 || currentState.objEntity != null 663 || currentState.procedure != null 664 || currentState.query != null; 665 } 666 667 if (!e.isRefired()){ 668 e.setDataNodeChanged(changed); 669 670 if (changed){ 671 clearState(); 672 currentState.domain = e.getDomain(); 673 currentState.node = e.getDataNode(); 674 } 675 } 676 677 if (changed){ 678 saveState(e); 679 } 680 681 EventListener [] list = listenerList.getListeners(DataNodeDisplayListener.class); 682 for (int i = 0; i < list.length; i++) { 683 ((DataNodeDisplayListener) list[i]).currentDataNodeChanged(e); 684 } 685 } 686 687 691 public void fireDataNodeEvent(DataNodeEvent e) { 692 setDirty(true); 693 694 if (e.getId() == DataNodeEvent.REMOVE) { 695 refreshNamespace(); 696 removeFromHistory(e); 697 } 698 699 EventListener [] list = listenerList.getListeners(DataNodeListener.class); 700 for (int i = 0; i < list.length; i++) { 701 DataNodeListener temp = (DataNodeListener) list[i]; 702 switch (e.getId()) { 703 case DataNodeEvent.ADD: 704 temp.dataNodeAdded(e); 705 break; 706 case DataNodeEvent.CHANGE: 707 temp.dataNodeChanged(e); 708 break; 709 case DataNodeEvent.REMOVE: 710 temp.dataNodeRemoved(e); 711 break; 712 default: 713 throw new IllegalArgumentException ("Invalid DataNodeEvent type: " 714 + e.getId()); 715 } 716 } 717 } 718 719 public void fireDataMapDisplayEvent(DataMapDisplayEvent e) { 720 boolean changed = e.getDataMap() != currentState.map; 721 if (!changed){ 722 changed = currentState.dbEntity != null 723 || currentState.objEntity != null 724 || currentState.procedure != null 725 || currentState.query != null; 726 } 727 728 if (!e.isRefired()){ 729 e.setDataMapChanged(changed); 730 731 if (changed){ 732 clearState(); 733 currentState.domain = e.getDomain(); 734 currentState.node = e.getDataNode(); 735 currentState.map = e.getDataMap(); 736 } 737 } 738 739 if (changed){ 740 saveState(e); 741 } 742 743 EventListener [] list = listenerList.getListeners(DataMapDisplayListener.class); 744 for (int i = 0; i < list.length; i++) { 745 DataMapDisplayListener temp = (DataMapDisplayListener) list[i]; 746 temp.currentDataMapChanged(e); 747 } 748 } 749 750 754 public void fireDataMapEvent(DataMapEvent e) { 755 setDirty(true); 756 757 if (e.getId() == DataMapEvent.REMOVE) { 758 refreshNamespace(); 759 removeFromHistory(e); 760 } 761 762 EventListener [] list = listenerList.getListeners(DataMapListener.class); 763 for (int i = 0; i < list.length; i++) { 764 DataMapListener listener = (DataMapListener) list[i]; 765 switch (e.getId()) { 766 case DataMapEvent.ADD: 767 listener.dataMapAdded(e); 768 break; 769 case DataMapEvent.CHANGE: 770 listener.dataMapChanged(e); 771 break; 772 case DataMapEvent.REMOVE: 773 &nbs
|