1 package uk.ac.vamsas.test;
3 import uk.ac.vamsas.client.*;
4 import uk.ac.vamsas.client.picking.IMessageHandler;
5 import uk.ac.vamsas.client.picking.IPickManager;
6 import uk.ac.vamsas.client.picking.Message;
7 import uk.ac.vamsas.objects.core.VAMSAS;
8 import uk.ac.vamsas.test.objects.Core;
10 import java.awt.Event;
11 import java.beans.PropertyChangeEvent;
12 import java.beans.PropertyChangeListener;
13 import java.io.DataInput;
14 import java.io.DataInputStream;
15 import java.io.DataOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.ObjectInputStream;
20 import java.io.ObjectOutputStream;
21 import java.io.OutputStream;
22 import java.util.Vector;
25 * Toy vamsas command line client application demonstrating the API.
26 * Currently runs with one argument: ExampleApplication.main(new String("watch"))
27 * Test: Start up at least two of these processes independently and they will
28 * successively modify and handle update events from the document model.
30 * Behaviour of each client:
31 * Event handlers are registered for documentUpdate.
32 * - every document update:
33 * * the vamsas document will be dumped to standard out using uk.ac.vamsas.test.simpleclient.ArchiveReports
34 * * 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.
35 * 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).
36 * A new vamsas root generated from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document.
37 * Then a while loop waits around for events until shutdown:
38 * - currently it will shutdown after 9 updates (totalUpdates)
39 * - an update will be made after every other update that is detected.
41 * 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).
44 * appData get/set methods
46 * TODO: verify and test pickManager and interaction
47 * between it and other session events
49 * TODO: add more session interaction events
51 * TODO: test client add/leave events - currently library generates exceptions for sessionlist and clientlist modifications.
56 public class ExampleApplication
58 private ClientHandle app;
60 private UserHandle user; // TODO: make this something defined by the
63 private IClientFactory clientfactory;
65 private IClient vorbaclient;
67 private byte[] mydata;
69 private Vector vamsasObjects;
71 private boolean isUpdated = false;
73 private boolean isShuttingdown = false;
75 private boolean isFinalizing = false;
76 private int totalUpdates = 9;
77 private uk.ac.vamsas.client.VorbaId recover = null;
79 private long mdatahash = 0;
80 private long muserdatahash = 0;
82 private void processVamsasDocument(IClientDocument doc)
84 if (doc.getVamsasRoots().length<4) {
85 doc.addVamsasRoot(Core.getDemoVamsas());
88 uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1].getDataSet(0);
89 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0);
92 recover = alsq.getVorbaId();
94 Vobject recoverd = doc.getObject(recover);
95 System.out.println("Recovery of "+recover+" was "+((recoverd==null) ? "A FAILURE" : "SUCCESSFUL"));
97 System.out.println("Modifying Sequence:\n"+alsq.hashCode());
98 alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar());
99 System.out.println("Modifying Sequence:\n"+alsq.hashCode());
100 System.out.println("Modified Sequence:\n"+alsq.getSequence());
101 doc.setVamsasRoots(doc.getVamsasRoots());
102 } catch (Exception ee) {
106 // get this apps 'mydata' if it hasn't got it already.
107 System.out.println("Trying to get appdata and modify it.....");
110 System.out.println(".....Finished.");
111 } catch (Exception e)
113 System.err.println("Failed to process appdata for our application.");
114 e.printStackTrace(System.err);
118 // .. access this application's 'public' mydata' if there is any.
119 vorbaclient.updateDocument(doc);
120 // merge vamsasObjects with vamsas objects in document
123 private int appdatareads=0;
124 private void processAppData(IClientDocument doc) throws Exception {
126 boolean writtenonce=false;
129 uk.ac.vamsas.client.IClientAppdata appd = doc.getClientAppdata();
130 if (appd.hasClientAppdata() && !(appdatareads % 2==0))
132 //byte[] cappd = appd.getClientAppdata();
134 // System.out.println("Client appdata\n"+cappd.toString()+"\nEnd of Appdata\n");
135 System.out.println("Testing read from inputstream");
136 String cappds = readData(appd.getClientInputStream());
137 System.out.println("Client appdata\n"+cappds+"\nEnd of Appdata\n");
142 // appd.setClientAppdata(makeappData("Client Appdata for "+user.toString()+" written"));
143 writeData(appd.getClientOutputStream(), "Client Appdata for all users written on "+appdatareads+" read by "+vorbaclient.getUserHandle());
144 System.out.println("Written to ClientAppdata stream.");
147 if (appd.hasUserAppdata() && !(appdatareads % 2==0))
149 byte[] cappd = appd.getUserAppdata();
151 System.out.println("User appdata\n"+new String(cappd)+"\nEnd of Users' Appdata\n");
154 System.out.println("No user appdata.");
155 appd.setUserAppdata(("no default - overwritten null byte set on "+appdatareads+" read by "+vorbaclient.getUserHandle()+"").getBytes());
161 byte[] bts = makeappData("User Appdata for "+user+" written on "+appdatareads+" read at ");
162 System.out.println("Setting appData bytes to\n"+new String(bts)+"\nEnd.");
163 appd.setUserAppdata(bts);
164 System.out.println("Written to UserAppdata stream.");
168 private byte[] makeappData(String message)
170 StringBuffer sb = new StringBuffer();
172 sb.append("on "+new java.util.Date());
173 return sb.toString().getBytes();
175 private boolean writeData(AppDataOutputStream os, String message)
177 StringBuffer sb = new StringBuffer();
179 sb.append("on "+new java.util.Date());
181 ObjectOutputStream oos = new ObjectOutputStream(os);
182 oos.writeObject(sb.toString());
186 catch (Exception e) {
187 System.err.println("Problem serialising this message:\n"+sb);
188 e.printStackTrace(System.err);
193 private String readData(AppDataInputStream is)
196 ObjectInputStream ois = new ObjectInputStream(is);
197 String rs = (String) ois.readObject();
202 System.err.println("Failed to read a string from input stream!");
203 e.printStackTrace(System.err);
207 private void addHandlers(IClient avorbaclient)
209 // make a non-volatile reference to the client instance.
210 final IClient vorbaclient = avorbaclient;
211 // register update handler
212 vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() {
213 public void propertyChange(PropertyChangeEvent evt)
215 System.out.println("Vamsas document update for "
216 + evt.getPropertyName() + ": " + evt.getOldValue()
217 + " to " + evt.getNewValue());
218 // merge new data into ours.
219 // example - output doc
222 IClientDocument cdoc = vorbaclient.getClientDocument();
223 if (calls>2 && cdoc.getVamsasRoots().length>0 && !cdoc.getVamsasRoots()[0].is__stored_in_document())
225 System.err.println("Pathological Update Detected - Document is zeroed!");
228 uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(
229 cdoc.getVamsasRoots(), true, System.out);
232 if (cdoc.getVamsasRoots().length>2) {
233 uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1].getDataSet(0);
234 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0);
235 if (alsq.isUpdated())
236 System.out.println("Seqeuence was updated since last time.");
237 alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar());
238 System.out.println("Newly Modified Sequence:\n"+alsq.getSequence());
239 cdoc.setVamsasRoots(cdoc.getVamsasRoots());
241 } catch (Exception ee) {
242 System.err.println("Exception whilst updating :");
243 ee.printStackTrace(System.err);
245 vorbaclient.updateDocument(cdoc);
250 .println("Exception whilst dumping document tree after an update.");
251 e.printStackTrace(System.err);
253 isUpdated = true; // tell main thread to reflect change...
256 // register close handler
257 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE,
258 new PropertyChangeListener() {
259 public void propertyChange(PropertyChangeEvent evt)
262 .println("Received request to close vamsas document.");
263 // ask user for a filename to save it to.
264 // Then pass it to the vorba object...
265 vorbaclient.storeDocument(new java.io.File(
270 // register some more handlers to monitor the session :
272 vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION,
273 new PropertyChangeListener() {
274 public void propertyChange(PropertyChangeEvent evt)
276 System.out.println("New Vamsas client for "
277 + evt.getPropertyName() + ": "
278 + evt.getOldValue() + " to "
279 + evt.getNewValue());
280 // tell app add new client to its list of clients.
283 vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION,
284 new PropertyChangeListener() {
285 public void propertyChange(PropertyChangeEvent evt)
287 System.out.println("Vamsas client finalizing for "
288 + evt.getPropertyName() + ": "
289 + evt.getOldValue() + " to "
290 + evt.getNewValue());
291 // tell app to update its list of clients to communicate
295 vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN,
296 new PropertyChangeListener() {
297 public void propertyChange(PropertyChangeEvent evt)
299 System.out.println("Session " + evt.getPropertyName()
300 + " is shutting down.");
301 // tell app to finalize its session data before
305 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA,
306 new PropertyChangeListener() {
307 public void propertyChange(PropertyChangeEvent evt)
310 .println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
311 // tell app to finalize its session data prior to the
312 // storage of the current session as an archive.
318 public String Usage = "ExampleApplication :/n [-arena <vamsasFileDirectory>][-session <vamsasSessionURN>] <action> [+<arguments>]\n"
319 + "<action> is one of :\n\tsave,update,close,watch";
322 String importFile=null;
323 String outputFile=null;
324 private boolean parseArgs(String args[])
326 if (args.length == 0)
331 boolean parsed=false;
332 while (!parsed && cpos<args.length)
334 if (args[cpos].toLowerCase().equals("load") && cpos+1<args.length)
336 importFile=args[cpos+1];
340 if (args[cpos].toLowerCase().equals("save") && cpos+1<args.length)
342 outputFile=args[cpos+1];
346 // default behaviour - if not anything else its probably a session urn
347 if (!args[cpos].toLowerCase().equals("watch"))
356 class ExamplePicker extends Thread
360 public IPickManager pm = null;
362 ExamplePicker(String me, IPickManager pm)
373 try { Thread.sleep(1000 + (long) Math.random() * 10000); }
374 catch (Exception e) {}
378 pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage("Message " + mcount++ + " from " + me));
385 public void runMe(String[] args)
387 if (!parseArgs(args))
389 System.err.print(Usage);
391 // get IClientFactory
394 clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
396 catch (IOException e)
398 System.err.println(e + "\n" + Usage);
402 // get an Iclient with session data
403 app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1");
404 user = new UserHandle("arnolduser", "deathsdoor");
409 System.out.println("Connecting to "+sess);
410 vorbaclient = clientfactory.getIClient(app, user, sess);
414 vorbaclient = clientfactory.getIClient(app, user);
417 catch (NoDefaultSessionException e)
420 .println("There appear to be several sessions to choose from :");
421 String[] sessions = clientfactory.getCurrentSessions();
422 for (int s = 0; s < sessions.length; s++)
423 System.err.println(sessions[s]);
426 addHandlers(vorbaclient);
429 vorbaclient.joinSession();
433 se.printStackTrace();
434 System.err.println(se + " when joining session.\n" + Usage);
437 // register an update listener and a close listener.
438 // import any data if requested to
439 if (importFile!=null)
441 File vfile = new File(importFile);
444 vorbaclient.importDocument(vfile);
448 System.err.println("Failed to import file "+importFile);
449 System.err.println("Exception received was "+e);
450 e.printStackTrace(System.err);
454 // Write out any data if requested to
455 if (outputFile!=null)
457 File vfile = new File(outputFile);
460 vorbaclient.storeDocument(vfile);
464 System.err.println("Failed to export session as file "+outputFile);
465 System.err.println("Exception received was "+e);
466 e.printStackTrace(System.err);
472 IClientDocument cdoc = vorbaclient.getClientDocument();
473 processVamsasDocument(cdoc);
478 .println("Unexpected exception when retrieving the client document for the first time!");
479 e.printStackTrace(System.err);
483 ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle()
484 .getClientUrn(), vorbaclient.getPickManager());
487 if (picker.pm!=null) {
488 picker.pm.registerMessageHandler(new IMessageHandler() {
490 public void handleMessage(Message message)
493 .println("Received |" + message.getRawMessage() + "|");
494 shutdown +=100; // hang around for 5 seconds or so before dying naturally.
500 shutdown = System.currentTimeMillis()+10000; // hang around for 10 seconds or so before dying naturally.
501 while (!isShuttingdown && update < totalUpdates)
503 // do something with data
504 // , update document, or something.
508 System.out.println("Update handler called " + (++update)
511 .println("******************************************");
512 isUpdated = false; // TODO: saner update det method.
513 shutdown = System.currentTimeMillis()+10000;
518 IClientDocument cdoc = vorbaclient.getClientDocument();
519 processVamsasDocument(cdoc);
524 .println("Error when updating document after an even numbered update.");
525 e.printStackTrace(System.err);
529 if (System.currentTimeMillis()>shutdown)
535 try { Thread.sleep(50); }
536 catch (Exception e) {}
539 System.out.println("Finalizing.");
540 // call finalizeClient
541 vorbaclient.finalizeClient();
542 System.out.println("Shutting down picker.");
544 while (picker.isAlive())
546 System.out.println("Waiting for picker to die...");
557 // { meanwhile, eventHandlers are called to do any saves if need be }
558 // and all registered listeners will be deregistered to avoid deadlock.
561 System.out.println("Byee!");
563 public static void main(String[] args)
565 ExampleApplication example = new ExampleApplication();