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;
12 import org.eclipse.core.runtime.CoreException;
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.core.runtime.NullProgressMonitor;
16 //import org.eclipse.jdt.core.IJavaModelStatusConstants;
17 //import org.eclipse.jdt.core.JavaModelException;
19 //import org.eclipse.jdt.internal.corext.Assert;
23 * A <code>TextBufferEditor</code> manages a set of <code>TextEdit</code>s and applies
24 * them as a whole to a <code>TextBuffer</code>. Added <code>TextEdit</code>s must
25 * not overlap. The only exception from this rule are insertion point. There can be more than
26 * one insert point at the same text position. Clients should use the method <code>
27 * canPerformEdits</code> to validate if all added text edits follow these rules.
29 * Clients can attach more than one <code>TextBufferEditor</code> to a single <code>
30 * TextBuffer</code>. If so <code>canPerformEdits</code> validates all text edits from
31 * all text buffer editors working on the same text buffer.
33 public class TextBufferEditor {
35 private TextBuffer fBuffer;
37 private RootNode fRootNode;
38 private int fNumberOfNodes;
39 private int fConnectCount;
42 /* package */ static final int UNDEFINED= 0;
43 /* package */ static final int REDO= 1;
44 /* package */ static final int UNDO= 2;
47 * Creates a new <code>TextBufferEditor</code> for the given
48 * <code>TextBuffer</code>.
50 * @param the text buffer this editor is working on.
52 public TextBufferEditor(TextBuffer buffer) {
54 // Assert.isNotNull(fBuffer);
55 fEdits= new ArrayList();
59 * Returns the text buffer this editor is working on.
61 * @return the text buffer this editor is working on
63 public TextBuffer getTextBuffer() {
68 * Adds a <code>TextEdit</code> to this text editor. Adding a <code>TextEdit</code>
69 * to a <code>TextBufferEditor</code> transfers ownership of the edit to the editor. So
70 * after a edit has been added to a editor the creator of that edit <b>must</b> not continue
73 * @param edit the text edit to be added
74 * @exception CoreException if the text edit can not be added
75 * to this text buffer editor
77 public void add(TextEdit edit) throws CoreException {
78 // Assert.isTrue(fMode == UNDEFINED || fMode == REDO);
84 * Adds a <code>MultiTextEdit</code> to this text editor. Adding a <code>MultiTextEdit</code>
85 * to a <code>TextBufferEditor</code> transfers ownership of the edit to the editor. So
86 * after a edit has been added to a editor the creator of that edit <b>must</b> not continue
89 * @param edit the multi text edit to be added
90 * @exception CoreException if the multi text edit can not be added
91 * to this text buffer editor
93 public void add(MultiTextEdit edit) throws CoreException {
94 // Assert.isTrue(fMode == UNDEFINED || fMode == REDO);
100 * Adds a <code>UndoMemento</code> to this text editor. Adding a <code>UndoMemento</code>
101 * to a <code>TextBufferEditor</code> transfers ownership of the memento to the editor. So
102 * after a memento has been added to a editor the creator of that memento <b>must</b> not continue
105 * @param undo the undo memento to be added
106 * @exception CoreException if the undo memento can not be added
107 * to this text buffer editor
109 public void add(UndoMemento undo) throws CoreException {
110 // Assert.isTrue(fMode == UNDEFINED);
111 List list= undo.fEdits;
112 // Add them reverse since we are adding undos.
113 for (int i= list.size() - 1; i >= 0; i--) {
114 internalAdd((TextEdit)list.get(i));
120 * Checks if the <code>TextEdit</code> added to this text editor can be executed.
122 * @return <code>true</code> if the edits can be executed. Return <code>false
123 * </code>otherwise. One major reason why text edits cannot be executed
124 * is a wrong offset or length value of a <code>TextEdit</code>.
126 public boolean canPerformEdits() {
127 if (fRootNode != null)
129 fRootNode= buildTree();
130 if (fRootNode == null)
132 if (fRootNode.validate(fBuffer.getLength()))
140 * Clears the text buffer editor.
142 public void clear() {
149 * Executes the text edits added to this text buffer editor and clears all added
152 * @param pm a progress monitor to report progress or <code>null</code> if
153 * no progress is desired.
154 * @return an object representing the undo of the executed <code>TextEdit</code>s
155 * @exception CoreException if the edits cannot be executed
157 public UndoMemento performEdits(IProgressMonitor pm) throws CoreException {
159 pm= new NullProgressMonitor();
161 int size= fEdits.size();
163 return new UndoMemento(fMode == UNDO ? REDO : UNDO);
165 if (fRootNode == null) {
166 fRootNode= buildTree();
167 if (fRootNode == null || !fRootNode.validate(fBuffer.getLength())) {
168 // throw new JavaModelException(null, IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
172 pm.beginTask("", fNumberOfNodes + 10); //$NON-NLS-1$
173 UndoMemento undo= null;
175 undo= fRootNode.performDo(fBuffer, pm);
176 fRootNode.performedDo();
178 undo= fRootNode.performUndo(fBuffer, pm);
179 fRootNode.performedUndo();
189 //---- Helper methods ------------------------------------------------------------
191 private RootNode buildTree() {
192 TextEditNode[] nodes= new TextEditNode[fEdits.size()];
193 for (int i= fEdits.size() - 1; i >= 0; i--) {
194 nodes[i]= TextEditNode.create((TextEdit)fEdits.get(i));
196 fNumberOfNodes= nodes.length;
197 Arrays.sort(nodes, new TextEditNodeComparator());
198 RootNode root= new RootNode(fBuffer.getLength());
199 for (int i= 0; i < nodes.length; i++) {
205 private void internalAdd(TextEdit edit) throws CoreException {
206 edit.index= fEdits.size();
207 edit.isSynthetic= fConnectCount > 0;