package uk.ac.vamsas.test; import uk.ac.vamsas.client.*; import uk.ac.vamsas.client.picking.IMessageHandler; import uk.ac.vamsas.client.picking.IPickManager; import uk.ac.vamsas.client.picking.Message; import uk.ac.vamsas.objects.core.VAMSAS; import uk.ac.vamsas.test.objects.Core; import java.awt.Event; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.Vector; /** * Toy vamsas command line client application demonstrating the API. * Currently runs with one argument: ExampleApplication.main(new String("watch")) * Test: Start up at least two of these processes independently and they will * successively modify and handle update events from the document model. * * Behaviour of each client: * Event handlers are registered for documentUpdate. * - every document update: * * the vamsas document will be dumped to standard out using uk.ac.vamsas.test.simpleclient.ArchiveReports * * if there are more than 4 vamsas roots, the first sequence in the first alignment of the first dataset of the second vamsas root will be appended with a single gap character and then written back to the session document. * A pick thread is started, which sends random CUSTOM pick events every so often (tuning: flooding the pick channel seems to affect the behaviour of other vamsasClient threads, suggesting some object lock contention). * A new vamsas root generated from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document. * Then a while loop waits around for events until shutdown: * - currently it will shutdown after 9 updates (totalUpdates) * - an update will be made after every other update that is detected. * * Status: PickManager now shuts down correctly. Serial updates for two instances work correctly and are detected under j1.4 (need to test in 1.5 and 1.6). * * TODO: test * appData get/set methods * * TODO: verify and test pickManager and interaction * between it and other session events * * TODO: add more session interaction events * * TODO: test client add/leave events - currently library generates exceptions for sessionlist and clientlist modifications. * * @author jimp */ public class ExampleApplication { private ClientHandle app; private UserHandle user; // TODO: make this something defined by the // api private IClientFactory clientfactory; private IClient vorbaclient; private byte[] mydata; private Vector vamsasObjects; private boolean isUpdated = false; private boolean isShuttingdown = false; private boolean isFinalizing = false; private int totalUpdates = 9; private void processVamsasDocument(IClientDocument doc) { if (doc.getVamsasRoots().length<4) { doc.addVamsasRoot(Core.getDemoVamsas()); } else { try { uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1].getDataSet(0); uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0); System.out.println("Modifying Sequence:\n"+alsq.hashCode()); alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar()); System.out.println("Modifying Sequence:\n"+alsq.hashCode()); System.out.println("Modified Sequence:\n"+alsq.getSequence()); doc.setVamsasRoots(doc.getVamsasRoots()); } catch (Exception ee) { } } vorbaclient.updateDocument(doc); // merge vamsasObjects with vamsas objects in document // get this apps 'mydata' if it hasn't got it already. // .. access this application's 'public' mydata' if there is any. } private void addHandlers(IClient avorbaclient) { // make a non-volatile reference to the client instance. final IClient vorbaclient = avorbaclient; // register update handler vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Vamsas document update for " + evt.getPropertyName() + ": " + evt.getOldValue() + " to " + evt.getNewValue()); // merge new data into ours. // example - output doc try { IClientDocument cdoc = vorbaclient.getClientDocument(); uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport( cdoc.getVamsasRoots(), true, System.out); // Simple update try { if (cdoc.getVamsasRoots().length>2) { uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1].getDataSet(0); uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0); if (alsq.isUpdated()) System.out.println("Seqeuence was updated since last time."); alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar()); System.out.println("Newly Modified Sequence:\n"+alsq.getSequence()); cdoc.setVamsasRoots(cdoc.getVamsasRoots()); } } catch (Exception ee) { System.err.println("Exception whilst updating :"); ee.printStackTrace(System.err); } vorbaclient.updateDocument(cdoc); } catch (Exception e) { System.err .println("Exception whilst dumping document tree after an update."); e.printStackTrace(System.err); } isUpdated = true; // tell main thread to reflect change... } }); // register close handler vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out .println("Received request to close vamsas document."); // ask user for a filename to save it to. // Then pass it to the vorba object... vorbaclient.storeDocument(new java.io.File( "UserLocation")); } }); // register some more handlers to monitor the session : vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("New Vamsas client for " + evt.getPropertyName() + ": " + evt.getOldValue() + " to " + evt.getNewValue()); // tell app add new client to its list of clients. } }); vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Vamsas client finalizing for " + evt.getPropertyName() + ": " + evt.getOldValue() + " to " + evt.getNewValue()); // tell app to update its list of clients to communicate // with. } }); vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Session " + evt.getPropertyName() + " is shutting down."); // tell app to finalize its session data before // shutdown. } }); vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out .println("Application received a DOCUMENT_FINALIZEAPPDATA event."); // tell app to finalize its session data prior to the // storage of the current session as an archive. } }); } public String Usage = "ExampleApplication [session urn] watch/n( future usage is :/n [+]\n" + " is one of :\n\tsave,update,close,watch"; String sess = null; private boolean parseArgs(String args[]) { if (args.length == 0) { return false; } if (!args[0].toLowerCase().equals("watch")) { sess = args[0]; } return true; } class ExamplePicker extends Thread { String me = null; public IPickManager pm = null; ExamplePicker(String me, IPickManager pm) { this.me = me; this.pm = pm; } public void run() { int mcount = 1; while (pm != null) { try { Thread.sleep(1000 + (long) Math.random() * 10000); } catch (Exception e) {} if (pm != null) { pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage("Message " + mcount++ + " from " + me)); } } } } public void runMe(String[] args) { if (!parseArgs(args)) { System.err.print(Usage); } // get IClientFactory try { clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory(); } catch (IOException e) { System.err.println(e + "\n" + Usage); System.exit(1); } // get an Iclient with session data app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1"); user = new UserHandle("arnolduser", "deathsdoor"); try { vorbaclient = clientfactory.getIClient(app, user); } catch (NoDefaultSessionException e) { System.err .println("There appear to be several sessions to choose from :"); String[] sessions = clientfactory.getCurrentSessions(); for (int s = 0; s < sessions.length; s++) System.err.println(sessions[s]); System.exit(2); } addHandlers(vorbaclient); try { vorbaclient.joinSession(); } catch (Exception se) { se.printStackTrace(); System.err.println(se + " when joining session.\n" + Usage); System.exit(1); } // register an update listener and a close listener. // get document data try { IClientDocument cdoc = vorbaclient.getClientDocument(); processVamsasDocument(cdoc); } catch (Exception e) { System.err .println("Unexpected exception when retrieving the client document for the first time!"); e.printStackTrace(System.err); System.exit(1); } int update = 0; ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle() .getClientUrn(), vorbaclient.getPickManager()); picker.start(); if (picker.pm!=null) { picker.pm.registerMessageHandler(new IMessageHandler() { public void handleMessage(Message message) { System.out .println("Received |" + message.getRawMessage() + "|"); } }); } while (!isShuttingdown && update < totalUpdates) { // do something with data // , update document, or something. // .. if (isUpdated) { System.out.println("Update handler called " + (++update) + " times"); System.out .println("******************************************"); isUpdated = false; // TODO: saner update det method. if (update % 2 == 1) { try { IClientDocument cdoc = vorbaclient.getClientDocument(); processVamsasDocument(cdoc); } catch (Exception e) { System.err .println("Error when updating document after an even numbered update."); e.printStackTrace(System.err); } } } try { Thread.sleep(15); } catch (Exception e) {} } System.out.println("Finalizing."); // call finalizeClient vorbaclient.finalizeClient(); System.out.println("Shutting down picker."); picker.pm = null; while (picker.isAlive()) { System.out.println("Waiting for picker to die..."); try { Thread.sleep(1000); } catch (Exception e) { } ; } // { meanwhile, eventHandlers are called to do any saves if need be } // and all registered listeners will be deregistered to avoid deadlock. // finish System.out.println("Byee!"); } public static void main(String[] args) { ExampleApplication example = new ExampleApplication(); example.runMe(args); } }