1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 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.ltk.internal.core.refactoring.resource;
15 
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.core.runtime.IPath;
22 
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
26 
27 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
28 import org.eclipse.ltk.core.refactoring.participants.CopyArguments;
29 import org.eclipse.ltk.core.refactoring.participants.CopyParticipant;
30 import org.eclipse.ltk.core.refactoring.participants.CreateArguments;
31 import org.eclipse.ltk.core.refactoring.participants.CreateParticipant;
32 import org.eclipse.ltk.core.refactoring.participants.DeleteArguments;
33 import org.eclipse.ltk.core.refactoring.participants.DeleteParticipant;
34 import org.eclipse.ltk.core.refactoring.participants.MoveArguments;
35 import org.eclipse.ltk.core.refactoring.participants.MoveParticipant;
36 import org.eclipse.ltk.core.refactoring.participants.ParticipantManager;
37 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
38 import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
39 import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
40 import org.eclipse.ltk.core.refactoring.participants.RenameParticipant;
41 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
42 
43 /**
44  * A data structure to collect resource modifications.
45  *
46  * @since 3.4
47  */
48 public class ResourceModifications {
49 
50 	private List<IResource> fCreate;
51 	private List<IResource> fDelete;
52 
53 	private List<IResource> fMove;
54 	private List<MoveArguments> fMoveArguments;
55 
56 	private List<IResource> fRename;
57 	private List<RenameArguments> fRenameArguments;
58 
59 	private List<IResource> fCopy;
60 	private List<CopyArguments> fCopyArguments;
61 
62 	private int fIgnoreCount;
63 	private List<DeltaDescription> fDeltaDescriptions;
64 
65 	public static abstract class DeltaDescription {
66 		protected IResource fResource;
DeltaDescription(IResource resource)67 		public DeltaDescription(IResource resource) {
68 			fResource= resource;
69 		}
buildDelta(IResourceChangeDescriptionFactory builder)70 		public abstract void buildDelta(IResourceChangeDescriptionFactory builder);
getDestinationPath()71 		public abstract IPath getDestinationPath();
72 
73 	}
74 	public static class DeleteDescription extends DeltaDescription {
DeleteDescription(IResource resource)75 		public DeleteDescription(IResource resource) {
76 			super(resource);
77 		}
78 		@Override
buildDelta(IResourceChangeDescriptionFactory builder)79 		public void buildDelta(IResourceChangeDescriptionFactory builder) {
80 			builder.delete(fResource);
81 		}
82 		@Override
getDestinationPath()83 		public IPath getDestinationPath() {
84 			return null;
85 		}
86 	}
87 	public static class ChangedDescription extends DeltaDescription {
ChangedDescription(IFile resource)88 		public ChangedDescription(IFile resource) {
89 			super(resource);
90 		}
91 		@Override
buildDelta(IResourceChangeDescriptionFactory builder)92 		public void buildDelta(IResourceChangeDescriptionFactory builder) {
93 			builder.change((IFile)fResource);
94 		}
95 		@Override
getDestinationPath()96 		public IPath getDestinationPath() {
97 			return null;
98 		}
99 	}
100 	public static class CreateDescription extends DeltaDescription {
CreateDescription(IResource resource)101 		public CreateDescription(IResource resource) {
102 			super(resource);
103 		}
104 		@Override
buildDelta(IResourceChangeDescriptionFactory builder)105 		public void buildDelta(IResourceChangeDescriptionFactory builder) {
106 			builder.create(fResource);
107 		}
108 		@Override
getDestinationPath()109 		public IPath getDestinationPath() {
110 			return fResource.getFullPath();
111 		}
112 	}
113 	public static class MoveDescription extends DeltaDescription {
114 		private IPath fDestination;
MoveDescription(IResource resource, IPath destination)115 		public MoveDescription(IResource resource, IPath destination) {
116 			super(resource);
117 			fDestination= destination;
118 		}
119 		@Override
buildDelta(IResourceChangeDescriptionFactory builder)120 		public void buildDelta(IResourceChangeDescriptionFactory builder) {
121 			builder.move(fResource, fDestination);
122 		}
123 		@Override
getDestinationPath()124 		public IPath getDestinationPath() {
125 			return fDestination;
126 		}
127 	}
128 	public static class CopyDescription extends DeltaDescription {
129 		private IPath fDestination;
CopyDescription(IResource resource, IPath destination)130 		public CopyDescription(IResource resource, IPath destination) {
131 			super(resource);
132 			fDestination= destination;
133 		}
134 		@Override
buildDelta(IResourceChangeDescriptionFactory builder)135 		public void buildDelta(IResourceChangeDescriptionFactory builder) {
136 			builder.copy(fResource, fDestination);
137 		}
138 		@Override
getDestinationPath()139 		public IPath getDestinationPath() {
140 			return fDestination;
141 		}
142 	}
143 
144 	/**
145 	 * Adds the given file to the list of changed files.
146 	 *
147 	 * @param file the changed file
148 	 */
addChanged(IFile file)149 	public void addChanged(IFile file) {
150 		if (fIgnoreCount == 0) {
151 			internalAdd(new ChangedDescription(file));
152 		}
153 	}
154 
155 	/**
156 	 * Adds the given resource to the list of resources
157 	 * to be created.
158 	 *
159 	 * @param create the resource to be add to the list of
160 	 *  resources to be created
161 	 */
addCreate(IResource create)162 	public void addCreate(IResource create) {
163 		if (fCreate == null)
164 			fCreate= new ArrayList<>(2);
165 		fCreate.add(create);
166 		if (fIgnoreCount == 0) {
167 			internalAdd(new CreateDescription(create));
168 		}
169 	}
170 
171 	/**
172 	 * Adds the given resource to the list of resources
173 	 * to be deleted.
174 	 *
175 	 * @param delete the resource to be deleted
176 	 */
addDelete(IResource delete)177 	public void addDelete(IResource delete) {
178 		if (fDelete == null)
179 			fDelete= new ArrayList<>(2);
180 		fDelete.add(delete);
181 		if (fIgnoreCount == 0) {
182 			internalAdd(new DeleteDescription(delete));
183 		}
184 	}
185 
186 	/**
187 	 * Adds the given resource to the list of resources
188 	 * to be moved.
189 	 *
190 	 * @param move the resource to be moved
191 	 * @param arguments the move arguments
192 	 */
addMove(IResource move, MoveArguments arguments)193 	public void addMove(IResource move, MoveArguments arguments) {
194 		if (fMove == null) {
195 			fMove= new ArrayList<>(2);
196 			fMoveArguments= new ArrayList<>(2);
197 		}
198 		fMove.add(move);
199 		fMoveArguments.add(arguments);
200 		if (fIgnoreCount == 0) {
201 			IPath destination= ((IResource)arguments.getDestination()).getFullPath().append(move.getName());
202 			internalAdd(new MoveDescription(move, destination));
203 		}
204 	}
205 
206 	/**
207 	 * Adds the given resource to the list of resources
208 	 * to be copied.
209 	 *
210 	 * @param copy the resource to be copied
211 	 * @param arguments the copy arguments
212 	 */
addCopy(IResource copy, CopyArguments arguments)213 	public void addCopy(IResource copy, CopyArguments arguments) {
214 		if (fCopy == null) {
215 			fCopy= new ArrayList<>(2);
216 			fCopyArguments= new ArrayList<>(2);
217 		}
218 		fCopy.add(copy);
219 		fCopyArguments.add(arguments);
220 		addCopyDelta(copy, arguments);
221 	}
222 
223 	/**
224 	 * Adds the given resource to the list of renamed
225 	 * resources.
226 	 *
227 	 * @param rename the resource to be renamed
228 	 * @param arguments the arguments of the rename
229 	 */
addRename(IResource rename, RenameArguments arguments)230 	public void addRename(IResource rename, RenameArguments arguments) {
231 		Assert.isNotNull(rename);
232 		Assert.isNotNull(arguments);
233 		if (fRename == null) {
234 			fRename= new ArrayList<>(2);
235 			fRenameArguments= new ArrayList<>(2);
236 		}
237 		fRename.add(rename);
238 		fRenameArguments.add(arguments);
239 		if (fIgnoreCount == 0) {
240 			IPath newPath= rename.getFullPath().removeLastSegments(1).append(arguments.getNewName());
241 			internalAdd(new MoveDescription(rename, newPath));
242 		}
243 	}
244 
getParticipants(RefactoringStatus status, RefactoringProcessor processor, String[] natures, SharableParticipants shared)245 	public RefactoringParticipant[] getParticipants(RefactoringStatus status, RefactoringProcessor processor, String[] natures, SharableParticipants shared) {
246 		List<RefactoringParticipant> result= new ArrayList<>(5);
247 		if (fDelete != null) {
248 			DeleteArguments arguments= new DeleteArguments();
249 			for (IResource iResource : fDelete) {
250 				DeleteParticipant[] deletes= ParticipantManager.loadDeleteParticipants(status,
251 					processor, iResource,
252 					arguments, natures, shared);
253 				Collections.addAll(result, deletes);
254 			}
255 		}
256 		if (fCreate != null) {
257 			CreateArguments arguments= new CreateArguments();
258 			for (IResource iResource : fCreate) {
259 				CreateParticipant[] creates= ParticipantManager.loadCreateParticipants(status,
260 					processor, iResource,
261 					arguments, natures, shared);
262 				Collections.addAll(result, creates);
263 			}
264 		}
265 		if (fMove != null) {
266 			for (int i= 0; i < fMove.size(); i++) {
267 				Object element= fMove.get(i);
268 				MoveArguments arguments= fMoveArguments.get(i);
269 				MoveParticipant[] moves= ParticipantManager.loadMoveParticipants(status,
270 					processor, element,
271 					arguments, natures, shared);
272 				Collections.addAll(result, moves);
273 
274 			}
275 		}
276 		if (fCopy != null) {
277 			for (int i= 0; i < fCopy.size(); i++) {
278 				Object element= fCopy.get(i);
279 				CopyArguments arguments= fCopyArguments.get(i);
280 				CopyParticipant[] copies= ParticipantManager.loadCopyParticipants(status,
281 					processor, element,
282 					arguments, natures, shared);
283 				Collections.addAll(result, copies);
284 			}
285 		}
286 		if (fRename != null) {
287 			for (int i= 0; i < fRename.size(); i++) {
288 				Object resource= fRename.get(i);
289 				RenameArguments arguments= fRenameArguments.get(i);
290 				RenameParticipant[] renames= ParticipantManager.loadRenameParticipants(status,
291 					processor, resource,
292 					arguments, natures, shared);
293 				Collections.addAll(result, renames);
294 			}
295 		}
296 		return result.toArray(new RefactoringParticipant[result.size()]);
297 	}
298 
ignoreForDelta()299 	public void ignoreForDelta() {
300 		fIgnoreCount++;
301 	}
302 
trackForDelta()303 	public void trackForDelta() {
304 		fIgnoreCount--;
305 	}
306 
addDelta(DeltaDescription description)307 	public void addDelta(DeltaDescription description) {
308 		if (fIgnoreCount > 0)
309 			return;
310 		internalAdd(description);
311 	}
312 
addCopyDelta(IResource copy, CopyArguments arguments)313 	public void addCopyDelta(IResource copy, CopyArguments arguments) {
314 		if (fIgnoreCount == 0) {
315 			IPath destination= ((IResource)arguments.getDestination()).getFullPath().append(copy.getName());
316 			internalAdd(new CopyDescription(copy, destination));
317 		}
318 	}
319 
320 	/**
321 	 * Checks if the resource will exist in the future based on
322 	 * the recorded resource modifications.
323 	 *
324 	 * @param resource the resource to check
325 	 * @return whether the resource will exist or not
326 	 */
willExist(IResource resource)327 	public boolean willExist(IResource resource) {
328 		if (fDeltaDescriptions == null)
329 			return false;
330 		IPath fullPath= resource.getFullPath();
331 		for (DeltaDescription delta : fDeltaDescriptions) {
332 			if (fullPath.equals(delta.getDestinationPath()))
333 				return true;
334 		}
335 		return false;
336 	}
337 
buildDelta(IResourceChangeDescriptionFactory builder)338 	public void buildDelta(IResourceChangeDescriptionFactory builder) {
339 		if (fDeltaDescriptions == null)
340 			return;
341 		for (DeltaDescription deltaDescription : fDeltaDescriptions) {
342 			deltaDescription.buildDelta(builder);
343 		}
344 	}
345 
buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, RenameArguments args)346 	public static void buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, RenameArguments args) {
347 		IPath newPath= resource.getFullPath().removeLastSegments(1).append(args.getNewName());
348 		builder.move(resource, newPath);
349 	}
350 
buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, MoveArguments args)351 	public static void buildMoveDelta(IResourceChangeDescriptionFactory builder, IResource resource, MoveArguments args) {
352 		IPath destination= ((IResource)args.getDestination()).getFullPath().append(resource.getName());
353 		builder.move(resource, destination);
354 	}
355 
buildCopyDelta(IResourceChangeDescriptionFactory builder, IResource resource, CopyArguments args)356 	public static void buildCopyDelta(IResourceChangeDescriptionFactory builder, IResource resource, CopyArguments args) {
357 		IPath destination= ((IResource)args.getDestination()).getFullPath().append(resource.getName());
358 		builder.copy(resource, destination);
359 	}
360 
internalAdd(DeltaDescription description)361 	private void internalAdd(DeltaDescription description) {
362 		if (fDeltaDescriptions == null)
363 			fDeltaDescriptions= new ArrayList<>();
364 		fDeltaDescriptions.add(description);
365 	}
366 }
367