Das client files
[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.util.*;
28 import java.net.*;
29 import java.util.logging.* ;
30 import org.biojava.dasobert.eventmodel.FeatureListener;
31 import org.biojava.dasobert.eventmodel.FeatureEvent;
32 import org.biojava.dasobert.dasregistry.Das1Source;
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         this.dasSource = dasSource;
62         this.ac = accessionCode;
63         featureListeners = new ArrayList();
64     }
65
66     public void addFeatureListener(FeatureListener li) {
67         featureListeners.add(li);
68     }
69
70     public void clearFeatureListeners() {
71         featureListeners.clear();
72     }
73
74     public synchronized void stop(){
75         thread = null;
76         notify();
77     }
78
79
80
81
82     public void run() {
83         Thread me = Thread.currentThread();
84         while ( thread == me) {
85             String url = dasSource.getUrl();
86             String queryString = url + "features?segment="+ ac ;
87             URL cmd = null ;
88             try {
89                 cmd = new URL(queryString);
90             } catch (MalformedURLException e ) {
91                 logger.warning("got MalformedURL from das source " +dasSource);
92                e.printStackTrace();
93             }
94
95             logger.info("requesting features from " + cmd);
96             DAS_FeatureRetrieve ftmp = new DAS_FeatureRetrieve(cmd);
97
98
99             int comeBackLater = ftmp.getComeBackLater();
100             int securityCounter = 0;
101             while ( (thread == me) && ( comeBackLater > 0 )) {
102                 securityCounter++;
103                 if ( securityCounter >= MAX_COME_BACK_ITERATIONS){
104                     comeBackLater = -1;
105                     break;
106
107                 }
108                 notifyComeBackLater(comeBackLater);
109                 // server is still calculating - asks us to come back later
110                 try {
111                     wait (comeBackLater);
112                 } catch (InterruptedException e){
113                     comeBackLater = -1;
114                     break;
115                 }
116
117                 ftmp.reload();
118                 comeBackLater = ftmp.getComeBackLater();
119             }
120
121             if ( ! (thread == me ) ) {
122                 break;
123             }
124
125             List features = ftmp.get_features();
126
127             // a fallback mechanism to prevent DAS sources from bringing down spice
128             if ( features.size() > MAX_NR_FEATURES){
129                 logger.warning("DAS source returned more than " + MAX_NR_FEATURES + "features. " +
130                                " throwing away excess features at " +cmd);
131                 features = features.subList(0,MAX_NR_FEATURES);
132             }
133
134
135             // notify FeatureListeners
136             Map[] feats = (Map[])features.toArray(new Map[features.size()]);
137             notifyFeatureListeners(feats);
138
139             break;
140
141
142         }
143         thread = null;
144
145     }
146
147     public void start() {
148         thread = new Thread(this);
149         thread.start();
150     }
151
152     private void notifyFeatureListeners(Map[] feats){
153         logger.finest("FeatureThread found " + feats.length + " features");
154         FeatureEvent fevent = new FeatureEvent(feats,dasSource);
155         Iterator fiter = featureListeners.iterator();
156         while (fiter.hasNext()){
157             FeatureListener fi = (FeatureListener)fiter.next();
158             fi.newFeatures(fevent);
159         }
160     }
161
162  /** the Annotation server requested to be queried again in a while
163      *
164      * @param comeBackLater
165      */
166     private void notifyComeBackLater(int comeBackLater){
167         FeatureEvent event = new FeatureEvent(new HashMap[0],dasSource);
168         event.setComeBackLater(comeBackLater);
169         Iterator fiter = featureListeners.iterator();
170         while (fiter.hasNext()){
171             FeatureListener fi = (FeatureListener)fiter.next();
172             fi.comeBackLater(event);
173         }
174
175     }
176
177
178 }
179