]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/issues/SCLIssuesContentProvider.java
7a5daffdbee0716670932e1358a3f227cf2f8dc4
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / issues / SCLIssuesContentProvider.java
1 package org.simantics.scl.ui.issues;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.concurrent.atomic.AtomicBoolean;
7
8 import org.eclipse.jface.viewers.IStructuredContentProvider;
9 import org.eclipse.jface.viewers.Viewer;
10 import org.eclipse.swt.widgets.Control;
11 import org.simantics.scl.compiler.errors.CompilationError;
12 import org.simantics.scl.compiler.errors.Failable;
13 import org.simantics.scl.compiler.errors.Failure;
14 import org.simantics.scl.compiler.module.Module;
15 import org.simantics.scl.compiler.module.repository.ModuleRepository;
16 import org.simantics.scl.compiler.module.repository.UpdateListener;
17
18 import gnu.trove.map.hash.THashMap;
19 import gnu.trove.procedure.TObjectObjectProcedure;
20 import gnu.trove.procedure.TObjectProcedure;
21
22 public class SCLIssuesContentProvider implements IStructuredContentProvider {
23
24     public static final int MAX_ISSUE_COUNT = 1000;
25     
26     Viewer viewer;
27     ModuleRepository repository;
28     boolean disposed = false;
29     AtomicBoolean refreshInProgress = new AtomicBoolean(false);
30     
31     THashMap<String, Failure> currentFailures = new THashMap<String, Failure>();
32     THashMap<String, UpdateListener> updateListeners = new THashMap<String, UpdateListener>(); 
33     
34     @Override
35     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
36         this.viewer = viewer;
37         this.repository = (ModuleRepository)newInput;
38         if(newInput != null)
39             listenIssues();
40     }
41     
42     private UpdateListener getUpdateListener(String moduleName) {
43         UpdateListener listener;
44         synchronized(updateListeners) {
45             listener = updateListeners.get(moduleName);
46             if(listener == null) {
47                 listener = new UpdateListener() {
48                     @Override
49                     public void notifyAboutUpdate() {
50                         if(!disposed)
51                             listenModule(moduleName);
52                     }
53                 };
54                 updateListeners.put(moduleName, listener);
55             }
56         }
57         return listener;
58     }
59     
60     private void listenModule(String moduleName) {
61         if(repository == null)
62             return;
63         Failable<Module> result = repository.getModule(moduleName, getUpdateListener(moduleName));
64         synchronized(currentFailures) {
65             if(result instanceof Failure) {
66                 Failure failure = (Failure)result;
67                 currentFailures.put(moduleName, failure);
68             }
69             else
70                 if(currentFailures.remove(moduleName) == null)
71                     return;
72         }
73         refresh();
74     }
75     
76     private void refresh() {
77         if(!refreshInProgress.compareAndSet(false, true))
78             return;
79         if(viewer == null)
80             return;
81         Control control = viewer.getControl();
82         if(control.isDisposed() || disposed)
83             return;
84         control.getDisplay().asyncExec(new Runnable() {
85             @Override
86             public void run() {
87                 if(control.isDisposed() || disposed)
88                     return;
89                 refreshInProgress.set(false);
90                 viewer.refresh();
91             }
92         });
93     }
94
95     private void listenIssues() {
96         new Thread() {
97             public void run() {
98                 if(repository == null)
99                     return;
100                 repository.getSourceRepository().forAllModules(new TObjectProcedure<String>() {
101                     @Override
102                     public boolean execute(String moduleName) {
103                         listenModule(moduleName);
104                         return true;
105                     }
106                 });
107             }
108         }.start();
109     }
110
111     @Override
112     public void dispose() {
113         if(this.disposed)
114             return;
115         this.disposed = true;
116         if(repository != null)
117             synchronized(updateListeners) {
118                 updateListeners.forEachEntry(new TObjectObjectProcedure<String, UpdateListener>() {
119                     @Override
120                     public boolean execute(String moduleName, UpdateListener listener) {
121                         listener.stopListening();
122                         return true;
123                     }
124                 });
125                 updateListeners.clear();
126             }
127     }
128
129     @Override
130     public Object[] getElements(Object inputElement) {
131         ArrayList<SCLIssuesTableEntry> result = new ArrayList<SCLIssuesTableEntry>();
132         synchronized(currentFailures) {
133             String[] moduleNames = currentFailures.keySet().toArray(new String[currentFailures.size()]);
134             Arrays.sort(moduleNames);
135             for(String moduleName : moduleNames) {
136                 Failure failure = currentFailures.get(moduleName);
137                 for(CompilationError error : failure.errors)
138                     result.add(new SCLIssuesTableEntry(moduleName, error));
139                 if(result.size() >= MAX_ISSUE_COUNT)
140                     break;
141             }
142         }
143         Collections.sort(result);
144         return result.toArray();
145     }
146
147 }