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.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
{
/*
* Chimera notification parameter name
*/
private static final String CHIMERA_NOTIFICATION = "chimeraNotification";
/*
* Chimera model changed notifications start with this
*/
private static final String MODEL_CHANGED = "ModelChanged: ";
/*
* Chimera selection changed notification message
*/
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;
/*
* Prefix for path below context root (myChimeraId is appended)
*/
private static final String PATH_PREFIX = "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;
/**
* Constructor that 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;
setPath(PATH_PREFIX + myChimeraId);
registerHandler();
}
/**
* 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)");
}
/**
* Returns a display name for this service
*/
@Override
public String getName()
{
return "ChimeraListener";
}
}