1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.team.internal.core.mapping;
15 
16 import org.eclipse.core.resources.IFile;
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.core.runtime.IAdaptable;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.team.core.TeamException;
21 import org.eclipse.team.core.diff.IDiff;
22 import org.eclipse.team.core.diff.IThreeWayDiff;
23 import org.eclipse.team.core.diff.ITwoWayDiff;
24 import org.eclipse.team.core.diff.provider.Diff;
25 import org.eclipse.team.core.diff.provider.ThreeWayDiff;
26 import org.eclipse.team.core.history.IFileRevision;
27 import org.eclipse.team.core.mapping.IResourceDiff;
28 import org.eclipse.team.core.mapping.provider.ResourceDiff;
29 import org.eclipse.team.core.synchronize.SyncInfo;
30 import org.eclipse.team.core.variants.IResourceVariant;
31 import org.eclipse.team.core.variants.IResourceVariantComparator;
32 import org.eclipse.team.internal.core.Messages;
33 import org.eclipse.team.internal.core.history.LocalFileRevision;
34 
35 /**
36  * Covert a SyncInfo into a IDiff
37  */
38 public class SyncInfoToDiffConverter {
39 
40 	private static class PrecalculatedSyncInfo extends SyncInfo {
41 		public int kind;
PrecalculatedSyncInfo(int kind, IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator)42 		public PrecalculatedSyncInfo(int kind, IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator) {
43 			super(local, base, remote, comparator);
44 			this.kind = kind;
45 		}
46 
47 		@Override
calculateKind()48 		protected int calculateKind() throws TeamException {
49 			return kind;
50 		}
51 	}
52 
53 	private static SyncInfoToDiffConverter instance;
54 
55 
diffKindToString(int kind)56 	public static String diffKindToString(int kind) {
57 		String label = ""; //$NON-NLS-1$
58 		if(kind==IDiff.NO_CHANGE) {
59 			label = Messages.RemoteSyncElement_insync;
60 		} else {
61 			switch(kind) {
62 				case IDiff.CHANGE: label = Messages.RemoteSyncElement_change ; break;
63 				case IDiff.ADD: label = Messages.RemoteSyncElement_addition; break;
64 				case IDiff.REMOVE: label = Messages.RemoteSyncElement_deletion; break;
65 			}
66 		}
67 		return label;
68 	}
69 
diffDirectionToString(int direction)70 	public static String diffDirectionToString(int direction) {
71 		switch(direction) {
72 			case IThreeWayDiff.CONFLICTING: return Messages.RemoteSyncElement_conflicting;
73 			case IThreeWayDiff.OUTGOING: return Messages.RemoteSyncElement_outgoing;
74 			case IThreeWayDiff.INCOMING: return Messages.RemoteSyncElement_incoming;
75 		}
76 		return ""; //$NON-NLS-1$
77 	}
78 
diffStatusToString(int status)79 	public static String diffStatusToString(int status) {
80 		int kind = status & Diff.KIND_MASK;
81 		String label = diffKindToString(kind);
82 		int direction = status & ThreeWayDiff.DIRECTION_MASK;
83 		if (direction != 0)
84 			label = NLS.bind(Messages.concatStrings, new String[] { diffDirectionToString(direction), label });
85 		return label;
86 	}
87 
asDiffFlags(int syncInfoFlags)88 	public static int asDiffFlags(int syncInfoFlags) {
89 		if (syncInfoFlags == SyncInfo.IN_SYNC)
90 			return IDiff.NO_CHANGE;
91 		int kind = SyncInfo.getChange(syncInfoFlags);
92 		int diffFlags = 0;
93 		switch (kind) {
94 		case SyncInfo.ADDITION:
95 			diffFlags = IDiff.ADD;
96 			break;
97 		case SyncInfo.DELETION:
98 			diffFlags = IDiff.REMOVE;
99 			break;
100 		case SyncInfo.CHANGE:
101 			diffFlags = IDiff.CHANGE;
102 			break;
103 		}
104 		int direction = SyncInfo.getDirection(syncInfoFlags);
105 		switch (direction) {
106 		case SyncInfo.INCOMING:
107 			diffFlags |= IThreeWayDiff.INCOMING;
108 			break;
109 		case SyncInfo.OUTGOING:
110 			diffFlags |= IThreeWayDiff.OUTGOING;
111 			break;
112 		case SyncInfo.CONFLICTING:
113 			diffFlags |= IThreeWayDiff.CONFLICTING;
114 			break;
115 		}
116 		return diffFlags;
117 	}
118 
asSyncInfoKind(IThreeWayDiff diff)119 	private static int asSyncInfoKind(IThreeWayDiff diff) {
120 		int kind = diff.getKind();
121 		if (diff.getKind() == IDiff.NO_CHANGE)
122 			return SyncInfo.IN_SYNC;
123 		int syncKind = 0;
124 		switch (kind) {
125 		case IDiff.ADD:
126 			syncKind = SyncInfo.ADDITION;
127 			break;
128 		case IDiff.REMOVE:
129 			syncKind = SyncInfo.DELETION;
130 			break;
131 		case IDiff.CHANGE:
132 			syncKind = SyncInfo.CHANGE;
133 			break;
134 		}
135 		int direction = diff.getDirection();
136 		switch (direction) {
137 		case IThreeWayDiff.INCOMING:
138 			syncKind |= SyncInfo.INCOMING;
139 			break;
140 		case IThreeWayDiff.OUTGOING:
141 			syncKind |= SyncInfo.OUTGOING;
142 			break;
143 		case IThreeWayDiff.CONFLICTING:
144 			syncKind |= SyncInfo.CONFLICTING;
145 			break;
146 		}
147 		return syncKind;
148 	}
149 
getDeltaFor(SyncInfo info)150 	public IDiff getDeltaFor(SyncInfo info) {
151 		if (info.getComparator().isThreeWay()) {
152 			ITwoWayDiff local = getLocalDelta(info);
153 			ITwoWayDiff remote = getRemoteDelta(info);
154 			return new ThreeWayDiff(local, remote);
155 		} else {
156 			if (info.getKind() != SyncInfo.IN_SYNC) {
157 				IResourceVariant remote = info.getRemote();
158 				IResource local = info.getLocal();
159 				int kind;
160 				if (remote == null) {
161 					kind = IDiff.REMOVE;
162 				} else if (!local.exists()) {
163 					kind = IDiff.ADD;
164 				} else {
165 					kind = IDiff.CHANGE;
166 				}
167 				if (local.getType() == IResource.FILE) {
168 					IFileRevision after = asFileState(remote);
169 					IFileRevision before = getFileRevisionFor((IFile)local);
170 					return new ResourceDiff(info.getLocal(), kind, 0, before, after);
171 				}
172 				// For folders, we don't need file states
173 				return new ResourceDiff(info.getLocal(), kind);
174 			}
175 			return null;
176 		}
177 	}
178 
getRemoteDelta(SyncInfo info)179 	private ITwoWayDiff getRemoteDelta(SyncInfo info) {
180 		int direction = SyncInfo.getDirection(info.getKind());
181 		if (direction == SyncInfo.INCOMING || direction == SyncInfo.CONFLICTING) {
182 			IResourceVariant ancestor = info.getBase();
183 			IResourceVariant remote = info.getRemote();
184 			int kind;
185 			if (ancestor == null) {
186 				kind = IDiff.ADD;
187 			} else if (remote == null) {
188 				kind = IDiff.REMOVE;
189 			} else {
190 				kind = IDiff.CHANGE;
191 			}
192 			// For folders, we don't need file states
193 			if (info.getLocal().getType() == IResource.FILE) {
194 				IFileRevision before = asFileState(ancestor);
195 				IFileRevision after = asFileState(remote);
196 				return new ResourceDiff(info.getLocal(), kind, 0, before, after);
197 			}
198 
199 			return new ResourceDiff(info.getLocal(), kind);
200 		}
201 		return null;
202 	}
203 
asFileState(final IResourceVariant variant)204 	private IFileRevision asFileState(final IResourceVariant variant) {
205 		if (variant == null)
206 			return null;
207 		return asFileRevision(variant);
208 	}
209 
getFileRevisionFor(final IFile file)210 	private IFileRevision getFileRevisionFor(final IFile file) {
211 		return new LocalFileRevision(file);
212 	}
213 
asFileRevision(final IResourceVariant variant)214 	protected ResourceVariantFileRevision asFileRevision(final IResourceVariant variant) {
215 		return new ResourceVariantFileRevision(variant);
216 	}
217 
getLocalDelta(SyncInfo info)218 	private ITwoWayDiff getLocalDelta(SyncInfo info) {
219 		int direction = SyncInfo.getDirection(info.getKind());
220 		if (direction == SyncInfo.OUTGOING || direction == SyncInfo.CONFLICTING) {
221 			IResourceVariant ancestor = info.getBase();
222 			IResource local = info.getLocal();
223 			int kind;
224 			if (ancestor == null) {
225 				kind = IDiff.ADD;
226 			} else if (!local.exists()) {
227 				kind = IDiff.REMOVE;
228 			} else {
229 				kind = IDiff.CHANGE;
230 			}
231 			if (local.getType() == IResource.FILE) {
232 				IFileRevision before = asFileState(ancestor);
233 				IFileRevision after = getFileRevisionFor((IFile)local);
234 				return new ResourceDiff(info.getLocal(), kind, 0, before, after);
235 			}
236 			// For folders, we don't need file states
237 			return new ResourceDiff(info.getLocal(), kind);
238 
239 		}
240 		return null;
241 	}
242 
getRemoteVariant(IThreeWayDiff twd)243 	public static IResourceVariant getRemoteVariant(IThreeWayDiff twd) {
244 		IFileRevision revision = getRemote(twd);
245 		if (revision != null)
246 			return asResourceVariant(revision);
247 		return null;
248 	}
249 
getBaseVariant(IThreeWayDiff twd)250 	public static IResourceVariant getBaseVariant(IThreeWayDiff twd) {
251 		IResourceDiff diff = (IResourceDiff)twd.getRemoteChange();
252 		if (diff != null)
253 			return asResourceVariant(diff.getBeforeState());
254 		diff = (IResourceDiff)twd.getLocalChange();
255 		if (diff != null)
256 			return asResourceVariant(diff.getBeforeState());
257 		return null;
258 	}
259 
asSyncInfo(IDiff diff, IResourceVariantComparator comparator)260 	public SyncInfo asSyncInfo(IDiff diff, IResourceVariantComparator comparator) {
261 		if (diff instanceof ResourceDiff) {
262 			ResourceDiff rd = (ResourceDiff) diff;
263 			IResource local = rd.getResource();
264 			IFileRevision afterState = rd.getAfterState();
265 			IResourceVariant remote = asResourceVariant(afterState);
266 			int kind;
267 			if (remote == null) {
268 				kind = SyncInfo.DELETION;
269 			} else if (!local.exists()) {
270 				kind = SyncInfo.ADDITION;
271 			} else {
272 				kind = SyncInfo.CHANGE;
273 			}
274 			SyncInfo info = createSyncInfo(comparator, kind, local, null, remote);
275 			return info;
276 		} else if (diff instanceof IThreeWayDiff) {
277 			IThreeWayDiff twd = (IThreeWayDiff) diff;
278 			IResource local = getLocal(twd);
279 			if (local != null) {
280 				IResourceVariant remote = getRemoteVariant(twd);
281 				IResourceVariant base = getBaseVariant(twd);
282 				int kind = asSyncInfoKind(twd);
283 				SyncInfo info = createSyncInfo(comparator, kind, local, base, remote);
284 				return info;
285 			}
286 		}
287 		return null;
288 	}
289 
createSyncInfo(IResourceVariantComparator comparator, int kind, IResource local, IResourceVariant base, IResourceVariant remote)290 	protected SyncInfo createSyncInfo(IResourceVariantComparator comparator, int kind, IResource local, IResourceVariant base, IResourceVariant remote) {
291 		PrecalculatedSyncInfo info = new PrecalculatedSyncInfo(kind, local, base, remote, comparator);
292 		try {
293 			info.init();
294 		} catch (TeamException e) {
295 			// Ignore
296 		}
297 		return info;
298 	}
299 
getLocal(IThreeWayDiff twd)300 	private static IResource getLocal(IThreeWayDiff twd) {
301 		IResourceDiff diff = (IResourceDiff)twd.getRemoteChange();
302 		if (diff != null)
303 			return diff.getResource();
304 		diff = (IResourceDiff)twd.getLocalChange();
305 		if (diff != null)
306 			return diff.getResource();
307 		return null;
308 	}
309 
asResourceVariant(IFileRevision revision)310 	public static IResourceVariant asResourceVariant(IFileRevision revision) {
311 		if (revision == null)
312 			return null;
313 		if (revision instanceof ResourceVariantFileRevision) {
314 			ResourceVariantFileRevision rvfr = (ResourceVariantFileRevision) revision;
315 			return rvfr.getVariant();
316 		}
317 		if (revision instanceof IAdaptable) {
318 			IAdaptable adaptable = (IAdaptable) revision;
319 			Object o = adaptable.getAdapter(IResourceVariant.class);
320 			if (o instanceof IResourceVariant) {
321 				return (IResourceVariant) o;
322 			}
323 		}
324 		return null;
325 	}
326 
getRemote(IDiff diff)327 	public static IFileRevision getRemote(IDiff diff) {
328 		if (diff instanceof IResourceDiff) {
329 			IResourceDiff rd = (IResourceDiff) diff;
330 			return rd.getAfterState();
331 		}
332 		if (diff instanceof IThreeWayDiff) {
333 			IThreeWayDiff twd = (IThreeWayDiff) diff;
334 			return getRemote(twd);
335 		}
336 		return null;
337 	}
338 
getRemote(IThreeWayDiff twd)339 	public static IFileRevision getRemote(IThreeWayDiff twd) {
340 		IResourceDiff rd = (IResourceDiff)twd.getRemoteChange();
341 		if (rd != null)
342 			return rd.getAfterState();
343 		rd = (IResourceDiff)twd.getLocalChange();
344 		if (rd != null)
345 			return rd.getBeforeState();
346 		return null;
347 	}
348 
getDefault()349 	public static SyncInfoToDiffConverter getDefault() {
350 		if (instance == null)
351 			instance = new SyncInfoToDiffConverter();
352 		return instance;
353 	}
354 }
355