1 11 12 package org.eclipse.ui.texteditor; 13 14 15 import java.lang.reflect.InvocationTargetException ; 16 import java.util.ArrayList ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.Iterator ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.eclipse.core.runtime.Assert; 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.core.runtime.IStatus; 28 import org.eclipse.core.runtime.NullProgressMonitor; 29 import org.eclipse.core.runtime.Status; 30 import org.eclipse.core.runtime.content.IContentType; 31 import org.eclipse.core.runtime.jobs.ISchedulingRule; 32 33 import org.eclipse.jface.operation.IRunnableContext; 34 import org.eclipse.jface.operation.IRunnableWithProgress; 35 36 import org.eclipse.jface.text.DocumentEvent; 37 import org.eclipse.jface.text.IDocument; 38 import org.eclipse.jface.text.IDocumentListener; 39 import org.eclipse.jface.text.source.IAnnotationModel; 40 41 import org.eclipse.ui.internal.texteditor.TextEditorPlugin; 42 43 44 45 52 public abstract class AbstractDocumentProvider implements IDocumentProvider, IDocumentProviderExtension, IDocumentProviderExtension2, IDocumentProviderExtension3, IDocumentProviderExtension4, IDocumentProviderExtension5 { 53 54 59 protected static abstract class DocumentProviderOperation implements IRunnableWithProgress { 60 61 67 protected abstract void execute(IProgressMonitor monitor) throws CoreException; 68 69 72 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 73 try { 74 execute(monitor); 75 } catch (CoreException x) { 76 throw new InvocationTargetException (x); 77 } 78 } 79 } 80 81 84 protected class ElementInfo implements IDocumentListener { 85 86 87 public Object fElement; 88 89 public int fCount; 90 91 public boolean fCanBeSaved; 92 93 public IDocument fDocument; 94 95 public IAnnotationModel fModel; 96 100 public boolean fIsStateValidated; 101 105 public IStatus fStatus; 106 107 108 115 public ElementInfo(IDocument document, IAnnotationModel model) { 116 fDocument= document; 117 fModel= model; 118 fCount= 0; 119 fCanBeSaved= false; 120 fIsStateValidated= false; 121 } 122 123 128 public boolean equals(Object o) { 129 if (o instanceof ElementInfo) { 130 ElementInfo e= (ElementInfo) o; 131 return fDocument.equals(e.fDocument); 132 } 133 return false; 134 } 135 136 139 public int hashCode() { 140 return fDocument.hashCode(); 141 } 142 143 146 public void documentChanged(DocumentEvent event) { 147 fCanBeSaved= true; 148 removeUnchangedElementListeners(fElement, this); 149 fireElementDirtyStateChanged(fElement, fCanBeSaved); 150 } 151 152 155 public void documentAboutToBeChanged(DocumentEvent event) { 156 } 157 } 158 159 160 167 static final protected boolean PR10806_UC5_ENABLED= true; 168 169 177 static final protected boolean PR14469_ENABLED= false; 178 179 183 static final protected IStatus STATUS_OK= new Status(IStatus.OK, TextEditorPlugin.PLUGIN_ID, IStatus.OK, EditorMessages.AbstractDocumentProvider_ok, null); 184 185 189 static final protected IStatus STATUS_ERROR= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.INFO, EditorMessages.AbstractDocumentProvider_error, null); 190 191 192 193 private Map fElementInfoMap= new HashMap (); 194 195 private List fElementStateListeners= new ArrayList (); 196 200 private IProgressMonitor fProgressMonitor; 201 202 203 206 protected AbstractDocumentProvider() { 207 } 208 209 218 protected abstract IDocument createDocument(Object element) throws CoreException; 219 220 229 protected abstract IAnnotationModel createAnnotationModel(Object element) throws CoreException; 230 231 243 protected abstract void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException; 244 245 252 protected abstract IRunnableContext getOperationRunner(IProgressMonitor monitor); 253 254 263 protected ISchedulingRule getSynchronizeRule(Object element) { 264 return null; 265 } 266 267 276 protected ISchedulingRule getValidateStateRule(Object element) { 277 return null; 278 } 279 280 289 protected ISchedulingRule getSaveRule(Object element) { 290 return null; 291 } 292 293 302 protected ISchedulingRule getResetRule(Object element) { 303 return null; 304 } 305 306 312 protected ElementInfo getElementInfo(Object element) { 313 return (ElementInfo) fElementInfoMap.get(element); 314 } 315 316 330 protected ElementInfo createElementInfo(Object element) throws CoreException { 331 return new ElementInfo(createDocument(element), createAnnotationModel(element)); 332 } 333 334 344 protected void disposeElementInfo(Object element, ElementInfo info) { 345 } 346 347 358 protected void addUnchangedElementListeners(Object element, ElementInfo info) { 359 if (info.fDocument != null) 360 info.fDocument.addDocumentListener(info); 361 } 362 363 373 protected void removeUnchangedElementListeners(Object element, ElementInfo info) { 374 if (info.fDocument != null) 375 info.fDocument.removeDocumentListener(info); 376 } 377 378 383 protected Iterator getConnectedElements() { 384 Set s= new HashSet (); 385 Set keys= fElementInfoMap.keySet(); 386 if (keys != null) 387 s.addAll(keys); 388 return s.iterator(); 389 } 390 391 394 public final void connect(Object element) throws CoreException { 395 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 396 if (info == null) { 397 398 info= createElementInfo(element); 399 if (info == null) 400 info= new ElementInfo(null, null); 401 402 info.fElement= element; 403 404 addUnchangedElementListeners(element, info); 405 406 fElementInfoMap.put(element, info); 407 if (fElementInfoMap.size() == 1) 408 connected(); 409 } 410 ++ info.fCount; 411 } 412 413 419 protected void connected() { 420 } 421 422 425 public final void disconnect(Object element) { 426 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 427 428 if (info == null) 429 return; 430 431 if (info.fCount == 1) { 432 433 fElementInfoMap.remove(element); 434 removeUnchangedElementListeners(element, info); 435 disposeElementInfo(element, info); 436 437 if (fElementInfoMap.size() == 0) 438 disconnected(); 439 440 } else 441 -- info.fCount; 442 } 443 444 450 protected void disconnected() { 451 } 452 453 456 public IDocument getDocument(Object element) { 457 458 if (element == null) 459 return null; 460 461 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 462 return (info != null ? info.fDocument : null); 463 } 464 465 468 public boolean mustSaveDocument(Object element) { 469 470 if (element == null) 471 return false; 472 473 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 474 return (info != null ? info.fCount == 1 && info.fCanBeSaved : false); 475 } 476 477 480 public IAnnotationModel getAnnotationModel(Object element) { 481 482 if (element == null) 483 return null; 484 485 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 486 return (info != null ? info.fModel : null); 487 } 488 489 492 public boolean canSaveDocument(Object element) { 493 494 if (element == null) 495 return false; 496 497 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 498 return (info != null ? info.fCanBeSaved : false); 499 } 500 501 509 protected void doResetDocument(Object element, IProgressMonitor monitor) throws CoreException { 510 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 511 if (info != null) { 512 513 IDocument original= null; 514 IStatus status= null; 515 516 try { 517 original= createDocument(element); 518 } catch (CoreException x) { 519 status= x.getStatus(); 520 } 521 522 info.fStatus= status; 523 524 if (original != null) { 525 fireElementContentAboutToBeReplaced(element); 526 info.fDocument.set(original.get()); 527 if (info.fCanBeSaved) { 528 info.fCanBeSaved= false; 529 addUnchangedElementListeners(element, info); 530 } 531 fireElementContentReplaced(element); 532 fireElementDirtyStateChanged(element, false); 533 } 534 } 535 } 536 537 545 protected void executeOperation(DocumentProviderOperation operation, IProgressMonitor monitor) throws CoreException { 546 try { 547 IRunnableContext runner= getOperationRunner(monitor); 548 if (runner != null) 549 runner.run(false, false, operation); 550 else 551 operation.run(monitor); 552 } catch (InvocationTargetException x) { 553 Throwable e= x.getTargetException(); 554 if (e instanceof CoreException) 555 throw (CoreException) e; 556 String message= (e.getMessage() != null ? e.getMessage() : ""); throw new CoreException(new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.ERROR, message, e)); 558 } catch (InterruptedException x) { 559 String message= (x.getMessage() != null ? x.getMessage() : ""); throw new CoreException(new Status(IStatus.CANCEL, TextEditorPlugin.PLUGIN_ID, IStatus.OK, message, x)); 561 } 562 } 563 564 567 public final void resetDocument(final Object element) throws CoreException { 568 569 if (element == null) 570 return; 571 572 class ResetOperation extends DocumentProviderOperation implements ISchedulingRuleProvider { 573 574 protected void execute(IProgressMonitor monitor) throws CoreException { 575 doResetDocument(element, monitor); 576 } 577 578 public ISchedulingRule getSchedulingRule() { 579 return getResetRule(element); 580 } 581 } 582 583 executeOperation(new ResetOperation(), getProgressMonitor()); 584 } 585 586 587 590 public final void saveDocument(IProgressMonitor monitor, final Object element, final IDocument document, final boolean overwrite) throws CoreException { 591 592 if (element == null) 593 return; 594 595 class SaveOperation extends DocumentProviderOperation implements ISchedulingRuleProvider { 596 597 600 protected void execute(IProgressMonitor pm) throws CoreException { 601 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 602 if (info != null) { 603 if (info.fDocument != document) { 604 Status status= new Status(IStatus.WARNING, TextEditorPlugin.PLUGIN_ID, IStatus.ERROR, EditorMessages.AbstractDocumentProvider_error_save_inuse, null); 605 throw new CoreException(status); 606 } 607 608 doSaveDocument(pm, element, document, overwrite); 609 610 if (pm != null && pm.isCanceled()) 611 return; 612 613 info.fCanBeSaved= false; 614 addUnchangedElementListeners(element, info); 615 fireElementDirtyStateChanged(element, false); 616 617 } else { 618 doSaveDocument(pm, element, document, overwrite); 619 } 620 } 621 622 public ISchedulingRule getSchedulingRule() { 623 return getSaveRule(element); 624 } 625 } 626 627 executeOperation(new SaveOperation(), monitor); 628 } 629 630 637 public void aboutToChange(Object element) { 638 } 639 640 647 public void changed(Object element) { 648 } 649 650 653 public void addElementStateListener(IElementStateListener listener) { 654 Assert.isNotNull(listener); 655 if (!fElementStateListeners.contains(listener)) 656 fElementStateListeners.add(listener); 657 } 658 659 662 public void removeElementStateListener(IElementStateListener listener) { 663 Assert.isNotNull(listener); 664 fElementStateListeners.remove(listener); 665 } 666 667 675 protected void fireElementDirtyStateChanged(Object element, boolean isDirty) { 676 Iterator e= new ArrayList (fElementStateListeners).iterator(); 677 while (e.hasNext()) { 678 IElementStateListener l= (IElementStateListener) e.next(); 679 l.elementDirtyStateChanged(element, isDirty); 680 } 681 } 682 683 690 protected void fireElementContentAboutToBeReplaced(Object element) { 691 Iterator e= new ArrayList (fElementStateListeners).iterator(); 692 while (e.hasNext()) { 693 IElementStateListener l= (IElementStateListener) e.next(); 694 l.elementContentAboutToBeReplaced(element); 695 } 696 } 697 698 705 protected void fireElementContentReplaced(Object element) { 706 Iterator e= new ArrayList (fElementStateListeners).iterator(); 707 while (e.hasNext()) { 708 IElementStateListener l= (IElementStateListener) e.next(); 709 l.elementContentReplaced(element); 710 } 711 } 712 713 720 protected void fireElementDeleted(Object element) { 721 Iterator e= new ArrayList (fElementStateListeners).iterator(); 722 while (e.hasNext()) { 723 IElementStateListener l= (IElementStateListener) e.next(); 724 l.elementDeleted(element); 725 } 726 } 727 728 735 protected void fireElementMoved(Object originalElement, Object movedElement) { 736 Iterator e= new ArrayList (fElementStateListeners).iterator(); 737 while (e.hasNext()) { 738 IElementStateListener l= (IElementStateListener) e.next(); 739 l.elementMoved(originalElement, movedElement); 740 } 741 } 742 743 747 public long getModificationStamp(Object element) { 748 return 0; 749 } 750 751 755 public long getSynchronizationStamp(Object element) { 756 return 0; 757 } 758 759 763 public boolean isDeleted(Object element) { 764 return false; 765 } 766 767 771 public boolean isReadOnly(Object element) { 772 return true; 773 } 774 775 779 public boolean isModifiable(Object element) { 780 return false; 781 } 782 783 791 public boolean isStateValidated(Object element) { 792 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 793 if (info != null) 794 return info.fIsStateValidated; 795 return false; 796 } 797 798 807 protected void doValidateState(Object element, Object computationContext) throws CoreException { 808 } 809 810 814 public void validateState(final Object element, final Object computationContext) throws CoreException { 815 if (element == null) 816 return; 817 818 class ValidateStateOperation extends DocumentProviderOperation implements ISchedulingRuleProvider { 819 820 protected void execute(IProgressMonitor monitor) throws CoreException { 821 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 822 if (info == null) 823 return; 824 825 doValidateState(element, computationContext); 826 827 doUpdateStateCache(element); 828 info.fIsStateValidated= true; 829 fireElementStateValidationChanged(element, true); 830 } 831 832 public ISchedulingRule getSchedulingRule() { 833 return getValidateStateRule(element); 834 } 835 } 836 837 executeOperation(new ValidateStateOperation(), getProgressMonitor()); 838 } 839 840 848 protected void doUpdateStateCache(Object element) throws CoreException { 849 } 850 851 860 protected boolean invalidatesState(Object element, boolean wasReadOnly) { 861 Assert.isTrue(PR10806_UC5_ENABLED != PR14469_ENABLED); 862 boolean readOnlyChanged= (isReadOnly(element) != wasReadOnly && !wasReadOnly); 863 if (PR14469_ENABLED) 864 return readOnlyChanged && !canSaveDocument(element); 865 return readOnlyChanged; 866 } 867 868 872 final public void updateStateCache(Object element) throws CoreException { 873 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 874 if (info != null) { 875 boolean wasReadOnly= isReadOnly(element); 876 doUpdateStateCache(element); 877 if (invalidatesState(element, wasReadOnly)) { 878 info.fIsStateValidated= false; 879 fireElementStateValidationChanged(element, false); 880 } 881 } 882 } 883 884 888 public void setCanSaveDocument(Object element) { 889 if (element != null) { 890 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 891 if (info != null) { 892 info.fCanBeSaved= true; 893 removeUnchangedElementListeners(element, info); 894 fireElementDirtyStateChanged(element, info.fCanBeSaved); 895 } 896 } 897 } 898 899 908 protected void fireElementStateValidationChanged(Object element, boolean isStateValidated) { 909 Iterator e= new ArrayList (fElementStateListeners).iterator(); 910 while (e.hasNext()) { 911 Object o= e.next(); 912 if (o instanceof IElementStateListenerExtension) { 913 IElementStateListenerExtension l= (IElementStateListenerExtension) o; 914 l.elementStateValidationChanged(element, isStateValidated); 915 } 916 } 917 } 918 919 927 protected void fireElementStateChanging(Object element) { 928 Iterator e= new ArrayList (fElementStateListeners).iterator(); 929 while (e.hasNext()) { 930 Object o= e.next(); 931 if (o instanceof IElementStateListenerExtension) { 932 IElementStateListenerExtension l= (IElementStateListenerExtension) o; 933 l.elementStateChanging(element); 934 } 935 } 936 } 937 938 946 protected void fireElementStateChangeFailed(Object element) { 947 Iterator e= new ArrayList (fElementStateListeners).iterator(); 948 while (e.hasNext()) { 949 Object o= e.next(); 950 if (o instanceof IElementStateListenerExtension) { 951 IElementStateListenerExtension l= (IElementStateListenerExtension) o; 952 l.elementStateChangeFailed(element); 953 } 954 } 955 } 956 957 961 public IStatus getStatus(Object element) { 962 ElementInfo info= (ElementInfo) fElementInfoMap.get(element); 963 if (info != null) { 964 if (info.fStatus != null) 965 return info.fStatus; 966 return (info.fDocument == null ? STATUS_ERROR : STATUS_OK); 967 } 968 969 return STATUS_ERROR; 970 } 971 972 980 protected void doSynchronize(Object element, IProgressMonitor monitor) throws CoreException { 981 } 982 983 987 public final void synchronize(final Object element) throws CoreException { 988 989 if (element == null) 990 return; 991 992 class SynchronizeOperation extends DocumentProviderOperation implements ISchedulingRuleProvider { 993 994 protected void execute(IProgressMonitor monitor) throws CoreException { 995 doSynchronize(element, monitor); 996 } 997 998 public ISchedulingRule getSchedulingRule() { 999 return getSynchronizeRule(element); 1000 } 1001 } 1002 1003 executeOperation(new SynchronizeOperation(), getProgressMonitor()); 1004 } 1005 1006 1010 public IProgressMonitor getProgressMonitor() { 1011 return fProgressMonitor == null ? new NullProgressMonitor() : fProgressMonitor; 1012 } 1013 1014 1018 public void setProgressMonitor(IProgressMonitor progressMonitor) { 1019 fProgressMonitor= progressMonitor; 1020 } 1021 1022 1026 public boolean isSynchronized(Object element) { 1027 return true; 1028 } 1029 1030 1034 public boolean isNotSynchronizedException(Object element, CoreException ex) { 1035 return false; 1036 } 1037 1038 1042 public IContentType getContentType(Object element) throws CoreException { 1043 return null; 1044 } 1045} 1046 | Popular Tags |