package jalview.ext.rbvi.chimera;
import java.net.BindException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jalview.httpserver.AbstractRequestHandler;
import jalview.httpserver.HttpServer;
import jalview.structure.SelectionSource;
/**
* This is a simple Http handler that can listen for selections in Chimera.
*
* Lifecycle:
*
* - Start the Chimera process
* - Start the REST service on Chimera, get the port number it is listening on
*
* - Start the ChimeraListener, get the URL it is listening on
* - The first listener started will start the singleton HttpServer
* - Send a 'listen' command to Chimera with the URL of the listener
* - When Jalview's Chimera window is closed, shut down the ChimeraListener
* - Multiple linked Chimera instances will each have a separate listener (but
* share one Http server)
*
*
* @author gmcarstairs
*
*/
public class ChimeraListener extends AbstractRequestHandler implements
SelectionSource
{
private static final String CHIMERA_NOTIFICATION = "chimeraNotification";
private static final String MODEL_CHANGED = "ModelChanged: ";
private static final String SELECTION_CHANGED = "SelectionChanged: selection changed\n";
/*
* A static counter so each listener can be associated with a distinct context
* root (/chimera0,1,2,3...). This is needed so we can fetch selections from
* multiple Chimera instances without confusion.
*/
private static int chimeraId = 0;
/*
* Path below context root that identifies this handler
*/
private static final String LISTENER_PATH = "chimera";
/*
* Value of chimeraId (0, 1, 2...) for this instance
*/
private int myChimeraId = 0;
/*
* A reference to the object by which we can talk to Chimera
*/
private JalviewChimeraBinding chimeraBinding;
/*
* The URI of this listener
*/
private String uri;
/**
* Constructor that also registers this as an Http request handler on path
* /chimeraN, where N is incremented for each instance. Call getUri to get the
* resulting URI for this handler.
*
* @param chimeraBinding
* @throws BindException
* if no free port can be assigned
*/
public ChimeraListener(JalviewChimeraBinding binding)
throws BindException
{
myChimeraId = chimeraId++;
this.chimeraBinding = binding;
final String path = LISTENER_PATH + myChimeraId;
this.uri = HttpServer.getInstance().registerHandler(path, this);
}
/**
* Returns the URI on which we are listening
*
* @return
*/
public String getUri()
{
return this.uri;
}
/**
* Process a message from Chimera
*/
@Override
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
{
// dumpRequest(request);
String message = request.getParameter(CHIMERA_NOTIFICATION);
if (SELECTION_CHANGED.equals(message))
{
this.chimeraBinding.highlightChimeraSelection();
}
else if (message != null && message.startsWith(MODEL_CHANGED))
{
processModelChanged(message.substring(MODEL_CHANGED.length()));
}
else
{
System.err.println("Unexpected chimeraNotification: " + message);
}
}
/**
* Handler a ModelChanged notification from Chimera
*
* @param substring
*/
protected void processModelChanged(String message)
{
System.out.println(message + " (not implemented in Jalview)");
}
/**
* Deregister this listener and close it down
*
* @throws Exception
*/
public void shutdown()
{
try
{
HttpServer.getInstance().removeHandler(this);
stop();
} catch (Exception e)
{
System.err.println("Error stopping chimera listener: "
+ e.getMessage());
}
}
}