Formatting
[jalview.git] / src / org / biojava / dasobert / das / FeatureThread.java
1 /*
2  *                    BioJava development code
3  *
4  * This code may be freely distributed and modified under the
5  * terms of the GNU Lesser General Public Licence.  This should
6  * be distributed with the code.  If you do not have a copy,
7  * see:
8  *
9  *      http://www.gnu.org/copyleft/lesser.html
10  *
11  * Copyright for this code is held jointly by the individual
12  * authors.  These should be listed in @author doc comments.
13  *
14  * For more information on the BioJava project and its aims,
15  * or to join the biojava-l mailing list, visit the home page
16  * at:
17  *
18  *      http://www.biojava.org/
19  *
20  * Created on 21.09.2004
21  * @author Andreas Prlic
22  *
23  */
24
25 package org.biojava.dasobert.das;
26
27 import java.net.*;
28 import java.util.*;
29 import java.util.logging.*;
30
31 import org.biojava.dasobert.dasregistry.*;
32 import org.biojava.dasobert.eventmodel.*;
33
34 /** a thread that connects to a DAS - Feature service and gets the features
35  *
36  * @author Andreas Prlic
37  */
38
39
40
41 public class FeatureThread
42     implements Runnable
43 {
44
45   /** number of times the client tries to reconnect to the server if a "come back later" is returned.
46    * the server should provide a reasonable estimation how long it will take him to create results.
47    * if this number of requests is still not successfull, give up.
48    */
49   public static int MAX_COME_BACK_ITERATIONS = 5;
50
51   public static int MAX_NR_FEATURES = 300;
52
53   static Logger logger = Logger.getLogger("org.biojava.spice");
54
55   Das1Source dasSource;
56   String ac;
57   List featureListeners;
58   Thread thread;
59
60   public FeatureThread(String accessionCode, Das1Source dasSource)
61   {
62     this.dasSource = dasSource;
63     this.ac = accessionCode;
64     featureListeners = new ArrayList();
65   }
66
67   public void addFeatureListener(FeatureListener li)
68   {
69     featureListeners.add(li);
70   }
71
72   public void clearFeatureListeners()
73   {
74     featureListeners.clear();
75   }
76
77   public synchronized void stop()
78   {
79     thread = null;
80     notify();
81   }
82
83   public void run()
84   {
85     Thread me = Thread.currentThread();
86     while (thread == me)
87     {
88       String url = dasSource.getUrl();
89       String queryString = url + "features?segment=" + ac;
90       URL cmd = null;
91       try
92       {
93         cmd = new URL(queryString);
94       }
95       catch (MalformedURLException e)
96       {
97         logger.warning("got MalformedURL from das source " + dasSource);
98         e.printStackTrace();
99
100       }
101
102       logger.info("requesting features from " + cmd);
103       DAS_FeatureRetrieve ftmp = new DAS_FeatureRetrieve(cmd);
104
105       int comeBackLater = ftmp.getComeBackLater();
106       int securityCounter = 0;
107       while ( (thread == me) && (comeBackLater > 0))
108       {
109         securityCounter++;
110         if (securityCounter >= MAX_COME_BACK_ITERATIONS)
111         {
112           comeBackLater = -1;
113           break;
114
115         }
116         notifyComeBackLater(comeBackLater);
117         // server is still calculating - asks us to come back later
118         try
119         {
120           wait(comeBackLater);
121         }
122         catch (InterruptedException e)
123         {
124           comeBackLater = -1;
125           break;
126         }
127
128         ftmp.reload();
129         comeBackLater = ftmp.getComeBackLater();
130       }
131
132       if (! (thread == me))
133       {
134         break;
135       }
136
137       List features = ftmp.get_features();
138
139       // a fallback mechanism to prevent DAS sources from bringing down spice
140       if (features.size() > MAX_NR_FEATURES)
141       {
142         logger.warning("DAS source returned more than " + MAX_NR_FEATURES +
143                        "features. " +
144                        " throwing away excess features at " + cmd);
145         features = features.subList(0, MAX_NR_FEATURES);
146       }
147
148       // notify FeatureListeners
149       Map[] feats = (Map[]) features.toArray(new Map[features.size()]);
150       notifyFeatureListeners(feats);
151
152       break;
153
154     }
155     thread = null;
156
157   }
158
159   public void start()
160   {
161     thread = new Thread(this);
162     thread.start();
163   }
164
165   private void notifyFeatureListeners(Map[] feats)
166   {
167     logger.finest("FeatureThread found " + feats.length + " features");
168     FeatureEvent fevent = new FeatureEvent(feats, dasSource);
169     Iterator fiter = featureListeners.iterator();
170     while (fiter.hasNext())
171     {
172       FeatureListener fi = (FeatureListener) fiter.next();
173       fi.newFeatures(fevent);
174     }
175   }
176
177   /** the Annotation server requested to be queried again in a while
178    *
179    * @param comeBackLater
180    */
181   private void notifyComeBackLater(int comeBackLater)
182   {
183     FeatureEvent event = new FeatureEvent(new HashMap[0], dasSource);
184     event.setComeBackLater(comeBackLater);
185     Iterator fiter = featureListeners.iterator();
186     while (fiter.hasNext())
187     {
188       FeatureListener fi = (FeatureListener) fiter.next();
189       fi.comeBackLater(event);
190     }
191
192   }
193
194 }