KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ui > mapping > ResourceSaveableComparison


1 /*******************************************************************************
2  * Copyright (c) 2006 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.team.internal.ui.mapping;
12
13 import org.eclipse.compare.*;
14 import org.eclipse.compare.structuremergeviewer.*;
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.runtime.*;
17 import org.eclipse.jface.dialogs.IDialogConstants;
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.resource.ImageDescriptor;
20 import org.eclipse.jface.util.IPropertyChangeListener;
21 import org.eclipse.jface.util.PropertyChangeEvent;
22 import org.eclipse.osgi.util.NLS;
23 import org.eclipse.swt.graphics.Image;
24 import org.eclipse.team.core.diff.IDiff;
25 import org.eclipse.team.core.diff.IThreeWayDiff;
26 import org.eclipse.team.core.history.IFileRevision;
27 import org.eclipse.team.core.mapping.IResourceDiff;
28 import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
29 import org.eclipse.team.internal.ui.*;
30 import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
31 import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
32 import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
33 import org.eclipse.team.ui.mapping.SaveableComparison;
34 import org.eclipse.team.ui.synchronize.ISynchronizeParticipant;
35
36 /**
37  * A saveable compare model that wraps an {@link IFile} based compare input.
38  */

39 public class ResourceSaveableComparison extends SaveableComparison implements IPropertyChangeListener {
40
41     ICompareInput input;
42     ISynchronizeParticipant participant;
43     private final CompareEditorInput editorInput;
44     private boolean isSaving;
45     
46     public static class ResourceDiffCompareInput extends DiffNode implements ISynchronizationCompareInput, IAdaptable {
47
48         private final IDiff node;
49         private long timestamp;
50
51         public ResourceDiffCompareInput(IDiff node) {
52             super(getCompareKind(node), getAncestor(node), getLeftContributor(node), getRightContributor(node));
53             this.node = node;
54         }
55         
56         /**
57          * We need to make this public so we can fire a change event after
58          * we save
59          */

60         public void fireChange() {
61             super.fireChange();
62         }
63         
64         private static int getCompareKind(IDiff node) {
65             int kind = 0;
66             switch (node.getKind()) {
67             case IDiff.CHANGE:
68                 kind = Differencer.CHANGE;
69                 break;
70             case IDiff.ADD:
71                 kind = Differencer.ADDITION;
72                 break;
73             case IDiff.REMOVE:
74                 kind = Differencer.DELETION;
75                 break;
76             }
77             if (node instanceof IThreeWayDiff) {
78                 IThreeWayDiff twd = (IThreeWayDiff) node;
79                 switch (twd.getDirection()) {
80                 case IThreeWayDiff.INCOMING:
81                     kind |= Differencer.RIGHT;
82                     break;
83                 case IThreeWayDiff.OUTGOING:
84                     kind |= Differencer.LEFT;
85                     break;
86                 case IThreeWayDiff.CONFLICTING:
87                     kind |= Differencer.CONFLICTING;
88                     break;
89                 }
90             }
91             return kind;
92         }
93         
94         private static ITypedElement getRightContributor(IDiff node) {
95             // For a resource diff, use the after state
96
if (node instanceof IResourceDiff) {
97                 IResourceDiff rd = (IResourceDiff) node;
98                 return asTypedElement(rd.getAfterState(), getLocalEncoding(node));
99             }
100             if (node instanceof IThreeWayDiff) {
101                 IThreeWayDiff twd = (IThreeWayDiff) node;
102                 IResourceDiff diff = (IResourceDiff)twd.getRemoteChange();
103                 // If there is a remote change, use the after state
104
if (diff != null)
105                     return getRightContributor(diff);
106                 // There's no remote change so use the before state of the local
107
diff = (IResourceDiff)twd.getLocalChange();
108                 return asTypedElement(diff.getBeforeState(), getLocalEncoding(node));
109                 
110             }
111             return null;
112         }
113
114         private static ITypedElement getLeftContributor(final IDiff node) {
115             // The left contributor is always the local resource
116
final IResource resource = ResourceDiffTree.getResourceFor(node);
117             return new LocalResourceTypedElement(resource) {
118                 public boolean isEditable() {
119                     if(! resource.exists() && isOutgoingDeletion(node)) {
120                         return false;
121                     }
122                     return super.isEditable();
123                 }
124
125                 private boolean isOutgoingDeletion(IDiff node) {
126                     if (node instanceof IThreeWayDiff) {
127                         IThreeWayDiff twd = (IThreeWayDiff) node;
128                         return twd.getKind() == IDiff.REMOVE && twd.getDirection() == IThreeWayDiff.OUTGOING;
129                     }
130                     return false;
131                 }
132             };
133         }
134
135         private static ITypedElement getAncestor(IDiff node) {
136             if (node instanceof IThreeWayDiff) {
137                 IThreeWayDiff twd = (IThreeWayDiff) node;
138                 IResourceDiff diff = (IResourceDiff)twd.getLocalChange();
139                 if (diff == null)
140                     diff = (IResourceDiff)twd.getRemoteChange();
141                 return asTypedElement(diff.getBeforeState(), getLocalEncoding(node));
142                 
143             }
144             return null;
145         }
146
147         private static String JavaDoc getLocalEncoding(IDiff node) {
148             IResource resource = ResourceDiffTree.getResourceFor(node);
149             if (resource instanceof IEncodedStorage) {
150                 IEncodedStorage es = (IEncodedStorage) resource;
151                 try {
152                     return es.getCharset();
153                 } catch (CoreException e) {
154                     TeamUIPlugin.log(e);
155                 }
156             }
157             return null;
158         }
159
160         private static ITypedElement asTypedElement(IFileRevision state, String JavaDoc localEncoding) {
161             if (state == null)
162                 return null;
163             return new FileRevisionTypedElement(state, localEncoding);
164         }
165
166         /* (non-Javadoc)
167          * @see org.eclipse.team.ui.mapping.IModelCompareInput#prepareInput(org.eclipse.compare.CompareConfiguration, org.eclipse.core.runtime.IProgressMonitor)
168          */

169         public void prepareInput(CompareConfiguration configuration, IProgressMonitor monitor) throws CoreException {
170             Utils.updateLabels(node, configuration, monitor);
171             // We need to cache contents here as well
172
Object JavaDoc ancestor = getAncestor();
173             if (ancestor instanceof FileRevisionTypedElement) {
174                 FileRevisionTypedElement fste = (FileRevisionTypedElement) ancestor;
175                 fste.cacheContents(monitor);
176             }
177             Object JavaDoc right = getRight();
178             if (right instanceof FileRevisionTypedElement) {
179                 FileRevisionTypedElement fste = (FileRevisionTypedElement) right;
180                 fste.cacheContents(monitor);
181             }
182             updateTimestamp();
183         }
184
185         /* (non-Javadoc)
186          * @see org.eclipse.team.ui.mapping.ISynchronizationCompareInput#getSaveable()
187          */

188         public SaveableComparison getSaveable() {
189             return null;
190         }
191
192         /* (non-Javadoc)
193          * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
194          */

195         public Object JavaDoc getAdapter(Class JavaDoc adapter) {
196             if (adapter == IFile.class || adapter == IResource.class) {
197                 if (node instanceof IResourceDiff) {
198                     IResourceDiff rd = (IResourceDiff) node;
199                     return (IFile)rd.getResource();
200                 }
201                 if (node instanceof IThreeWayDiff) {
202                     IThreeWayDiff twd = (IThreeWayDiff) node;
203                     IResourceDiff diff = (IResourceDiff)twd.getRemoteChange();
204                     // If there is a remote change, use the after state
205
if (diff != null)
206                         return (IFile)diff.getResource();
207                     // There's no remote change so use the before state of the local
208
diff = (IResourceDiff)twd.getLocalChange();
209                     return (IFile)diff.getResource();
210                     
211                 }
212             }
213             return null;
214         }
215
216         public String JavaDoc getFullPath() {
217             final IResource resource = ResourceDiffTree.getResourceFor(node);
218             if (resource != null)
219                 return resource.getFullPath().toString();
220             return getName();
221         }
222
223         public boolean isCompareInputFor(Object JavaDoc object) {
224             final IResource resource = ResourceDiffTree.getResourceFor(node);
225             IResource other = Utils.getResource(object);
226             if (resource != null && other != null)
227                 return resource.equals(other);
228             return false;
229         }
230         
231         public boolean checkUpdateConflict() {
232             long newTimestamp = ResourceDiffTree.getResourceFor(node).getLocalTimeStamp();
233             if(newTimestamp != timestamp) {
234                 final MessageDialog dialog =
235                     new MessageDialog(TeamUIPlugin.getStandardDisplay().getActiveShell(),
236                             TeamUIMessages.SyncInfoCompareInput_0,
237                             null,
238                             TeamUIMessages.SyncInfoCompareInput_1,
239                             MessageDialog.QUESTION,
240                         new String JavaDoc[] {
241                             TeamUIMessages.SyncInfoCompareInput_2,
242                             IDialogConstants.CANCEL_LABEL},
243                         0);
244                 
245                 int retval = dialog.open();
246                 switch(retval) {
247                     // save
248
case 0:
249                         return false;
250                     // cancel
251
case 1:
252                         return true;
253                 }
254             }
255             return false;
256         }
257
258         public void updateTimestamp() {
259             timestamp = ResourceDiffTree.getResourceFor(node).getLocalTimeStamp();
260         }
261     }
262     
263     public ResourceSaveableComparison(ICompareInput input, ISynchronizeParticipant participant, ModelCompareEditorInput editorInput) {
264         this.input = input;
265         this.participant = participant;
266         this.editorInput = editorInput;
267         initializeContentChangeListeners();
268     }
269     
270     private void initializeContentChangeListeners() {
271         // We need to listen to saves to the input to catch the case
272
// where Save was picked from the context menu
273
ITypedElement te = input.getLeft();
274         if (te instanceof IContentChangeNotifier) {
275             ((IContentChangeNotifier) te).addContentChangeListener(new IContentChangeListener() {
276                 public void contentChanged(IContentChangeNotifier source) {
277                     try {
278                         if(! isSaving) {
279                             performSave(new NullProgressMonitor());
280                         }
281                     } catch (CoreException e) {
282                         TeamUIPlugin.log(e);
283                     }
284                 }
285             });
286         }
287     }
288     
289     /* (non-Javadoc)
290      * @see org.eclipse.team.ui.mapping.SaveableCompareModel#performSave(org.eclipse.core.runtime.IProgressMonitor)
291      */

292     protected void performSave(IProgressMonitor monitor) throws CoreException {
293         if (input instanceof ResourceDiffCompareInput) {
294             ResourceDiffCompareInput rdci = (ResourceDiffCompareInput) input;
295             if (rdci.checkUpdateConflict())
296                 return;
297         }
298         try {
299             isSaving = true;
300             monitor.beginTask(null, 100);
301             // First, we need to flush the viewers so the changes get buffered
302
// in the input
303
editorInput.saveChanges(Policy.subMonitorFor(monitor, 40));
304             // Then we tell the input to commit its changes
305
// Only the left is ever saveable
306
ITypedElement left = input.getLeft();
307             if (left instanceof LocalResourceTypedElement)
308                 ((LocalResourceTypedElement) left).commit(Policy.subMonitorFor(monitor, 60));
309         } finally {
310             // Make sure we fire a change for the compare input to update the viewers
311
if (input instanceof ResourceDiffCompareInput) {
312                 ResourceDiffCompareInput rdci = (ResourceDiffCompareInput) input;
313                 rdci.updateTimestamp();
314                 rdci.fireChange();
315             }
316             setDirty(false);
317             isSaving = false;
318             monitor.done();
319         }
320     }
321     
322     /* (non-Javadoc)
323      * @see org.eclipse.team.ui.mapping.SaveableCompareModel#isDirty()
324      */

325     public boolean isDirty() {
326         // We need to get the dirty state from the compare editor input
327
// since it is our only connection to the merge viewer
328
return editorInput.isSaveNeeded();
329     }
330     
331     /* (non-Javadoc)
332      * @see org.eclipse.team.ui.mapping.SaveableCompareModel#setDirty(boolean)
333      */

334     protected void setDirty(boolean dirty) {
335         // We need to set the dirty state on the compare editor input
336
// since it is our only connection to the merge viewer
337
editorInput.setDirty(dirty);
338     }
339
340     /* (non-Javadoc)
341      * @see org.eclipse.team.ui.mapping.SaveableCompareModel#performRevert(org.eclipse.core.runtime.IProgressMonitor)
342      */

343     protected void performRevert(IProgressMonitor monitor) {
344         // Only the left is ever editable
345
ITypedElement left = input.getLeft();
346         if (left instanceof LocalResourceTypedElement)
347              ((LocalResourceTypedElement) left).discardBuffer();
348     }
349
350     /* (non-Javadoc)
351      * @see org.eclipse.ui.ISaveableModel#getName()
352      */

353     public String JavaDoc getName() {
354         return input.getName();
355     }
356
357     /* (non-Javadoc)
358      * @see org.eclipse.ui.ISaveableModel#getToolTipText()
359      */

360     public String JavaDoc getToolTipText() {
361         String JavaDoc fullPath;
362         if (input instanceof ISynchronizationCompareInput) {
363             ISynchronizationCompareInput mci = (ISynchronizationCompareInput) input;
364             fullPath = mci.getFullPath();
365         } else {
366             fullPath = getName();
367         }
368         return NLS.bind(TeamUIMessages.SyncInfoCompareInput_tooltip, new String JavaDoc[] { Utils.shortenText(30, participant.getName()), fullPath });
369     }
370
371     /* (non-Javadoc)
372      * @see org.eclipse.ui.ISaveableModel#getImageDescriptor()
373      */

374     public ImageDescriptor getImageDescriptor() {
375         Image image = input.getImage();
376         if (image != null)
377             return ImageDescriptor.createFromImage(image);
378         return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW);
379     }
380
381     /* (non-Javadoc)
382      * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
383      */

384     public void propertyChange(PropertyChangeEvent e) {
385         String JavaDoc propertyName= e.getProperty();
386         if (CompareEditorInput.DIRTY_STATE.equals(propertyName)) {
387             boolean changed= false;
388             Object JavaDoc newValue= e.getNewValue();
389             if (newValue instanceof Boolean JavaDoc)
390                 changed= ((Boolean JavaDoc)newValue).booleanValue();
391             setDirty(changed);
392         }
393     }
394
395     public boolean equals(Object JavaDoc object) {
396         if (object instanceof ResourceSaveableComparison) {
397             ResourceSaveableComparison rscm = (ResourceSaveableComparison) object;
398             return rscm.input.equals(input);
399         }
400         return false;
401     }
402
403     public int hashCode() {
404         return input.hashCode();
405     }
406 }
407
Popular Tags