KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ui > synchronize > ActiveChangeSetCollector


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.ui.synchronize;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.IWorkspaceRunnable;
22 import org.eclipse.core.runtime.IPath;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.team.core.TeamException;
25 import org.eclipse.team.core.diff.*;
26 import org.eclipse.team.core.mapping.IResourceDiffTree;
27 import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
28 import org.eclipse.team.core.synchronize.*;
29 import org.eclipse.team.internal.core.subscribers.*;
30 import org.eclipse.team.internal.ui.TeamUIPlugin;
31 import org.eclipse.team.ui.synchronize.*;
32
33 /**
34  * Group incoming changes according to the active change set that are
35  * located in
36  */

37 public class ActiveChangeSetCollector implements IDiffChangeListener {
38
39     private final ISynchronizePageConfiguration configuration;
40     
41     /*
42      * Map active change sets to infos displayed by the participant
43      */

44     private final Map JavaDoc activeSets = new HashMap JavaDoc();
45     
46     /*
47      * Set which contains those changes that are not part of an active set
48      */

49     private SyncInfoTree rootSet = new SyncInfoTree();
50
51     private final ChangeSetModelProvider provider;
52
53     /*
54      * Listener registered with active change set manager
55      */

56     private IChangeSetChangeListener activeChangeSetListener = new IChangeSetChangeListener() {
57
58         public void setAdded(final ChangeSet set) {
59             // Remove any resources that are in the new set
60
provider.performUpdate(new IWorkspaceRunnable() {
61                 public void run(IProgressMonitor monitor) {
62                     remove(set.getResources());
63                     createSyncInfoSet(set);
64                 }
65             }, true, true);
66         }
67         
68         public void defaultSetChanged(final ChangeSet previousDefault, final ChangeSet set) {
69             provider.performUpdate(new IWorkspaceRunnable() {
70                 public void run(IProgressMonitor monitor) {
71                     if (listener != null)
72                         listener.defaultSetChanged(previousDefault, set);
73                 }
74             }, true, true);
75         }
76         
77         public void setRemoved(final ChangeSet set) {
78             provider.performUpdate(new IWorkspaceRunnable() {
79                 public void run(IProgressMonitor monitor) {
80                     remove(set);
81                     if (!set.isEmpty()) {
82                         add(getSyncInfos(set).getSyncInfos());
83                     }
84                 }
85             }, true, true);
86         }
87
88         public void nameChanged(final ChangeSet set) {
89             provider.performUpdate(new IWorkspaceRunnable() {
90                 public void run(IProgressMonitor monitor) {
91                     if (listener != null)
92                         listener.nameChanged(set);
93                 }
94             }, true, true);
95         }
96
97         public void resourcesChanged(final ChangeSet set, final IPath[] paths) {
98             // Look for any resources that were removed from the set but are still out-of sync.
99
// Re-add those resources
100
final List JavaDoc outOfSync = new ArrayList JavaDoc();
101             for (int i = 0; i < paths.length; i++) {
102                 IPath path = paths[i];
103                 if (!((DiffChangeSet)set).contains(path)) {
104                     SyncInfo info = getSyncInfo(path);
105                     if (info != null && info.getKind() != SyncInfo.IN_SYNC) {
106                         outOfSync.add(info);
107                     }
108                 }
109             }
110             if (!outOfSync.isEmpty()) {
111                 provider.performUpdate(new IWorkspaceRunnable() {
112                     public void run(IProgressMonitor monitor) {
113                         add((SyncInfo[]) outOfSync.toArray(new SyncInfo[outOfSync.size()]));
114                     }
115                 }, true, true);
116             }
117         }
118     };
119
120     /**
121      * Listener that wants to receive change events from this collector
122      */

123     private IChangeSetChangeListener listener;
124     
125     public ActiveChangeSetCollector(ISynchronizePageConfiguration configuration, ChangeSetModelProvider provider) {
126         this.configuration = configuration;
127         this.provider = provider;
128         getActiveChangeSetManager().addListener(activeChangeSetListener);
129     }
130
131     public ISynchronizePageConfiguration getConfiguration() {
132         return configuration;
133     }
134     
135     public ActiveChangeSetManager getActiveChangeSetManager() {
136         ISynchronizeParticipant participant = getConfiguration().getParticipant();
137         if (participant instanceof IChangeSetProvider) {
138             return ((IChangeSetProvider)participant).getChangeSetCapability().getActiveChangeSetManager();
139         }
140         return null;
141     }
142     
143     /**
144      * Re-populate the change sets from the seed set.
145      * If <code>null</code> is passed, the state
146      * of the collector is cleared but the set is not
147      * re-populated.
148      * <p>
149      * This method is invoked by the model provider when the
150      * model provider changes state. It should not
151      * be invoked by other clients. The model provider
152      * will invoke this method from a particular thread (which may
153      * or may not be the UI thread). Updates done to the collector
154      * from within this thread will be thread-safe and update the view
155      * properly. Updates done from other threads should use the
156      * <code>performUpdate</code> method to ensure the view is
157      * updated properly.
158      * @param seedSet
159      */

160     public void reset(SyncInfoSet seedSet) {
161         // First, clean up
162
rootSet.clear();
163         ChangeSet[] sets = (ChangeSet[]) activeSets.keySet().toArray(new ChangeSet[activeSets.size()]);
164         for (int i = 0; i < sets.length; i++) {
165             ChangeSet set = sets[i];
166             remove(set);
167         }
168         activeSets.clear();
169         
170         // Now re-populate
171
if (seedSet != null) {
172             if (getConfiguration().getComparisonType() == ISynchronizePageConfiguration.THREE_WAY) {
173                 // Show all active change sets even if they are empty
174
sets = getActiveChangeSetManager().getSets();
175                 for (int i = 0; i < sets.length; i++) {
176                     ChangeSet set = sets[i];
177                     add(set);
178                 }
179                 // The above will add all sync info that are contained in sets.
180
// We still need to add uncontained infos to the root set
181
SyncInfo[] syncInfos = seedSet.getSyncInfos();
182                 for (int i = 0; i < syncInfos.length; i++) {
183                     SyncInfo info = syncInfos[i];
184                     if (isLocalChange(info)) {
185                         ChangeSet[] containingSets = findChangeSets(info);
186                         if (containingSets.length == 0) {
187                             rootSet.add(info);
188                         }
189                     }
190                 }
191             } else {
192                 add(seedSet.getSyncInfos());
193             }
194         }
195     }
196     
197     /**
198      * Handle a sync info set change event from the provider's
199      * seed set.
200      * <p>
201      * This method is invoked by the model provider when the
202      * model provider changes state. It should not
203      * be invoked by other clients. The model provider
204      * will invoke this method from a particular thread (which may
205      * or may not be the UI thread). Updates done to the collector
206      * from within this thread will be thread-safe and update the view
207      * properly. Updates done from other threads should use the
208      * <code>performUpdate</code> method to ensure the view is
209      * updated properly.
210      */

211     public void handleChange(ISyncInfoSetChangeEvent event) {
212         List JavaDoc removals = new ArrayList JavaDoc();
213         List JavaDoc additions = new ArrayList JavaDoc();
214         removals.addAll(Arrays.asList(event.getRemovedResources()));
215         additions.addAll(Arrays.asList(event.getAddedResources()));
216         SyncInfo[] changed = event.getChangedResources();
217         for (int i = 0; i < changed.length; i++) {
218             SyncInfo info = changed[i];
219             additions.add(info);
220             removals.add(info.getLocal());
221         }
222         if (!removals.isEmpty()) {
223             remove((IResource[]) removals.toArray(new IResource[removals.size()]));
224         }
225         if (!additions.isEmpty()) {
226             add((SyncInfo[]) additions.toArray(new SyncInfo[additions.size()]));
227         }
228     }
229     
230     /**
231      * Remove the given resources from all sets of this collector.
232      * @param resources the resources to be removed
233      */

234     protected void remove(IResource[] resources) {
235         for (Iterator JavaDoc iter = activeSets.values().iterator(); iter.hasNext();) {
236             SyncInfoSet set = (SyncInfoSet) iter.next();
237             set.removeAll(resources);
238         }
239         rootSet.removeAll(resources);
240     }
241     
242     /* (non-Javadoc)
243      * @see org.eclipse.team.ui.synchronize.SyncInfoSetChangeSetCollector#add(org.eclipse.team.core.synchronize.SyncInfo[])
244      */

245     protected void add(SyncInfo[] infos) {
246         for (int i = 0; i < infos.length; i++) {
247             SyncInfo info = infos[i];
248             if (isLocalChange(info) && select(info)) {
249                 ChangeSet[] sets = findChangeSets(info);
250                 if (sets.length == 0) {
251                     rootSet.add(info);
252                 } else {
253                     for (int j = 0; j < sets.length; j++) {
254                         ChangeSet set = sets[j];
255                         SyncInfoSet targetSet = getSyncInfoSet(set);
256                         if (targetSet == null) {
257                             // This will add all the appropriate sync info to the set
258
createSyncInfoSet(set);
259                         } else {
260                             targetSet.add(info);
261                         }
262                     }
263                 }
264             }
265         }
266     }
267
268     private ChangeSet[] findChangeSets(SyncInfo info) {
269         ActiveChangeSetManager manager = getActiveChangeSetManager();
270         ChangeSet[] sets = manager.getSets();
271         List JavaDoc result = new ArrayList JavaDoc();
272         for (int i = 0; i < sets.length; i++) {
273             ChangeSet set = sets[i];
274             if (set.contains(info.getLocal())) {
275                 result.add(set);
276             }
277         }
278         return (ChangeSet[]) result.toArray(new ChangeSet[result.size()]);
279     }
280
281     /*
282      * Return if this sync info is an outgoing change.
283      */

284     private boolean isLocalChange(SyncInfo info) {
285         if (!info.getComparator().isThreeWay()) {
286             try {
287                 // Obtain the sync info from the subscriber and use it to see if the change is local
288
info = ((SubscriberChangeSetManager)getActiveChangeSetManager()).getSubscriber().getSyncInfo(info.getLocal());
289             } catch (TeamException e) {
290                 TeamUIPlugin.log(e);
291             }
292         }
293         return (info.getComparator().isThreeWay()
294                 && ((info.getKind() & SyncInfo.DIRECTION_MASK) == SyncInfo.OUTGOING ||
295                         (info.getKind() & SyncInfo.DIRECTION_MASK) == SyncInfo.CONFLICTING));
296     }
297     
298     public SyncInfoTree getRootSet() {
299         return rootSet;
300     }
301
302     /*
303      * Add the set from the collector.
304      */

305     public void add(ChangeSet set) {
306         SyncInfoSet targetSet = getSyncInfoSet(set);
307         if (targetSet == null) {
308             createSyncInfoSet(set);
309         }
310         if (listener != null) {
311             listener.setAdded(set);
312         }
313     }
314     
315     private SyncInfoTree createSyncInfoSet(ChangeSet set) {
316         SyncInfoTree sis = getSyncInfoSet(set);
317         // Register the listener last since the add will
318
// look for new elements
319
boolean added = false;
320         // Use a variable to ensure that both begin and end are invoked
321
try {
322             if (sis == null) {
323                 sis = new SyncInfoTree();
324                 activeSets.put(set, sis);
325                 added = true;
326             }
327             sis.beginInput();
328             if (!sis.isEmpty())
329                 sis.removeAll(sis.getResources());
330             sis.addAll(getSyncInfos(set));
331         } finally {
332             if (sis != null)
333                 sis.endInput(null);
334         }
335         if (added) {
336             ((DiffChangeSet)set).getDiffTree().addDiffChangeListener(this);
337             if (listener != null)
338                 listener.setAdded(set);
339         }
340         return sis;
341     }
342
343     private SyncInfoSet getSyncInfos(ChangeSet set) {
344         IDiff[] diffs = ((ResourceDiffTree)((DiffChangeSet)set).getDiffTree()).getDiffs();
345         return asSyncInfoSet(diffs);
346     }
347
348     private SyncInfoSet asSyncInfoSet(IDiff[] diffs) {
349         SyncInfoSet result = new SyncInfoSet();
350         for (int i = 0; i < diffs.length; i++) {
351             IDiff diff = diffs[i];
352             if (select(diff)) {
353                 SyncInfo info = asSyncInfo(diff);
354                 if (info != null)
355                     result.add(info);
356             }
357         }
358         return result;
359     }
360
361     private SyncInfo asSyncInfo(IDiff diff) {
362         try {
363             return ((SubscriberParticipant)getConfiguration().getParticipant()).getSubscriber().getSyncInfo(ResourceDiffTree.getResourceFor(diff));
364         } catch (TeamException e) {
365             TeamUIPlugin.log(e);
366         }
367         return null;
368     }
369
370     private boolean select(IDiff diff) {
371         return getSeedSet().getSyncInfo(ResourceDiffTree.getResourceFor(diff)) != null;
372     }
373     
374     /* private */ SyncInfo getSyncInfo(IPath path) {
375         return getSyncInfo(getSeedSet(), path);
376     }
377     
378     /* private */ IResource[] getResources(SyncInfoSet set, IPath[] paths) {
379         List JavaDoc result = new ArrayList JavaDoc();
380         for (int i = 0; i < paths.length; i++) {
381             IPath path = paths[i];
382             SyncInfo info = getSyncInfo(set, path);
383             if (info != null) {
384                 result.add(info.getLocal());
385             }
386         }
387         return (IResource[]) result.toArray(new IResource[result.size()]);
388     }
389
390     private SyncInfo getSyncInfo(SyncInfoSet set, IPath path) {
391         SyncInfo[] infos = set.getSyncInfos();
392         for (int i = 0; i < infos.length; i++) {
393             SyncInfo info = infos[i];
394             if (info.getLocal().getFullPath().equals(path))
395                 return info;
396         }
397         return null;
398     }
399
400     /*
401      * Remove the set from the collector.
402      */

403     public void remove(ChangeSet set) {
404         ((DiffChangeSet)set).getDiffTree().removeDiffChangeListener(this);
405         activeSets.remove(set);
406         if (listener != null) {
407             listener.setRemoved(set);
408         }
409     }
410
411     /*
412      * Return the sync info set for the given active change set
413      * or null if there isn't one.
414      */

415     public SyncInfoTree getSyncInfoSet(ChangeSet set) {
416         return (SyncInfoTree)activeSets.get(set);
417     }
418
419     private ChangeSet getChangeSet(IDiffTree tree) {
420         for (Iterator JavaDoc iter = activeSets.keySet().iterator(); iter.hasNext();) {
421             ChangeSet changeSet = (ChangeSet) iter.next();
422             if (((DiffChangeSet)changeSet).getDiffTree() == tree) {
423                 return changeSet;
424             }
425         }
426         return null;
427     }
428     
429     private boolean select(SyncInfo info) {
430         return getSeedSet().getSyncInfo(info.getLocal()) != null;
431     }
432     
433     private SyncInfoSet getSeedSet() {
434         return provider.getSyncInfoSet();
435     }
436
437     public void dispose() {
438         getActiveChangeSetManager().removeListener(activeChangeSetListener);
439     }
440     
441     /**
442      * Set the change set listener for this collector. There is
443      * only one for this type of collector.
444      * @param listener change set change listener
445      */

446     public void setChangeSetChangeListener(IChangeSetChangeListener listener) {
447         this.listener = listener;
448         if (listener == null) {
449             getActiveChangeSetManager().removeListener(activeChangeSetListener);
450         } else {
451             getActiveChangeSetManager().addListener(activeChangeSetListener);
452         }
453     }
454     
455     public void diffsChanged(final IDiffChangeEvent event, IProgressMonitor monitor) {
456         provider.performUpdate(new IWorkspaceRunnable() {
457             public void run(IProgressMonitor monitor) {
458                 ChangeSet changeSet = getChangeSet(event.getTree());
459                 if (changeSet != null) {
460                     SyncInfoSet targetSet = getSyncInfoSet(changeSet);
461                     if (targetSet != null) {
462                         targetSet.removeAll(getResources(targetSet, event.getRemovals()));
463                         targetSet.addAll(asSyncInfoSet(event.getAdditions()));
464                         targetSet.addAll(asSyncInfoSet(event.getChanges()));
465                         rootSet.removeAll(((IResourceDiffTree)event.getTree()).getAffectedResources());
466                     }
467                 }
468             }
469
470         }, true /* preserver expansion */, true /* run in UI thread */);
471     }
472
473     public void propertyChanged(IDiffTree tree, int property, IPath[] paths) {
474         // Nothing to do
475
}
476 }
477
Popular Tags