KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2006, 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.team.internal.ui.mapping;
12
13 import org.eclipse.compare.*;
14 import org.eclipse.compare.structuremergeviewer.Differencer;
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.resources.mapping.ResourceMapping;
17 import org.eclipse.core.runtime.*;
18 import org.eclipse.team.core.diff.IDiff;
19 import org.eclipse.team.core.diff.IThreeWayDiff;
20 import org.eclipse.team.core.history.IFileRevision;
21 import org.eclipse.team.core.mapping.IResourceDiff;
22 import org.eclipse.team.core.mapping.ISynchronizationContext;
23 import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
24 import org.eclipse.team.internal.ui.TeamUIPlugin;
25 import org.eclipse.team.internal.ui.Utils;
26 import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
27 import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
28 import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
29 import org.eclipse.team.ui.mapping.SaveableComparison;
30
31 /**
32  * A resource-based compare input that gets it's contributors from an {@link IDiff}.
33  */

34 public class ResourceDiffCompareInput extends AbstractCompareInput implements ISynchronizationCompareInput, IAdaptable, IResourceProvider {
35
36     private IDiff node;
37     private final ISynchronizationContext context;
38     
39     public static int getCompareKind(IDiff node) {
40         int compareKind = 0;
41         if (node != null) {
42             switch (node.getKind()) {
43             case IDiff.ADD:
44                 compareKind = Differencer.ADDITION;
45                 break;
46             case IDiff.REMOVE:
47                 compareKind = Differencer.DELETION;
48                 break;
49             case IDiff.CHANGE:
50                 compareKind = Differencer.CHANGE;
51                 break;
52             }
53             if (node instanceof IThreeWayDiff) {
54                 IThreeWayDiff twd = (IThreeWayDiff) node;
55                 switch (twd.getDirection()) {
56                 case IThreeWayDiff.OUTGOING :
57                     compareKind |= Differencer.RIGHT;
58                     break;
59                 case IThreeWayDiff.INCOMING :
60                     compareKind |= Differencer.LEFT;
61                     break;
62                 case IThreeWayDiff.CONFLICTING :
63                     compareKind |= Differencer.LEFT;
64                     compareKind |= Differencer.RIGHT;
65                     break;
66                 }
67             }
68         }
69         return compareKind;
70     }
71     
72     private static FileRevisionTypedElement getRightContributor(IDiff node) {
73         // For a resource diff, use the after state
74
if (node instanceof IResourceDiff) {
75             IResourceDiff rd = (IResourceDiff) node;
76             return asTypedElement(rd.getAfterState(), getLocalEncoding(node));
77         }
78         if (node instanceof IThreeWayDiff) {
79             IThreeWayDiff twd = (IThreeWayDiff) node;
80             IResourceDiff diff = (IResourceDiff)twd.getRemoteChange();
81             // If there is a remote change, use the after state
82
if (diff != null)
83                 return getRightContributor(diff);
84             // There's no remote change so use the before state of the local
85
diff = (IResourceDiff)twd.getLocalChange();
86             return asTypedElement(diff.getBeforeState(), getLocalEncoding(node));
87             
88         }
89         return null;
90     }
91
92     private static LocalResourceTypedElement getLeftContributor(final IDiff node) {
93         // The left contributor is always the local resource
94
return new LocalResourceTypedElement(ResourceDiffTree.getResourceFor(node));
95     }
96
97     private static FileRevisionTypedElement getAncestor(IDiff node) {
98         if (node instanceof IThreeWayDiff) {
99             IThreeWayDiff twd = (IThreeWayDiff) node;
100             IResourceDiff diff = (IResourceDiff)twd.getLocalChange();
101             if (diff == null)
102                 diff = (IResourceDiff)twd.getRemoteChange();
103             return asTypedElement(diff.getBeforeState(), getLocalEncoding(node));
104             
105         }
106         return null;
107     }
108
109     private static String JavaDoc getLocalEncoding(IDiff node) {
110         IResource resource = ResourceDiffTree.getResourceFor(node);
111         if (resource instanceof IEncodedStorage) {
112             IEncodedStorage es = (IEncodedStorage) resource;
113             try {
114                 return es.getCharset();
115             } catch (CoreException e) {
116                 TeamUIPlugin.log(e);
117             }
118         }
119         return null;
120     }
121
122     private static FileRevisionTypedElement asTypedElement(IFileRevision state, String JavaDoc localEncoding) {
123         if (state == null)
124             return null;
125         return new FileRevisionTypedElement(state, localEncoding);
126     }
127
128     public static void ensureContentsCached(IDiff diff, IProgressMonitor monitor) throws CoreException {
129         if (diff != null) {
130             ensureContentsCached(getAncestor(diff), getRightContributor(diff), monitor);
131         }
132     }
133     
134     private static void ensureContentsCached(Object JavaDoc ancestor, Object JavaDoc right,
135             IProgressMonitor monitor) throws CoreException {
136         SubMonitor sm = SubMonitor.convert(monitor, 100);
137         if (ancestor instanceof FileRevisionTypedElement) {
138             FileRevisionTypedElement fste = (FileRevisionTypedElement) ancestor;
139             fste.cacheContents(sm.newChild(50));
140         } else {
141             sm.setWorkRemaining(50);
142         }
143         if (right instanceof FileRevisionTypedElement) {
144             FileRevisionTypedElement fste = (FileRevisionTypedElement) right;
145             fste.cacheContents(sm.newChild(50));
146         }
147         if (monitor != null)
148             monitor.done();
149     }
150     
151     /**
152      * Create the compare input on the given diff.
153      * @param diff the diff
154      * @param context the synchronization context
155      */

156     public ResourceDiffCompareInput(IDiff diff, ISynchronizationContext context) {
157         super(getCompareKind(diff), getAncestor(diff), getLeftContributor(diff), getRightContributor(diff));
158         this.node = diff;
159         this.context = context;
160     }
161     
162     /**
163      * Fire a compare input change event.
164      * This method is public so that the change can be fired
165      * by the containing editor input on a save.
166      */

167     public void fireChange() {
168         super.fireChange();
169     }
170     
171     /* (non-Javadoc)
172      * @see org.eclipse.team.ui.mapping.ISynchronizationCompareInput#prepareInput(org.eclipse.compare.CompareConfiguration, org.eclipse.core.runtime.IProgressMonitor)
173      */

174     public void prepareInput(CompareConfiguration configuration, IProgressMonitor monitor) throws CoreException {
175         configuration.setLabelProvider(this, ((ResourceCompareInputChangeNotifier)getChangeNotifier()).getLabelProvider());
176         ensureContentsCached(getAncestor(), getRight(), monitor);
177     }
178
179     /* (non-Javadoc)
180      * @see org.eclipse.team.ui.mapping.ISynchronizationCompareInput#getSaveable()
181      */

182     public SaveableComparison getSaveable() {
183         return null;
184     }
185
186     /* (non-Javadoc)
187      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
188      */

189     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
190         if (adapter == IFile.class || adapter == IResource.class) {
191             return ResourceDiffTree.getResourceFor(node);
192         }
193         if (adapter == ResourceMapping.class) {
194             IResource resource = ResourceDiffTree.getResourceFor(node);
195             return resource.getAdapter(adapter);
196         }
197         return null;
198     }
199
200     /* (non-Javadoc)
201      * @see org.eclipse.team.ui.mapping.ISynchronizationCompareInput#getFullPath()
202      */

