JAL-1645 Version-Rel Version 2.9 Year-Rel 2015 Licensing glob
[jalview.git] / src / jalview / ext / rbvi / chimera / ChimeraListener.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9)
3  * Copyright (C) 2015 The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.ext.rbvi.chimera;
22
23 import jalview.httpserver.AbstractRequestHandler;
24 import jalview.structure.SelectionSource;
25
26 import java.net.BindException;
27
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 /**
32  * This is a simple Http handler that can listen for selections in Chimera.
33  * <p/>
34  * Lifecycle:
35  * <ul>
36  * <li>Start the Chimera process</li>
37  * <li>Start the REST service on Chimera, get the port number it is listening on
38  * </li>
39  * <li>Start the ChimeraListener, get the URL it is listening on</li>
40  * <li>The first listener started will start the singleton HttpServer</li>
41  * <li>Send a 'listen' command to Chimera with the URL of the listener</li>
42  * <li>When Jalview's Chimera window is closed, shut down the ChimeraListener</li>
43  * <li>Multiple linked Chimera instances will each have a separate listener (but
44  * share one Http server)</li>
45  * </ul>
46  * 
47  * @author gmcarstairs
48  *
49  */
50 public class ChimeraListener extends AbstractRequestHandler implements
51         SelectionSource
52 {
53   /*
54    * Chimera notification parameter name
55    */
56   private static final String CHIMERA_NOTIFICATION = "chimeraNotification";
57
58   /*
59    * Chimera model changed notifications start with this
60    */
61   private static final String MODEL_CHANGED = "ModelChanged: ";
62
63   /*
64    * Chimera selection changed notification message
65    */
66   private static final String SELECTION_CHANGED = "SelectionChanged: selection changed\n";
67
68   /*
69    * A static counter so each listener can be associated with a distinct context
70    * root (/chimera0,1,2,3...). This is needed so we can fetch selections from
71    * multiple Chimera instances without confusion.
72    */
73   private static int chimeraId = 0;
74
75   /*
76    * Prefix for path below context root (myChimeraId is appended)
77    */
78   private static final String PATH_PREFIX = "chimera";
79
80   /*
81    * Value of chimeraId (0, 1, 2...) for this instance
82    */
83   private int myChimeraId = 0;
84
85   /*
86    * A reference to the object by which we can talk to Chimera
87    */
88   private JalviewChimeraBinding chimeraBinding;
89
90   /**
91    * Constructor that registers this as an Http request handler on path
92    * /chimeraN, where N is incremented for each instance. Call getUri to get the
93    * resulting URI for this handler.
94    * 
95    * @param chimeraBinding
96    * @throws BindException
97    *           if no free port can be assigned
98    */
99   public ChimeraListener(JalviewChimeraBinding binding)
100           throws BindException
101   {
102     myChimeraId = chimeraId++;
103     this.chimeraBinding = binding;
104     setPath(PATH_PREFIX + myChimeraId);
105     registerHandler();
106   }
107
108   /**
109    * Process a message from Chimera
110    */
111   @Override
112   protected void processRequest(HttpServletRequest request,
113           HttpServletResponse response)
114   {
115     // dumpRequest(request);
116     String message = request.getParameter(CHIMERA_NOTIFICATION);
117     if (SELECTION_CHANGED.equals(message))
118     {
119       this.chimeraBinding.highlightChimeraSelection();
120     }
121     else if (message != null && message.startsWith(MODEL_CHANGED))
122     {
123       processModelChanged(message.substring(MODEL_CHANGED.length()));
124     }
125     else
126     {
127       System.err.println("Unexpected chimeraNotification: " + message);
128     }
129   }
130
131   /**
132    * Handler a ModelChanged notification from Chimera
133    * 
134    * @param substring
135    */
136   protected void processModelChanged(String message)
137   {
138     // System.out.println(message + " (not implemented in Jalview)");
139   }
140
141   /**
142    * Returns a display name for this service
143    */
144   @Override
145   public String getName()
146   {
147     return "ChimeraListener";
148   }
149 }