KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > resources > mapping > ResourceChangeDescriptionFactory


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.core.internal.resources.mapping;
12
13 import org.eclipse.core.internal.utils.Policy;
14 import org.eclipse.core.resources.*;
15 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IPath;
18
19 /**
20  * Factory for creating a resource delta that describes a proposed change.
21  */

22 public class ResourceChangeDescriptionFactory implements IResourceChangeDescriptionFactory {
23
24     private ProposedResourceDelta root = new ProposedResourceDelta(ResourcesPlugin.getWorkspace().getRoot());
25
26     /**
27      * Creates and a delta representing a deleted resource, and adds it to the provided
28      * parent delta.
29      * @param parentDelta The parent of the deletion delta to create
30      * @param resource The deleted resource to create a delta for
31      */

32     private ProposedResourceDelta buildDeleteDelta(ProposedResourceDelta parentDelta, IResource resource) {
33         //start with the existing delta for this resource, if any, to preserve other flags
34
ProposedResourceDelta delta = parentDelta.getChild(resource.getName());
35         if (delta == null) {
36             delta = new ProposedResourceDelta(resource);
37             parentDelta.add(delta);
38         }
39         delta.setKind(IResourceDelta.REMOVED);
40         if (resource.getType() == IResource.FILE)
41             return delta;
42         //recurse to build deletion deltas for children
43
try {
44             IResource[] members = ((IContainer) resource).members();
45             int childCount = members.length;
46             if (childCount > 0) {
47                 ProposedResourceDelta[] childDeltas = new ProposedResourceDelta[childCount];
48                 for (int i = 0; i < childCount; i++)
49                     childDeltas[i] = buildDeleteDelta(delta, members[i]);
50             }
51         } catch (CoreException e) {
52             //don't need to create deletion deltas for children of inaccessible resources
53
}
54         return delta;
55     }
56
57     /* (non-Javadoc)
58      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#change(org.eclipse.core.resources.IFile)
59      */

60     public void change(IFile file) {
61         ProposedResourceDelta delta = getDelta(file);
62         if (delta.getKind() == 0)
63             delta.setKind(IResourceDelta.CHANGED);
64         //the CONTENT flag only applies to the changed and moved from cases
65
if (delta.getKind() == IResourceDelta.CHANGED
66                 || (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0
67                 || (delta.getFlags() & IResourceDelta.COPIED_FROM) != 0)
68             delta.addFlags(IResourceDelta.CONTENT);
69     }
70
71     /* (non-Javadoc)
72      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#close(org.eclipse.core.resources.IProject)
73      */

74     public void close(IProject project) {
75         delete(project);
76         ProposedResourceDelta delta = getDelta(project);
77         delta.addFlags(IResourceDelta.OPEN);
78     }
79
80     /* (non-Javadoc)
81      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#copy(org.eclipse.core.resources.IResource, org.eclipse.core.runtime.IPath)
82      */

83     public void copy(IResource resource, IPath destination) {
84         moveOrCopyDeep(resource, destination, false /* copy */);
85     }
86
87     /* (non-Javadoc)
88      * @see org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory#create(org.eclipse.core.resources.IResource)
89      */

90     public void create(IResource resource) {
91         getDelta(resource).setKind(IResourceDelta.ADDED);
92     }
93
94     /* (non-Javadoc)
95      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#delete(org.eclipse.core.resources.IResource)
96      */

97     public void delete(IResource resource) {
98         if (resource.getType() == IResource.ROOT) {
99             //the root itself cannot be deleted, so create deletions for each project
100
IProject[] projects = ((IWorkspaceRoot)resource).getProjects();
101             for (int i = 0; i < projects.length; i++)
102                 buildDeleteDelta(root, projects[i]);
103         } else {
104             buildDeleteDelta(getDelta(resource.getParent()), resource);
105         }
106     }
107
108     private void fail(CoreException e) {
109         Policy.log(e.getStatus().getSeverity(), "An internal error occurred while accumulating a change description.", e); //$NON-NLS-1$
110
}
111
112     /* (non-Javadoc)
113      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#getDelta()
114      */

115     public IResourceDelta getDelta() {
116         return root;
117     }
118
119     ProposedResourceDelta getDelta(IResource resource) {
120         ProposedResourceDelta delta = (ProposedResourceDelta) root.findMember(resource.getFullPath());
121         if (delta != null) {
122             return delta;
123         }
124         ProposedResourceDelta parent = getDelta(resource.getParent());
125         delta = new ProposedResourceDelta(resource);
126         parent.add(delta);
127         return delta;
128     }
129
130     /*
131      * Return the resource at the destination path that corresponds to the source resource
132      * @param source the source resource
133      * @param sourcePrefix the path of the root of the move or copy
134      * @param destinationPrefix the path of the destination the root was copied to
135      * @return the destination resource
136      */

137     protected IResource getDestinationResource(IResource source, IPath sourcePrefix, IPath destinationPrefix) {
138         IPath relativePath = source.getFullPath().removeFirstSegments(sourcePrefix.segmentCount());
139         IPath destinationPath = destinationPrefix.append(relativePath);
140         IResource destination;
141         IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
142         switch (source.getType()) {
143             case IResource.FILE :
144                 destination = wsRoot.getFile(destinationPath);
145                 break;
146             case IResource.FOLDER :
147                 destination = wsRoot.getFolder(destinationPath);
148                 break;
149             case IResource.PROJECT :
150                 destination = wsRoot.getProject(destinationPath.segment(0));
151                 break;
152             default :
153                 // Shouldn't happen
154
destination = null;
155         }
156         return destination;
157     }
158
159     /* (non-Javadoc)
160      * @see org.eclipse.core.resources.mapping.IProposedResourceDeltaFactory#move(org.eclipse.core.resources.IResource, org.eclipse.core.runtime.IPath)
161      */

162     public void move(IResource resource, IPath destination) {
163         moveOrCopyDeep(resource, destination, true /* move */);
164     }
165
166     /**
167      * Builds the delta representing a single resource being moved or copied.
168      *
169      * @param resource The resource being moved
170      * @param sourcePrefix The root of the sub-tree being moved
171      * @param destinationPrefix The root of the destination sub-tree
172      * @param move <code>true</code> for a move, <code>false</code> for a copy
173      * @return Whether to move or copy the child
174      */

175     boolean moveOrCopy(IResource resource, final IPath sourcePrefix, final IPath destinationPrefix, final boolean move) {
176         ProposedResourceDelta sourceDelta = getDelta(resource);
177         if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
178             // There is already a removed delta here so there
179
// is nothing to move/copy
180
return false;
181         }
182         IResource destinationResource = getDestinationResource(resource, sourcePrefix, destinationPrefix);
183         ProposedResourceDelta destinationDelta = getDelta(destinationResource);
184         if ((destinationDelta.getKind() & (IResourceDelta.ADDED | IResourceDelta.CHANGED)) > 0) {
185             // There is already a resource at the destination
186
// TODO: What do we do
187
return false;
188         }
189         // First, create the delta for the source
190
IPath fromPath = resource.getFullPath();
191         boolean wasAdded = false;
192         final int sourceFlags = sourceDelta.getFlags();
193         if (move) {
194             // We transfer the source flags to the destination
195
if (sourceDelta.getKind() == IResourceDelta.ADDED) {
196                 if ((sourceFlags & IResourceDelta.MOVED_FROM) != 0) {
197                     // The resource was moved from somewhere else so
198
// we need to transfer the path to the new location
199
fromPath = sourceDelta.getMovedFromPath();
200                     sourceDelta.setMovedFromPath(null);
201                 }
202                 // The source was added and then moved so we'll
203
// make it an add at the destination
204
sourceDelta.setKind(0);
205                 wasAdded = true;
206             } else {
207                 // We reset the status to be a remove/move_to
208
sourceDelta.setKind(IResourceDelta.REMOVED);
209                 sourceDelta.setFlags(IResourceDelta.MOVED_TO);
210                 sourceDelta.setMovedToPath(destinationPrefix.append(fromPath.removeFirstSegments(sourcePrefix.segmentCount())));
211             }
212         }
213         // Next, create the delta for the destination
214
if (destinationDelta.getKind() == IResourceDelta.REMOVED) {
215             // The destination was removed and is being re-added
216
destinationDelta.setKind(IResourceDelta.CHANGED);
217             destinationDelta.addFlags(IResourceDelta.REPLACED);
218         } else {
219             destinationDelta.setKind(IResourceDelta.ADDED);
220         }
221         if (!wasAdded || !fromPath.equals(resource.getFullPath())) {
222             // The source wasn't added so it is a move/copy
223
destinationDelta.addFlags(move ? IResourceDelta.MOVED_FROM : IResourceDelta.COPIED_FROM);
224             destinationDelta.setMovedFromPath(fromPath);
225             // Apply the source flags
226
if (move)
227                 destinationDelta.addFlags(sourceFlags);
228         }
229
230         return true;
231     }
232
233     /**
234      * Helper method that generate a move or copy delta for a sub-tree
235      * of resources being moved or copied.
236      */

237     private void moveOrCopyDeep(IResource resource, IPath destination, final boolean move) {
238         final IPath sourcePrefix = resource.getFullPath();
239         final IPath destinationPrefix = destination;
240         try {
241             //build delta for the entire sub-tree if available
242
if (resource.isAccessible()) {
243                 resource.accept(new IResourceVisitor() {
244                     public boolean visit(IResource child) {
245                         return moveOrCopy(child, sourcePrefix, destinationPrefix, move);
246                     }
247                 });
248             } else {
249                 //just build a delta for the single resource
250
moveOrCopy(resource, sourcePrefix, destination, move);
251             }
252         } catch (CoreException e) {
253             fail(e);
254         }
255     }
256 }
257
Popular Tags