KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ltk > core > refactoring > TextFileChange


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ltk.core.refactoring;
12
13 import org.eclipse.text.edits.UndoEdit;
14
15 import org.eclipse.core.runtime.Assert;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IPath;
18 import org.eclipse.core.runtime.IProgressMonitor;
19
20 import org.eclipse.core.filebuffers.FileBuffers;
21 import org.eclipse.core.filebuffers.ITextFileBuffer;
22 import org.eclipse.core.filebuffers.ITextFileBufferManager;
23 import org.eclipse.core.filebuffers.LocationKind;
24
25 import org.eclipse.core.resources.IFile;
26
27 import org.eclipse.jface.text.IDocument;
28
29 import org.eclipse.ltk.internal.core.refactoring.BufferValidationState;
30 import org.eclipse.ltk.internal.core.refactoring.Changes;
31 import org.eclipse.ltk.internal.core.refactoring.ContentStamps;
32
33 /**
34  * A special {@link TextChange} that operates on a <code>IFile</code>.
35  * <p>
36  * As of 3.1 the content stamp managed by a text file change maps to the modification
37  * stamp of its underlying <code>IFile</code>. Undoing a text file change will
38  * roll back the modification stamp of a resource to its original value using
39  * the new API {@link org.eclipse.core.resources.IResource#revertModificationStamp(long)}
40  * </p>
41  * <p>
42  * The class should be subclassed by clients which need to perform
43  * special operation when acquiring or releasing a document.
44  * </p>
45  * @since 3.0
46  */

