KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > core > mapping > ChangeTracker


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.core.mapping;
12
13 import java.util.*;
14
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IAdaptable;
18 import org.eclipse.team.core.RepositoryProvider;
19 import org.eclipse.team.core.RepositoryProviderType;
20 import org.eclipse.team.internal.core.*;
21
22 /**
23  * Supports the tracking of related changes for the purpose of grouping then using an {@link IChangeGroupingRequestor}.
24  * <p>
25  * Clients may subclass this class.
26  * </p>
27  * @see IChangeGroupingRequestor
28  * @since 3.3
29  */

30 public abstract class ChangeTracker {
31
32     private Map trackedProjects = new HashMap(); // Map IProject->IChangeGroupingRequestor
33
private boolean disposed;
34     private ChangeListener changeListener = new ChangeListener();
35     
36     private class ChangeListener implements IResourceChangeListener, IRepositoryProviderListener {
37         /**
38          * Handle a resource change event.
39          * Update the set of projects for which we can track changes
40          * by listening for project changes and project description changes.
41          * @param event the change event
42          */

43         public void resourceChanged(IResourceChangeEvent event) {
44             if (disposed) return;
45             IResourceDelta delta = event.getDelta();
46             IResourceDelta[] projectDeltas = delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED);
47             for (int i = 0; i < projectDeltas.length; i++) {
48                 IResourceDelta projectDelta = projectDeltas[i];
49                 IResource resource = projectDelta.getResource();
50                 if (resource.getType() == IResource.PROJECT) {
51                     IProject project = (IProject)resource;
52                     if (isProjectOfInterest(project)) {
53                         if (isProjectTracked(project)) {
54                             IResource[] resources = getProjectChanges(project, projectDelta);
55                             if (resources.length > 0)
56                                 handleChanges(project, resources);
57                         } else {
58                             trackProject(project);
59                         }
60                     } else {
61                         stopTrackingProject(project);
62                     }
63                 }
64             }
65         }
66         
67         /**
68          * When a project is shared, start tracking it if it is of interest.
69          * @param provider the repository provider
70          */

71         public void providerMapped(RepositoryProvider provider) {
72             if (disposed) return;
73             if (isProjectOfInterest(provider.getProject())) {
74                 trackProject(provider.getProject());
75             }
76         }
77
78         /**
79          * When a project is no longer shared, stop tracking the project.
80          * @param project the project
81          */

82         public void providerUnmapped(IProject project) {
83             if (disposed) return;
84             stopTrackingProject(project);
85         }
86     }
87     
88     /**
89      * Create a change tracker
90      */

91     public ChangeTracker() {
92         super();
93     }
94
95     /**
96      * Start tracking changes. This registers listeners with the workspace
97      * and team.
98      */

99     public void start() {
100         ResourcesPlugin.getWorkspace().addResourceChangeListener(changeListener, IResourceChangeEvent.POST_CHANGE);
101         RepositoryProviderManager.getInstance().addListener(changeListener);
102         IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
103         for (int i = 0; i < allProjects.length; i++) {
104             IProject project = allProjects[i];
105             if (isProjectOfInterest(project))
106                 trackProject(project);
107         }
108     }
109
110     /**
111      * Remove any listeners for this tracker. Subclasses
112      * may extend this method but must call this method if they do.
113      */

114     public void dispose() {
115         disposed = true;
116         ResourcesPlugin.getWorkspace().removeResourceChangeListener(changeListener);
117         RepositoryProviderManager.getInstance().removeListener(changeListener);
118     }
119
120     private IResource[] getProjectChanges(IProject project, IResourceDelta projectDelta) {
121         final List result = new ArrayList();
122         try {
123             projectDelta.accept(new IResourceDeltaVisitor() {
124                 public boolean visit(IResourceDelta delta) throws CoreException {
125                     if (isResourceOfInterest(delta.getResource()) & isChangeOfInterest(delta)) {
126                         result.add(delta.getResource());
127                     }
128                     return true;
129                 }
130             });
131         } catch (CoreException e) {
132             TeamPlugin.log(e);
133         }
134         return (IResource[]) result.toArray(new IResource[result.size()]);
135     }
136
137     /**
138      * Return whether the given delta represents a change of interest.
139      * @param delta the delta
140      * @return whether the given delta represents a change of interest
141      */

142     protected boolean isChangeOfInterest(IResourceDelta delta) {
143         return (delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED)) > 0;
144     }
145
146     /**
147      * Stop tracking changes for the given project. Subclasses
148      * may extend but must call this method.
149      * @param project the project
150      */