203     public String JavaDoc getFullPath() {
204         final IResource resource = ResourceDiffTree.getResourceFor(node);
205         if (resource != null)
206             return resource.getFullPath().toString();
207         return getName();
208     }
209
210     /* (non-Javadoc)
211      * @see org.eclipse.team.ui.mapping.ISynchronizationCompareInput#isCompareInputFor(java.lang.Object)
212      */

213     public boolean isCompareInputFor(Object JavaDoc object) {
214         final IResource resource = ResourceDiffTree.getResourceFor(node);
215         IResource other = Utils.getResource(object);
216         if (resource != null && other != null)
217             return resource.equals(other);
218         return false;
219     }
220
221     /* (non-Javadoc)
222      * @see org.eclipse.compare.IResourceProvider#getResource()
223      */

224     public IResource getResource() {
225         return ResourceDiffTree.getResourceFor(node);
226     }
227
228     /**
229      * Return a compare input change notifier that will detect changes in the synchronization context and
230      * translate them into compare input change events by calling {@link #update()}.
231      * @return a compare input change notifier
232      */

233     public CompareInputChangeNotifier getChangeNotifier() {
234         return ResourceCompareInputChangeNotifier.getChangeNotifier(context);
235     }
236
237     /* (non-Javadoc)
238      * @see org.eclipse.compare.structuremergeviewer.DiffNode#equals(java.lang.Object)
239      */

