KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > core > subscribers > SubscriberResourceCollector


1 /*******************************************************************************
2  * Copyright (c) 2000, 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.team.internal.core.subscribers;
12
13 import org.eclipse.core.resources.*;
14 import org.eclipse.core.runtime.Assert;
15 import org.eclipse.team.core.subscribers.*;
16
17 /**
18  * This class acts as a superclass for any class that is collecting subscriber
19  * resources. It provides functionality that listens to resource deltas and
20  * subscriber change events in order to determine when the state of resources
21  * that are supervised by a subscriber may have changed.
22  */

23 public abstract class SubscriberResourceCollector implements IResourceChangeListener, ISubscriberChangeListener {
24     
25     Subscriber subscriber;
26     
27     /**
28      * Create the collector and register it as a listener with the workspace
29      * and the subscriber.
30      */

31     public SubscriberResourceCollector(Subscriber subscriber) {
32         Assert.isNotNull(subscriber);
33         this.subscriber = subscriber;
34         ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
35         subscriber.addListener(this);
36     }
37     
38     /**
39      * Returns the <code>Subscriber</code> associated with this collector.
40      *
41      * @return the <code>Subscriber</code> associated with this collector.
42      */

43     public Subscriber getSubscriber() {
44         return subscriber;
45     }
46     
47     /**
48      * De-register the listeners for this collector.
49      */

50     public void dispose() {
51         getSubscriber().removeListener(this);
52         ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
53     }
54     
55     /* (non-Javadoc)
56      * @see org.eclipse.team.core.sync.ITeamResourceChangeListener#teamResourceChanged(org.eclipse.team.core.sync.TeamDelta[])
57      */

58     public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) {
59         try {
60             beginInput();
61             IResource[] roots = getRoots();
62             for (int i = 0; i < deltas.length; i++) {
63                 switch (deltas[i].getFlags()) {
64                     case ISubscriberChangeEvent.SYNC_CHANGED :
65                         if (isAllRootsIncluded() || isDescendantOfRoot(deltas[i].getResource(), roots)) {
66                             change(deltas[i].getResource(), IResource.DEPTH_ZERO);
67                         }
68                         break;
69                     case ISubscriberChangeEvent.ROOT_REMOVED :
70                         remove(deltas[i].getResource());
71                         break;
72                     case ISubscriberChangeEvent.ROOT_ADDED :
73                         if (isAllRootsIncluded() || isDescendantOfRoot(deltas[i].getResource(), roots)) {
74                             change(deltas[i].getResource(), IResource.DEPTH_INFINITE);
75                         }
76                         break;
77                 }
78             }
79         } finally {
80             endInput();
81         }
82     }
83
84     /**
85      * This method is invoked at the beginning of a subscriber change event
86      * or resource delta event. The endInput method will be invoked at some point
87      * following this. There may be several invocations of remove or change
88      * in between.
89      */

90     protected void beginInput() {
91         // Do nothing by default
92
}
93     
94     /**
95      * The processing of the resource or subscriber delta has finished.
96      * Subclasses can accumulate removals and changes and handle them
97      * at this point to allow batched change events.
98      */

99     protected void endInput() {
100         // Do nothing by default
101
}
102     
103
104     /*(non-Javadoc)
105      * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
106      */

107     public void resourceChanged(IResourceChangeEvent event) {
108         try {
109             beginInput();
110             processDelta(event.getDelta(), getRoots());
111         } finally {
112             endInput();
113         }
114     }
115     
116     /**
117      * Process the resource delta and posts all necessary events to the background
118      * event handler.
119      *
120      * @param delta the resource delta to analyze
121      */

