2 * (c) Copyright IBM Corp. 2000, 2001.
5 package net.sourceforge.phpdt.internal.corext.textmanipulation;
7 import java.util.ArrayList;
8 import java.util.Arrays;
11 import net.sourceforge.phpdt.internal.corext.textmanipulation.TextEditNode.RootNode;
13 import org.eclipse.core.runtime.CoreException;
14 import org.eclipse.core.runtime.IProgressMonitor;
15 import org.eclipse.core.runtime.NullProgressMonitor;
17 //import org.eclipse.jdt.core.IJavaModelStatusConstants;
18 //import org.eclipse.jdt.core.JavaModelException;
20 //import org.eclipse.jdt.internal.corext.Assert;
24 * A <code>TextBufferEditor</code> manages a set of <code>TextEdit</code>s and applies
25 * them as a whole to a <code>TextBuffer</code>. Added <code>TextEdit</code>s must
26 * not overlap. The only exception from this rule are insertion point. There can be more than
27 * one insert point at the same text position. Clients should use the method <code>
28 * canPerformEdits</code> to validate if all added text edits follow these rules.
30 * Clients can attach more than one <code>TextBufferEditor</code> to a single <code>
31 * TextBuffer</code>. If so <code>canPerformEdits</code> validates all text edits from
32 * all text buffer editors working on the same text buffer.
34 public class TextBufferEditor {
36 private TextBuffer fBuffer;
38 private RootNode fRootNode;
39 private int fNumberOfNodes;
40 private int fConnectCount;
43 /* package */ static final int UNDEFINED= 0;
44 /* package */ static final int REDO= 1;
45 /* package */ static final int UNDO= 2;
48 * Creates a new <code>TextBufferEditor</code> for the given
49 * <code>TextBuffer</code>.
51 * @param the text buffer this editor is working on.
53 public TextBufferEditor(TextBuffer buffer) {
55 // Assert.isNotNull(fBuffer);
56 fEdits= new ArrayList();
60 * Returns the text buffer this editor is working on.
62 * @return the text buffer this editor is working on
64 public TextBuffer getTextBuffer() {
69 * Adds a <code>TextEdit</code> to this text editor. Adding a <code>TextEdit</code>
70 * to a <code>TextBufferEditor</code> transfers ownership of the edit to the editor. So
71 * after a edit has been added to a editor the creator of that edit <b>must</b> not continue
74 * @param edit the text edit to be added
75 * @exception CoreException if the text edit can not be added
76 * to this text buffer editor
78 public void add(TextEdit edit) throws CoreException {
79 // Assert.isTrue(fMode == UNDEFINED || fMode == REDO);
85 * Adds a <code>MultiTextEdit</code> to this text editor. Adding a <code>MultiTextEdit</code>
86 * to a <code>TextBufferEditor</code> transfers ownership of the edit to the editor. So
87 * after a edit has been added to a editor the creator of that edit <b>must</b> not continue
90 * @param edit the multi text edit to be added
91 * @exception CoreException if the multi text edit can not be added
92 * to this text buffer editor
94 public void add(MultiTextEdit edit) throws CoreException {
95 // Assert.isTrue(fMode == UNDEFINED || fMode == REDO);
101 * Adds a <code>UndoMemento</code> to this text editor. Adding a <code>UndoMemento</code>
102 * to a <code>TextBufferEditor</code> transfers ownership of the memento to the editor. So
103 * after a memento has been added to a editor the creator of that memento <b>must</b> not continue
106 * @param undo the undo memento to be added
107 * @exception CoreException if the undo memento can not be added
108 * to this text buffer editor
110 public void add(UndoMemento undo) throws CoreException {
111 // Assert.isTrue(fMode == UNDEFINED);
112 List list= undo.fEdits;
113 // Add them reverse since we are adding undos.
114 for (int i= list.size() - 1; i >= 0; i--) {
115 internalAdd((TextEdit)list.get(i));
121 * Checks if the <code>TextEdit</code> added to this text editor can be executed.
123 * @return <code>true</code> if the edits can be executed. Return <code>false
124 * </code>otherwise. One major reason why text edits cannot be executed
125 * is a wrong offset or length value of a <code>TextEdit</code>.
127 public boolean canPerformEdits() {
128 if (fRootNode != null)
130 fRootNode= buildTree();
131 if (fRootNode == null)
133 if (fRootNode.validate(fBuffer.getLength()))
141 * Clears the text buffer editor.
143 public void clear() {
150 * Executes the text edits added to this text buffer editor and clears all added
153 * @param pm a progress monitor to report progress or <code>null</code> if
154 * no progress is desired.
155 * @return an object representing the undo of the executed <code>TextEdit</code>s
156 * @exception CoreException if the edits cannot be executed
158 public UndoMemento performEdits(IProgressMonitor pm) throws CoreException {
160 pm= new NullProgressMonitor();
162 int size= fEdits.size();
164 return new UndoMemento(fMode == UNDO ? REDO : UNDO);
166 if (fRootNode == null) {
167 fRootNode= buildTree();
168 if (fRootNode == null || !fRootNode.validate(fBuffer.getLength())) {
169 // throw new JavaModelException(null, IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
173 pm.beginTask("", fNumberOfNodes + 10); //$NON-NLS-1$
174 UndoMemento undo= null;
176 undo= fRootNode.performDo(fBuffer, pm);
177 fRootNode.performedDo();
179 undo= fRootNode.performUndo(fBuffer, pm);
180 fRootNode.performedUndo();
190 //---- Helper methods ------------------------------------------------------------
192 private RootNode buildTree() {
193 TextEditNode[] nodes= new TextEditNode[fEdits.size()];
194 for (int i= fEdits.size() - 1; i >= 0; i--) {
195 nodes[i]= TextEditNode.create((TextEdit)fEdits.get(i));
197 fNumberOfNodes= nodes.length;
198 Arrays.sort(nodes, new TextEditNodeComparator());
199 RootNode root= new RootNode(fBuffer.getLength());
200 for (int i= 0; i < nodes.length; i++) {
206 private void internalAdd(TextEdit edit) throws CoreException {
207 edit.index= fEdits.size();
208 edit.isSynthetic= fConnectCount > 0;