Das client files
[jalview.git] / src / org / biojava / dasobert / das / FeatureThread.java
diff --git a/src/org/biojava/dasobert/das/FeatureThread.java b/src/org/biojava/dasobert/das/FeatureThread.java
new file mode 100755 (executable)
index 0000000..7435cdb
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *                    BioJava development code
+ *
+ * This code may be freely distributed and modified under the
+ * terms of the GNU Lesser General Public Licence.  This should
+ * be distributed with the code.  If you do not have a copy,
+ * see:
+ *
+ *      http://www.gnu.org/copyleft/lesser.html
+ *
+ * Copyright for this code is held jointly by the individual
+ * authors.  These should be listed in @author doc comments.
+ *
+ * For more information on the BioJava project and its aims,
+ * or to join the biojava-l mailing list, visit the home page
+ * at:
+ *
+ *      http://www.biojava.org/
+ *
+ * Created on 21.09.2004
+ * @author Andreas Prlic
+ *
+ */
+
+package org.biojava.dasobert.das ;
+
+import java.util.*;
+import java.net.*;
+import java.util.logging.* ;
+import org.biojava.dasobert.eventmodel.FeatureListener;
+import org.biojava.dasobert.eventmodel.FeatureEvent;
+import org.biojava.dasobert.dasregistry.Das1Source;
+
+/** a thread that connects to a DAS - Feature service and gets the features
+ *
+ * @author Andreas Prlic
+ */
+
+
+
+public class FeatureThread
+    implements Runnable
+{
+
+    /** number of times the client tries to reconnect to the server if a "come back later" is returned.
+     * the server should provide a reasonable estimation how long it will take him to create results.
+     * if this number of requests is still not successfull, give up.
+     */
+    public static int MAX_COME_BACK_ITERATIONS = 5;
+
+    public static int MAX_NR_FEATURES = 300;
+
+    static Logger logger = Logger.getLogger("org.biojava.spice");
+
+    Das1Source dasSource;
+    String ac ;
+    List featureListeners;
+    Thread thread;
+
+    public FeatureThread (String accessionCode, Das1Source dasSource) {
+       this.dasSource = dasSource;
+       this.ac = accessionCode;
+       featureListeners = new ArrayList();
+    }
+
+    public void addFeatureListener(FeatureListener li) {
+       featureListeners.add(li);
+    }
+
+    public void clearFeatureListeners() {
+       featureListeners.clear();
+    }
+
+    public synchronized void stop(){
+       thread = null;
+       notify();
+    }
+
+
+
+
+    public void run() {
+       Thread me = Thread.currentThread();
+       while ( thread == me) {
+           String url = dasSource.getUrl();
+           String queryString = url + "features?segment="+ ac ;
+           URL cmd = null ;
+           try {
+               cmd = new URL(queryString);
+           } catch (MalformedURLException e ) {
+               logger.warning("got MalformedURL from das source " +dasSource);
+               e.printStackTrace();
+           }
+
+           logger.info("requesting features from " + cmd);
+           DAS_FeatureRetrieve ftmp = new DAS_FeatureRetrieve(cmd);
+
+
+           int comeBackLater = ftmp.getComeBackLater();
+           int securityCounter = 0;
+           while ( (thread == me) && ( comeBackLater > 0 )) {
+               securityCounter++;
+               if ( securityCounter >= MAX_COME_BACK_ITERATIONS){
+                   comeBackLater = -1;
+                   break;
+
+               }
+               notifyComeBackLater(comeBackLater);
+               // server is still calculating - asks us to come back later
+               try {
+                   wait (comeBackLater);
+               } catch (InterruptedException e){
+                   comeBackLater = -1;
+                   break;
+               }
+
+               ftmp.reload();
+               comeBackLater = ftmp.getComeBackLater();
+           }
+
+           if ( ! (thread == me ) ) {
+               break;
+           }
+
+           List features = ftmp.get_features();
+
+           // a fallback mechanism to prevent DAS sources from bringing down spice
+           if ( features.size() > MAX_NR_FEATURES){
+               logger.warning("DAS source returned more than " + MAX_NR_FEATURES + "features. " +
+                              " throwing away excess features at " +cmd);
+               features = features.subList(0,MAX_NR_FEATURES);
+           }
+
+
+           // notify FeatureListeners
+           Map[] feats = (Map[])features.toArray(new Map[features.size()]);
+           notifyFeatureListeners(feats);
+
+           break;
+
+
+       }
+       thread = null;
+
+    }
+
+    public void start() {
+       thread = new Thread(this);
+       thread.start();
+    }
+
+    private void notifyFeatureListeners(Map[] feats){
+        logger.finest("FeatureThread found " + feats.length + " features");
+        FeatureEvent fevent = new FeatureEvent(feats,dasSource);
+        Iterator fiter = featureListeners.iterator();
+        while (fiter.hasNext()){
+            FeatureListener fi = (FeatureListener)fiter.next();
+            fi.newFeatures(fevent);
+        }
+    }
+
+ /** the Annotation server requested to be queried again in a while
+     *
+     * @param comeBackLater
+     */
+    private void notifyComeBackLater(int comeBackLater){
+        FeatureEvent event = new FeatureEvent(new HashMap[0],dasSource);
+        event.setComeBackLater(comeBackLater);
+        Iterator fiter = featureListeners.iterator();
+        while (fiter.hasNext()){
+            FeatureListener fi = (FeatureListener)fiter.next();
+            fi.comeBackLater(event);
+        }
+
+    }
+
+
+}
+