122     protected void processDelta(IResourceDelta delta, IResource[] roots) {
123         IResource resource = delta.getResource();
124         int kind = delta.getKind();
125
126         if (resource.getType() == IResource.PROJECT) {
127             // Handle projects that should be removed from the collector
128
if (((kind & IResourceDelta.REMOVED) != 0) /* deleted project */
129                     || (delta.getFlags() & IResourceDelta.OPEN) != 0 && !((IProject) resource).isOpen() /* closed project */
130                     || !isAncestorOfRoot(resource, roots)) /* not within subscriber roots */ {
131                 // If the project has any entries in the sync set, remove them
132
if (hasMembers(resource)) {
133                     remove(resource);
134                 }
135             }
136         }
137
138         boolean visitChildren = false;
139         if (isDescendantOfRoot(resource, roots)) {
140             visitChildren = true;
141             // If the resource has changed type, remove the old resource handle
142
// and add the new one
143
if ((delta.getFlags() & IResourceDelta.TYPE) != 0) {
144                 remove(resource);
145                 change(resource, IResource.DEPTH_INFINITE);
146             }
147     
148             // Check the flags for changes the SyncSet cares about.
149
// Notice we don't care about MARKERS currently.
150
int changeFlags = delta.getFlags();
151             if ((changeFlags & (IResourceDelta.OPEN | IResourceDelta.CONTENT)) != 0) {
152                 change(resource, IResource.DEPTH_ZERO);
153             }
154     
155             // Check the kind and deal with those we care about
156
if ((delta.getKind() & (IResourceDelta.REMOVED | IResourceDelta.ADDED)) != 0) {
157                 change(resource, IResource.DEPTH_ZERO);
158             }
159         }
160
161         // Handle changed children
162
if (visitChildren || isAncestorOfRoot(resource, roots)) {
163             IResourceDelta[] affectedChildren = delta.getAffectedChildren(IResourceDelta.CHANGED | IResourceDelta.REMOVED | IResourceDelta.ADDED);
164             for (int i = 0; i < affectedChildren.length; i++) {
165                 processDelta(affectedChildren[i], roots);
166             }
167         }
168     }
169     
170     /**
171      * Return the root resources that are to be considered by this handler.
172      * These may be either the subscriber roots or a set of resources that are
173      * contained by the subscriber's roots.
174      * @return the root resources that are to be considered by this handler
175      */

176     protected IResource[] getRoots() {
177         return getSubscriber().roots();
178     }
179
180     /**
181      * Return whether the given resource, which is not
182      * within the roots of this handler, has children
183      * that are.
184      * @param resource the resource
185      * @return whether the resource has children that are being considered
186      * by this handler.
187      */

188     protected abstract boolean hasMembers(IResource resource);
189     
190     /**
191      * The resource is no longer of concern to the subscriber.
192      * Remove the resource and any of it's descendants
193      * from the set of resources being collected.
194      * @param resource the resource to be removed along with its
195      * descendants.
196      */

197     protected abstract void remove(IResource resource);
198
199     /**
200      * The resource sync state has changed to the depth specified.
201      * @param resource the resource
202      * @param depth the depth
203      */

204     protected abstract void change(IResource resource, int depth);
205     
206     /**
207      * Return whether all roots of a subscriber are included or
208      * if the collector is only consider a subset of the resources.
209      * @return whether all roots of a subscriber are included
210      */

211     protected boolean isAllRootsIncluded() {
212         return true;
213     }
214
215     private boolean isAncestorOfRoot(IResource parent, IResource[] roots) {
216         // Always traverse into projects in case a root was removed
217
if (parent.getType() == IResource.ROOT) return true;
218         for (int i = 0; i < roots.length; i++) {
219             IResource resource = roots[i];
220             if (parent.getFullPath().isPrefixOf(resource.getFullPath())) {
221                 return true;
222             }
223         }
224         return false;
225     }
226
227     private boolean isDescendantOfRoot(IResource resource, IResource[] roots) {
228         for (int i = 0; i < roots.length; i++) {
229             IResource root = roots[i];
230             if (root.getFullPath().isPrefixOf(resource.getFullPath())) {
231                 return true;
232             }
233         }
234         return false;
235     }
236 }
237
Popular Tags