47 public class TextFileChange extends TextChange {
48     
49     /**
50      * Flag (value 1) indicating that the file's save state has to be kept. This means an
51      * unsaved file is still unsaved after performing the change and a saved one
52      * will be saved.
53      */

54     public static final int KEEP_SAVE_STATE= 1 << 0;
55     
56     /**
57      * Flag (value 2) indicating that the file is to be saved after the change has been applied.
58      */

59     public static final int FORCE_SAVE= 1 << 1;
60     
61     /**
62      * Flag (value 4) indicating that the file will not be saved after the change has been applied.
63      */

64     public static final int LEAVE_DIRTY= 1 << 2;
65     
66     
67     // the file to change
68
private IFile fFile;
69     private int fSaveMode= KEEP_SAVE_STATE;
70     
71     // the mapped text buffer
72
private int fAcquireCount;
73     private ITextFileBuffer fBuffer;
74     private BufferValidationState fValidationState;
75     private ContentStamp fContentStamp;
76     
77     /**
78      * Creates a new <code>TextFileChange</code> for the given file.
79      *
80      * @param name the change's name mainly used to render the change in the UI
81      * @param file the file this text change operates on
82      */

83     public TextFileChange(String JavaDoc name, IFile file) {
84         super(name);
85         Assert.isNotNull(file);
86         fFile= file;
87     }
88     
89     /**
90      * Sets the save state. Must be one of <code>KEEP_SAVE_STATE</code>,
91      * <code>FORCE_SAVE</code> or <code>LEAVE_DIRTY</code>.
92      *
93      * @param saveMode indicating how save is handled when the document
94      * gets committed
95      */

96     public void setSaveMode(int saveMode) {
97         fSaveMode= saveMode;
98     }
99     
100     /**
101      * Returns the save state set via {@link #setSaveMode(int)}.
102      *
103      * @return the save state
104      */

105     public int getSaveMode() {
106         return fSaveMode;
107     }
108     
109     /**
110      * Returns the <code>IFile</code> this change is working on.
111      *
112      * @return the file this change is working on
113      */

114     public IFile getFile() {
115         return fFile;
116     }
117     
118     /**
119      * Hook to create an undo change for the given undo edit and content stamp.
120      * This hook gets called while performing the change to construct the
121      * corresponding undo change object.
122      *
123      * @param edit the {@link UndoEdit} to create an undo change for
124      * @param stampToRestore the content stamp to restore when the undo
125      * edit is executed.
126      *
127      * @return the undo change or <code>null</code> if no undo change can
128      * be created. Returning <code>null</code> results in the fact that
129      * the whole change tree can't be undone. So returning <code>null</code>
130      * is only recommended if an exception occurred during creating the
131      * undo change.
132      */

133     protected Change createUndoChange(UndoEdit edit, ContentStamp stampToRestore) {
134         return new UndoTextFileChange(getName(), fFile, edit, stampToRestore, fSaveMode);
135     }
136     
137     /**
138      * {@inheritDoc}
139      */

140     public Object JavaDoc getModifiedElement(){
141         return fFile;
142     }
143
144     public Object JavaDoc[] getAffectedObjects() {
145         Object JavaDoc modifiedElement= getModifiedElement();
146         if (modifiedElement == null)
147             return null;
148         return new Object JavaDoc[] { modifiedElement };
149     }
150     
151     /**
152      * {@inheritDoc}
153      */

154     public void initializeValidationData(IProgressMonitor monitor) {
155         try {
156             monitor.beginTask("", 1); //$NON-NLS-1$
157
fValidationState= BufferValidationState.create(fFile);
158         } finally {
159             monitor.done();
160         }
161     }
162     
163     /**
164      * {@inheritDoc}
165      */

166     public RefactoringStatus isValid(IProgressMonitor monitor) throws CoreException {
167         try {
168             monitor.beginTask("", 1); //$NON-NLS-1$
169
boolean needsSaving= needsSaving();
170             RefactoringStatus result= fValidationState.isValid(needsSaving);
171             if (needsSaving) {
172                 result.merge(Changes.validateModifiesFiles(new IFile[] { fFile}));
173             } else {
174                 // we are reading the file. So it should be at least in sync
175
result.merge(Changes.checkInSync(new IFile[] { fFile}));
176             }
177             return result;
178         } finally {
179             monitor.done();
180         }
181     }
182
183     /**
184      * {@inheritDoc}
185      */

186     public void dispose() {
187         fValidationState.dispose();
188     }
189     
190     /**
191      * {@inheritDoc}
192      */

193     protected IDocument acquireDocument(IProgressMonitor pm) throws CoreException {
194         fAcquireCount++;
195         if (fAcquireCount > 1)
196             return fBuffer.getDocument();
197         
198         ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
199         IPath path= fFile.getFullPath();
200         manager.connect(path, LocationKind.IFILE, pm);
201         fBuffer= manager.getTextFileBuffer(path, LocationKind.IFILE);
202         IDocument result= fBuffer.getDocument();
203         fContentStamp= ContentStamps.get(fFile, result);
204         return result;
205     }
206     
207     /**
208      * {@inheritDoc}
209      * <p>
210      * The implementation of this method only commits the underlying buffer if
211      * {@link #needsSaving()} and {@link #isDocumentModified()} returns <code>true</code>.
212      * </p>
213      */

214     protected void commit(IDocument document, IProgressMonitor pm) throws CoreException {
215         if (needsSaving()) {
216             fBuffer.commit(pm, false);
217         }
218     }
219     
220     /**
221      * {@inheritDoc}
222      */

223     protected void releaseDocument(IDocument document, IProgressMonitor pm) throws CoreException {
224         Assert.isTrue(fAcquireCount > 0);
225         if (fAcquireCount == 1) {
226             ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
227             manager.disconnect(fFile.getFullPath(), LocationKind.IFILE, pm);
228         }
229         fAcquireCount--;
230     }
231     
232     /**
233      * {@inheritDoc}
234      */

235     protected final Change createUndoChange(UndoEdit edit) {
236         return createUndoChange(edit, fContentStamp);
237     }
238
239     /**
240      * Is the document currently acquired?
241      *
242      * @return <code>true</code> if the document is currently acquired,
243      * <code>false</code> otherwise
244      * @since 3.2
245      */

246     protected boolean isDocumentAcquired() {
247         return fAcquireCount > 0;
248     }
249         
250     /**
251      * Has the document been modified since it has been first acquired by the change?
252      *
253      * @return Returns true if the document has been modified since it got acquired by the change.
254      * <code>false</code> is returned if the document has not been acquired yet, or has been released
255      * already.
256      *
257      * @since 3.3
258      */

259     protected boolean isDocumentModified() {
260         if (fAcquireCount > 0) {
261             ContentStamp currentStamp= ContentStamps.get(fFile, fBuffer.getDocument());
262             return !currentStamp.equals(fContentStamp);
263         }
264         return false;
265     }
266
267     /**
268      * Does the text file change need saving?
269      * <p>
270      * The implementation of this method returns <code>true</code> if the
271      * <code>FORCE_SAVE</code> flag is enabled, or the underlying file is not
272      * dirty and <code>KEEP_SAVE_STATE</code> is enabled.
273      * </p>
274      *
275      * @return <code>true</code> if it needs saving according to its dirty
276      * state and the save mode flags, <code>false</code> otherwise
277      * @since 3.3
278      */

279     protected boolean needsSaving() {
280         if ((fSaveMode & FORCE_SAVE) != 0) {
281             return true;
282         }
283         if ((fSaveMode & KEEP_SAVE_STATE) != 0) {
284             return fValidationState == null || !fValidationState.wasDirty();
285         }
286         return false;
287     }
288 }
289
Popular Tags