240     public boolean equals(Object JavaDoc other) {
241         if (other == this)
242             return true;
243         if (other instanceof ResourceDiffCompareInput) {
244             ResourceDiffCompareInput otherInput = (ResourceDiffCompareInput) other;
245             return (isEqual(getLeft(), otherInput.getLeft())
246                     && isEqual(getRight(), otherInput.getRight())
247                     && isEqual(getAncestor(), otherInput.getAncestor()));
248         }
249         return false;
250     }
251     
252     private boolean isEqual(ITypedElement e1, ITypedElement e2) {
253         if (e1 == null) {
254             return e2 == null;
255         }
256         if (e2 == null)
257             return false;
258         return e1.equals(e2);
259     }
260
261     /* (non-Javadoc)
262      * @see org.eclipse.compare.structuremergeviewer.DiffNode#hashCode()
263      */

264     public int hashCode() {
265         return getResource().hashCode();
266     }
267
268     /**
269      * Re-obtain the diff for this compare input and update the kind and 3
270      * contributor appropriately.
271      */

272     public void update() {
273         IDiff newNode = context.getDiffTree().getDiff(getResource());
274         if (newNode == null) {
275             // The resource is in-sync. Just leave the ancestor and right the same and set the kind
276
setKind(Differencer.NO_CHANGE);
277             fireChange();
278         } else {
279             LocalResourceTypedElement left = (LocalResourceTypedElement)getLeft();
280             if (!this.node.equals(newNode) || !left.isSynchronized()) {
281                 this.node = newNode;
282                 setKind(getCompareKind(node));
283                 left.update();
284                 FileRevisionTypedElement newRight = getRightContributor(node);
285                 propogateAuthorIfSameRevision((FileRevisionTypedElement)getRight(), newRight);
286                 setRight(newRight);
287                 FileRevisionTypedElement newAncestor = getAncestor(node);
288                 propogateAuthorIfSameRevision((FileRevisionTypedElement)getAncestor(), newAncestor);
289                 setAncestor(newAncestor);
290                 propogateAuthorIfSameRevision((FileRevisionTypedElement)getAncestor(), (FileRevisionTypedElement)getRight());
291             }
292             fireChange();
293         }
294     }
295
296     private boolean propogateAuthorIfSameRevision(FileRevisionTypedElement oldContributor,
297             FileRevisionTypedElement newContributor) {
298         if (oldContributor == null || newContributor == null)
299             return false;
300         String JavaDoc author = oldContributor.getAuthor();
301         if (newContributor.getAuthor() == null
302                 && author != null
303                 && oldContributor.getContentIdentifier().equals(newContributor.getContentIdentifier())) {
304             newContributor.setAuthor(author);
305             return true;
306         }
307         return false;
308     }
309
310     /**
311      * Return whether the diff associated with this input has changed.
312      * @return whether the diff associated with this input has changed
313      */

314     public boolean needsUpdate() {
315         IDiff newNode = context.getDiffTree().getDiff(getResource());
316         return newNode == null || !newNode.equals(node);
317     }
318
319     /**
320      * Return the local content id for this compare input.
321      * @return the local content id for this compare input
322      */

323     public String JavaDoc getLocalContentId() {
324         return Utils.getLocalContentId(node);
325     }
326
327     public boolean updateAuthorInfo(IProgressMonitor monitor) throws CoreException {
328         boolean authorFound = false;
329         FileRevisionTypedElement ancestor = (FileRevisionTypedElement)getAncestor();
330         FileRevisionTypedElement right = (FileRevisionTypedElement)getRight();
331         if (ancestor != null && ancestor.getAuthor() == null) {
332             ancestor.fetchAuthor(monitor);
333             if (right != null && propogateAuthorIfSameRevision(ancestor, right)) {
334                 return true;
335             }
336             authorFound = ancestor.getAuthor() != null;
337         }
338         if (right != null && right.getAuthor() == null) {
339             right.fetchAuthor(monitor);
340             authorFound |= right.getAuthor() != null;
341         }
342         return authorFound;
343     }
344
345 }
346
Popular Tags