151     protected void stopTrackingProject(IProject project) {
152         trackedProjects.remove(project);
153     }
154
155     /**
156      * Return whether the given project is being tracked.
157      * @param project the project
158      * @return whether the given project is being tracked
159      */

160     protected final boolean isProjectTracked(IProject project) {
161         return trackedProjects.containsKey(project);
162     }
163
164     /**
165      * Return whether the given project is of interest to this
166      * tracker. By default, <code>true</code> is returned if the
167      * project is accessible. Subclasses may extend but should
168      * still check for project accessibility either by calling
169      * {@link IResource#isAccessible()} or by invoking the
170      * overridden method.
171      * @param project the project
172      * @return whether the given project is of interest to this
173      * tracker
174      */

175     protected boolean isProjectOfInterest(IProject project) {
176         return project.isAccessible();
177     }
178
179     /**
180      * Return whether the given resource is of interest to the tracker.
181      * @param resource the resource
182      * @return whether the given resource is of interest to the tracker
183      */

184     protected abstract boolean isResourceOfInterest(IResource resource);
185
186     /**
187      * The given resources of interest have changed in the given project.
188      * @param project the project
189      * @param resources the resources
190      */

191     protected abstract void handleChanges(IProject project, IResource[] resources);
192
193     /**
194      * Resources of interest in the given project have changed but the
195      * specific changes are not known. Implementors must search the project for
196      * changes of interest.
197      * @param project the project
198      */

199     protected abstract void handleProjectChange(IProject project);
200
201     /**
202      * Track the given project if it has a change set collector. If the project
203      * does not have a collector, the project is not tracked.
204      * @param project the project
205      * @return whether the project is being tracked
206      */

207     protected final boolean trackProject(IProject project) {
208         if (RepositoryProvider.isShared(project)) {
209             try {
210                 String JavaDoc currentId = project.getPersistentProperty(TeamPlugin.PROVIDER_PROP_KEY);
211                 if (currentId != null) {
212                     RepositoryProviderType type = RepositoryProviderType.getProviderType(currentId);
213                     if (type != null) {
214                         IChangeGroupingRequestor collector = getCollector(type);
215                         if (collector != null) {
216                             trackedProjects.put(project, collector);
217                             // Ensure that an appropriate change set exists if needed
218
// We can do this here because we know that the number of files
219
// to test is small.
220
projectTracked(project);
221                             return true;
222                         }
223                     }
224                 }
225             } catch (CoreException e) {
226                 TeamPlugin.log(e);
227             }
228         }
229         return false;
230     }
231
232     private IChangeGroupingRequestor getCollector(RepositoryProviderType type) {
233         if (type instanceof IAdaptable) {
234             IAdaptable adaptable = (IAdaptable) type;
235             Object JavaDoc o = adaptable.getAdapter(IChangeGroupingRequestor.class);
236             if (o instanceof IChangeGroupingRequestor) {
237                 return (IChangeGroupingRequestor) o;
238             }
239         }
240         return null;
241     }
242
243     /**
244      * Callback made from {@link #trackProject(IProject)} when a project is tracked.
245      * By default, {@link #handleProjectChange(IProject)} is called by subclasses may override.
246      * @param project the project
247      */

248     protected void projectTracked(IProject project) {
249         handleProjectChange(project);
250     }
251     
252     /**
253      * Group the given modified file into a change set with the given name.
254      * @param project the project
255      * @param name the unique name used to identify the change set
256      * @param files the change files to be grouped
257      * @throws CoreException
258      */

259     protected void ensureGrouped(IProject project, String JavaDoc name, IFile[] files) throws CoreException {
260         IChangeGroupingRequestor collector = getCollector(project);
261         if (collector != null) {
262             collector.ensureChangesGrouped(project, files, name);
263         }
264     }
265
266     private IChangeGroupingRequestor getCollector(IProject project) {
267         return (IChangeGroupingRequestor)trackedProjects.get(project);
268     }
269     
270     /**
271      * Return whether the given file is modified with respect to the
272      * repository provider associated with the file's project.
273      * @param file the file
274      * @return whether the given file is modified
275      * @throws CoreException
276      */

277     protected boolean isModified(IFile file) throws CoreException {
278         IChangeGroupingRequestor collector = getCollector(file.getProject());
279         if (collector != null)
280             return collector.isModified(file);
281         return false;
282     }
283
284 }
285
Popular Tags