fix NPE when no annotation workers present ...
[jalview.git] / src / jalview / workers / AlignCalcManager.java
1 package jalview.workers;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.Hashtable;
6 import java.util.List;
7 import java.util.Map;
8
9 import jalview.api.AlignCalcManagerI;
10 import jalview.api.AlignCalcWorkerI;
11 import jalview.datamodel.AlignmentAnnotation;
12
13 public class AlignCalcManager implements AlignCalcManagerI
14 {
15   private volatile List<AlignCalcWorkerI> restartable = new ArrayList<AlignCalcWorkerI>();
16
17   private List<Class> blackList = new ArrayList<Class>();
18
19   /**
20    * global record of calculations in progress
21    */
22   private static Hashtable<Class, AlignCalcWorkerI> inProgress = new Hashtable<Class, AlignCalcWorkerI>();
23
24   /**
25    * record of calculations pending or in progress in the current context
26    */
27   private Map<Class, List<AlignCalcWorkerI>> updating = new Hashtable<Class, List<AlignCalcWorkerI>>();
28
29   @Override
30   public void notifyStart(AlignCalcWorkerI worker)
31   {
32     List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
33     if (upd == null)
34     {
35       updating.put(worker.getClass(),
36               upd = new ArrayList<AlignCalcWorkerI>());
37     }
38     upd.add(worker);
39   }
40
41   @Override
42   public synchronized boolean alreadyDoing(AlignCalcWorkerI worker)
43   {
44     return inProgress.containsKey(worker.getClass());
45   }
46
47   @Override
48   public synchronized boolean notifyWorking(AlignCalcWorkerI worker)
49   {
50     // synchronized (inProgress)
51     {
52       // TODO: decide if we should throw exceptions here if multiple workers
53       // start to work
54       if (inProgress.get(worker.getClass()) != null)
55       {
56         if (false)
57         {
58           System.err
59                   .println("Warning: Multiple workers are running of type "
60                           + worker.getClass());
61         }
62         return false;
63       }
64       inProgress.put(worker.getClass(), worker);
65     }
66     return true;
67   }
68
69   private HashSet<AlignCalcWorkerI> canUpdate=new HashSet<AlignCalcWorkerI>();
70   @Override
71   public synchronized void workerComplete(AlignCalcWorkerI worker)
72   {
73     inProgress.remove(worker.getClass());
74     List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
75     if (upd != null)
76     {
77       upd.remove(worker);
78       canUpdate.add(worker);
79     }
80
81   }
82
83   @Override
84   public void workerCannotRun(AlignCalcWorkerI worker)
85   {
86     blackList.add(worker.getClass());
87   }
88
89   public boolean isBlackListed(Class workerType)
90   {
91     return blackList.contains(workerType);
92   }
93
94   @Override
95   public void startWorker(AlignCalcWorkerI worker)
96   {
97     new Thread(worker).start();
98   }
99
100   @Override
101   public synchronized boolean isWorking(AlignCalcWorkerI worker)
102   {
103     // System.err.println("isWorking : worker "+(worker!=null ?
104     // worker.getClass():"null")+ " "+hashCode());
105     return worker != null && inProgress.get(worker.getClass()) == worker;
106   }
107
108   @Override
109   public boolean isWorking()
110   {
111     // System.err.println("isWorking "+hashCode());
112     return inProgress.size() > 0;
113   }
114
115   @Override
116   public void registerWorker(AlignCalcWorkerI worker)
117   {
118     if (!restartable.contains(worker))
119     {
120       restartable.add(worker);
121     }
122     startWorker(worker);
123   }
124
125   @Override
126   public void restartWorkers()
127   {
128     for (AlignCalcWorkerI worker : restartable)
129     {
130       startWorker(worker);
131     }
132   }
133
134   @Override
135   public boolean workingInvolvedWith(AlignmentAnnotation alignmentAnnotation)
136   {
137     if (isWorking())
138     {
139       for (List<AlignCalcWorkerI> workers: updating.values())
140       {
141         for (AlignCalcWorkerI worker:workers)
142         if (worker.involves(alignmentAnnotation))
143         {
144           return true;
145         }
146       }
147     }
148     return false;
149   }
150
151   @Override
152   public void updateAnnotationFor(Class workerClass)
153   {
154     for (AlignCalcWorkerI worker:canUpdate.toArray(new AlignCalcWorkerI[0]))
155     {
156       if (workerClass.equals(worker.getClass()))
157       {
158         worker.updateAnnotation();
159       }
160     }
161   }
162
163   @Override
164   public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
165           Class workerClass)
166   {
167     List<AlignCalcWorkerI> workingClass=new ArrayList<AlignCalcWorkerI>();
168     for (AlignCalcWorkerI worker:canUpdate.toArray(new AlignCalcWorkerI[0]))
169     {
170       if (workerClass.equals(worker.getClass()))
171       {
172         workingClass.add(worker);
173       }
174     }
175     return (workingClass.size()==0) ? null : workingClass;
176   }
177
178   @Override
179   public boolean startRegisteredWorkersOfClass(Class workerClass)
180   {
181           List<AlignCalcWorkerI> workers=getRegisteredWorkersOfClass(workerClass);
182           if (workers==null)
183           {
184                   return false;
185           }
186           for (AlignCalcWorkerI worker: workers) {
187                   startWorker(worker);
188           }
189           return true;
190   }
191
192   @Override
193   public void workerMayRun(AlignCalcWorkerI worker)
194   {
195     if (blackList.contains(worker.getClass()))
196     {
197       blackList.remove(worker.getClass());
198     }
199   }
200 }