]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/viewsupport/ProblemMarkerManager.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / viewsupport / ProblemMarkerManager.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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.jdt.internal.ui.viewsupport;
12
13
14 import java.util.HashSet;
15 import java.util.Set;
16
17 import org.eclipse.swt.widgets.Display;
18
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.ListenerList;
23 import org.eclipse.core.runtime.Status;
24
25 import org.eclipse.core.resources.IMarker;
26 import org.eclipse.core.resources.IMarkerDelta;
27 import org.eclipse.core.resources.IProject;
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.resources.IResourceChangeEvent;
30 import org.eclipse.core.resources.IResourceChangeListener;
31 import org.eclipse.core.resources.IResourceDelta;
32 import org.eclipse.core.resources.IResourceDeltaVisitor;
33
34 import org.eclipse.jface.text.source.AnnotationModelEvent;
35 import org.eclipse.jface.text.source.IAnnotationModel;
36 import org.eclipse.jface.text.source.IAnnotationModelListener;
37 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
38
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.progress.UIJob;
41
42 import org.eclipse.jdt.internal.ui.JavaPlugin;
43 import org.eclipse.jdt.internal.ui.JavaUIMessages;
44 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitAnnotationModelEvent;
45
46 /**
47  * Listens to resource deltas and filters for marker changes of type IMarker.PROBLEM
48  * Viewers showing error ticks should register as listener to
49  * this type.
50  */
51 public class ProblemMarkerManager implements IResourceChangeListener, IAnnotationModelListener , IAnnotationModelListenerExtension {
52
53         /**
54          * Visitors used to look if the element change delta contains a marker change.
55          */
56         private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
57
58                 private HashSet<IResource> fChangedElements;
59
60                 public ProjectErrorVisitor(HashSet<IResource> changedElements) {
61                         fChangedElements= changedElements;
62                 }
63
64                 public boolean visit(IResourceDelta delta) throws CoreException {
65                         IResource res= delta.getResource();
66                         if (res instanceof IProject && delta.getKind() == IResourceDelta.CHANGED) {
67                                 IProject project= (IProject) res;
68                                 if (!project.isAccessible()) {
69                                         // only track open Java projects
70                                         return false;
71                                 }
72                         }
73                         checkInvalidate(delta, res);
74                         return true;
75                 }
76
77                 private void checkInvalidate(IResourceDelta delta, IResource resource) {
78                         int kind= delta.getKind();
79                         if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
80                                 // invalidate the resource and all parents
81                                 while (resource.getType() != IResource.ROOT && fChangedElements.add(resource)) {
82                                         resource= resource.getParent();
83                                 }
84                         }
85                 }
86
87                 private boolean isErrorDelta(IResourceDelta delta) {
88                         if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
89                                 IMarkerDelta[] markerDeltas= delta.getMarkerDeltas();
90                                 for (int i= 0; i < markerDeltas.length; i++) {
91                                         if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
92                                                 int kind= markerDeltas[i].getKind();
93                                                 if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED)
94                                                         return true;
95                                                 int severity= markerDeltas[i].getAttribute(IMarker.SEVERITY, -1);
96                                                 int newSeverity= markerDeltas[i].getMarker().getAttribute(IMarker.SEVERITY, -1);
97                                                 if (newSeverity != severity)
98                                                         return true;
99                                         }
100                                 }
101                         }
102                         return false;
103                 }
104         }
105
106         private ListenerList fListeners;
107
108         private Set<IResource> fResourcesWithMarkerChanges;
109         private Set<IResource> fResourcesWithAnnotationChanges;
110
111         private UIJob fNotifierJob;
112
113         public ProblemMarkerManager() {
114                 fListeners= new ListenerList();
115                 fResourcesWithMarkerChanges= new HashSet<IResource>();
116                 fResourcesWithAnnotationChanges= new HashSet<IResource>();
117         }
118
119         /*
120          * @see IResourceChangeListener#resourceChanged
121          */
122         public void resourceChanged(IResourceChangeEvent event) {
123                 HashSet<IResource> changedElements= new HashSet<IResource>();
124
125                 try {
126                         IResourceDelta delta= event.getDelta();
127                         if (delta != null)
128                                 delta.accept(new ProjectErrorVisitor(changedElements));
129                 } catch (CoreException e) {
130                         JavaPlugin.log(e.getStatus());
131                 }
132
133                 if (!changedElements.isEmpty()) {
134                         boolean hasChanges= false;
135                         synchronized (this) {
136                                 if (fResourcesWithMarkerChanges.isEmpty()) {
137                                         fResourcesWithMarkerChanges= changedElements;
138                                         hasChanges= true;
139                                 } else {
140                                         hasChanges= fResourcesWithMarkerChanges.addAll(changedElements);
141                                 }
142                         }
143                         if (hasChanges) {
144                                 fireChanges();
145                         }
146                 }
147         }
148
149         /* (non-Javadoc)
150          * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
151          */
152         public void modelChanged(IAnnotationModel model) {
153                 // no action
154         }
155
156         /* (non-Javadoc)
157          * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
158          */
159         public void modelChanged(AnnotationModelEvent event) {
160                 if (event instanceof CompilationUnitAnnotationModelEvent) {
161                         CompilationUnitAnnotationModelEvent cuEvent= (CompilationUnitAnnotationModelEvent) event;
162                         if (cuEvent.includesProblemMarkerAnnotationChanges()) {
163                                 boolean hasChanges= false;
164                                 synchronized (this) {
165                                         IResource changedResource= cuEvent.getUnderlyingResource();
166                                         hasChanges= fResourcesWithAnnotationChanges.add(changedResource);
167                                 }
168                                 if (hasChanges) {
169                                         fireChanges();
170                                 }
171                         }
172                 }
173         }
174
175
176         /**
177          * Adds a listener for problem marker changes.
178          * @param listener the listener to add
179          */
180         public void addListener(IProblemChangedListener listener) {
181                 if (fListeners.isEmpty()) {
182                         JavaPlugin.getWorkspace().addResourceChangeListener(this);
183                         JavaPlugin.getDefault().getCompilationUnitDocumentProvider().addGlobalAnnotationModelListener(this);
184                 }
185                 fListeners.add(listener);
186         }
187
188         /**
189          * Removes a <code>IProblemChangedListener</code>.
190          * @param listener the listener to remove
191          */
192         public void removeListener(IProblemChangedListener listener) {
193                 fListeners.remove(listener);
194                 if (fListeners.isEmpty()) {
195                         JavaPlugin.getWorkspace().removeResourceChangeListener(this);
196                         JavaPlugin.getDefault().getCompilationUnitDocumentProvider().removeGlobalAnnotationModelListener(this);
197                 }
198         }
199
200         private void fireChanges() {
201                 Display display= PlatformUI.getWorkbench().getDisplay();
202                 if (display != null && !display.isDisposed()) {
203                         postAsyncUpdate(display);
204                 }
205         }
206
207         private void postAsyncUpdate(final Display display) {
208                 if (fNotifierJob == null) {
209                         fNotifierJob= new UIJob(display, JavaUIMessages.ProblemMarkerManager_problem_marker_update_job_description) {
210                                 @Override
211                                 public IStatus runInUIThread(IProgressMonitor monitor) {
212                                         runPendingUpdates();
213                                         return Status.OK_STATUS;
214                                 }
215                         };
216                         fNotifierJob.setSystem(true);
217                 }
218                 fNotifierJob.schedule();
219         }
220
221         /**
222          * Notify all IProblemChangedListener. Must be called in the display thread.
223          */
224         private void runPendingUpdates() {
225                 IResource[] markerResources= null;
226                 IResource[] annotationResources= null;
227                 synchronized (this) {
228                         if (!fResourcesWithMarkerChanges.isEmpty()) {
229                                 markerResources= fResourcesWithMarkerChanges.toArray(new IResource[fResourcesWithMarkerChanges.size()]);
230                                 fResourcesWithMarkerChanges.clear();
231                         }
232                         if (!fResourcesWithAnnotationChanges.isEmpty()) {
233                                 annotationResources= fResourcesWithAnnotationChanges.toArray(new IResource[fResourcesWithAnnotationChanges.size()]);
234                                 fResourcesWithAnnotationChanges.clear();
235                         }
236                 }
237                 Object[] listeners= fListeners.getListeners();
238                 for (int i= 0; i < listeners.length; i++) {
239                         IProblemChangedListener curr= (IProblemChangedListener) listeners[i];
240                         if (markerResources != null) {
241                                 curr.problemsChanged(markerResources, true);
242                         }
243                         if (annotationResources != null) {
244                                 curr.problemsChanged(annotationResources, false);
245                         }
246                 }
247         }
248
249 }