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. Currently
26 * runs with one argument: ExampleApplication.main(new String("watch")) Test:
27 * 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: Event handlers are registered for documentUpdate. -
31 * every document update: * the vamsas document will be dumped to standard out
32 * using uk.ac.vamsas.test.simpleclient.ArchiveReports * if there are more than
33 * 4 vamsas roots, the first sequence in the first alignment of the first
34 * dataset of the second vamsas root will be appended with a single gap
35 * character and then written back to the session document. A pick thread is
36 * started, which sends random CUSTOM pick events every so often (tuning:
37 * flooding the pick channel seems to affect the behaviour of other vamsasClient
38 * threads, suggesting some object lock contention). A new vamsas root generated
39 * from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document.
40 * Then a while loop waits around for events until shutdown: - currently it will
41 * shutdown after 9 updates (totalUpdates) - an update will be made after every
42 * other update that is detected.
44 * Status: PickManager now shuts down correctly. Serial updates for two
45 * instances work correctly and are detected under j1.4 (need to test in 1.5 and
48 * TODO: test appData get/set methods
50 * TODO: verify and test pickManager and interaction between it and other
53 * TODO: add more session interaction events
55 * TODO: test client add/leave events - currently library generates exceptions
56 * for sessionlist and clientlist modifications.
61 public class ExampleApplication {
62 private ClientHandle app;
64 private UserHandle user; // TODO: make this something defined by the
68 private IClientFactory clientfactory;
70 private IClient vorbaclient;
72 private byte[] mydata;
74 private Vector vamsasObjects;
76 private boolean isUpdated = false;
78 private boolean isShuttingdown = false;
80 private boolean isFinalizing = false;
82 private int totalUpdates = 9;
84 private uk.ac.vamsas.client.VorbaId recover = null;
86 private int calls = 0;
88 private long mdatahash = 0;
90 private long muserdatahash = 0;
92 private void processVamsasDocument(IClientDocument doc) {
93 if (doc.getVamsasRoots().length < 4) {
94 doc.addVamsasRoot(Core.getDemoVamsas());
97 uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1]
99 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0)
100 .getAlignmentSequence(0);
101 if (recover == null) {
102 recover = alsq.getVorbaId();
104 Vobject recoverd = doc.getObject(recover);
105 System.out.println("Recovery of " + recover + " was "
106 + ((recoverd == null) ? "A FAILURE" : "SUCCESSFUL"));
108 System.out.println("Modifying Sequence:\n" + alsq.hashCode());
109 alsq.setSequence(alsq.getSequence() + ds.getAlignment(0).getGapChar());
110 System.out.println("Modifying Sequence:\n" + alsq.hashCode());
111 System.out.println("Modified Sequence:\n" + alsq.getSequence());
112 doc.setVamsasRoots(doc.getVamsasRoots());
113 } catch (Exception ee) {
117 // get this apps 'mydata' if it hasn't got it already.
118 System.out.println("Trying to get appdata and modify it.....");
121 System.out.println(".....Finished.");
122 } catch (Exception e) {
123 System.err.println("Failed to process appdata for our application.");
124 e.printStackTrace(System.err);
127 // .. access this application's 'public' mydata' if there is any.
128 vorbaclient.updateDocument(doc);
129 // merge vamsasObjects with vamsas objects in document
133 private int appdatareads = 0;
135 boolean clientappd = true;
137 boolean userappd = false;
139 private void processAppData(IClientDocument doc) throws Exception {
141 boolean writtenonce = false;
143 uk.ac.vamsas.client.IClientAppdata appd = doc.getClientAppdata();
145 if (appd.hasClientAppdata() && !(appdatareads % 2 == 0)) {
146 // byte[] cappd = appd.getClientAppdata();
148 // System.out.println("Client appdata\n"+cappd.toString()+"\nEnd of
150 System.out.println("Testing read from inputstream");
151 String cappds = readData(appd.getClientInputStream());
153 .println("Client appdata\n" + cappds + "\nEnd of Appdata\n");
156 String newapd = "Client Appdata:";
157 if (appd.hasClientAppdata()) {
158 AppDataInputStream is;
159 newapd = readData(is = appd.getClientInputStream());
163 // appd.setClientAppdata(makeappData("Client Appdata for
164 // "+user.toString()+" written"));
165 writeData(appd.getClientOutputStream(), newapd
166 + " : Client Appdata for all users written on " + appdatareads
167 + " read by " + vorbaclient.getUserHandle());
168 System.out.println("Written to ClientAppdata stream.");
173 if (appd.hasUserAppdata() && !(appdatareads % 2 == 0)) {
174 byte[] cappd = appd.getUserAppdata();
176 System.out.println("User appdata\n" + new String(cappd)
177 + "\nEnd of Users' Appdata\n");
179 System.out.println("No user appdata.");
181 .setUserAppdata(("no default - overwritten null byte set on "
182 + appdatareads + " read by " + vorbaclient.getUserHandle() + "")
185 } else if (!writtenonce) {
187 byte[] bts = makeappData("User Appdata for " + user + " written on "
188 + appdatareads + " read at ");
189 System.out.println("Setting appData bytes to\n" + new String(bts)
191 appd.setUserAppdata(bts);
192 System.out.println("Written to UserAppdata stream.");
198 private byte[] makeappData(String message) {
199 StringBuffer sb = new StringBuffer();
201 sb.append("on " + new java.util.Date());
202 return sb.toString().getBytes();
205 private boolean writeData(AppDataOutputStream os, String message) {
206 StringBuffer sb = new StringBuffer();
208 sb.append("on " + new java.util.Date());
210 ObjectOutputStream oos = new ObjectOutputStream(os);
211 oos.writeObject(sb.toString());
214 } catch (Exception e) {
215 System.err.println("Problem serialising this message:\n" + sb);
216 e.printStackTrace(System.err);
222 private String readData(AppDataInputStream is) {
225 if (is.available() > 0) {
226 ObjectInputStream ois = new ObjectInputStream(is);
227 String rs = (String) ois.readObject();
230 } catch (Exception e) {
231 System.err.println("Failed to read a string from input stream!");
232 e.printStackTrace(System.err);
238 private void addHandlers(IClient avorbaclient) {
239 final ExampleApplication me = this;
240 // make a non-volatile reference to the client instance.
241 final IClient vorbaclient = avorbaclient;
242 // register update handler
243 vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() {
244 public void propertyChange(PropertyChangeEvent evt) {
245 System.out.println("Vamsas document update for "
246 + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
247 + evt.getNewValue());
248 // merge new data into ours.
249 // example - output doc
251 IClientDocument cdoc = vorbaclient.getClientDocument();
252 if (calls > 2 && cdoc.getVamsasRoots().length > 0
253 && !cdoc.getVamsasRoots()[0].is__stored_in_document()) {
255 .println("Pathological Update Detected - Document is zeroed!");
258 uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(cdoc
259 .getVamsasRoots(), true, System.out);
262 if (cdoc.getVamsasRoots().length > 2) {
263 uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1]
265 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds
266 .getAlignment(0).getAlignmentSequence(0);
267 if (alsq.isUpdated())
268 System.out.println("Seqeuence was updated since last time.");
269 alsq.setSequence(alsq.getSequence()
270 + ds.getAlignment(0).getGapChar());
271 System.out.println("Newly Modified Sequence:\n"
272 + alsq.getSequence());
273 cdoc.setVamsasRoots(cdoc.getVamsasRoots());
275 } catch (Exception ee) {
276 System.err.println("Exception whilst updating :");
277 ee.printStackTrace(System.err);
279 vorbaclient.updateDocument(cdoc);
280 } catch (Exception e) {
282 .println("Exception whilst dumping document tree after an update.");
283 e.printStackTrace(System.err);
285 isUpdated = true; // tell main thread to reflect change...
288 // register close handler
289 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE,
290 new PropertyChangeListener() {
291 public void propertyChange(PropertyChangeEvent evt) {
292 System.out.println("Received request to close vamsas document.");
293 // ask user for a filename to save it to.
294 // Then pass it to the vorba object...
295 vorbaclient.storeDocument(new java.io.File("UserLocation"));
299 // register some more handlers to monitor the session :
301 vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION,
302 new PropertyChangeListener() {
303 public void propertyChange(PropertyChangeEvent evt) {
304 System.out.println("New Vamsas client for " + evt.getPropertyName()
305 + ": " + evt.getOldValue() + " to " + evt.getNewValue());
306 // tell app add new client to its list of clients.
309 vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION,
310 new PropertyChangeListener() {
311 public void propertyChange(PropertyChangeEvent evt) {
312 System.out.println("Vamsas client finalizing for "
313 + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
314 + evt.getNewValue());
315 // tell app to update its list of clients to communicate
319 vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN,
320 new PropertyChangeListener() {
321 public void propertyChange(PropertyChangeEvent evt) {
322 System.out.println("Session " + evt.getPropertyName()
323 + " is shutting down.");
324 // tell app to finalize its session data before
328 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA,
329 new PropertyChangeListener() {
330 public void propertyChange(PropertyChangeEvent evt) {
331 boolean finalized = false;
333 .println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
334 IClientDocument cdoc = null;
336 cdoc = vorbaclient.getClientDocument();
338 IClientAppdata apd = cdoc.getClientAppdata();
341 if (apd.getUserAppdata() != null) {
342 userd = new String(apd.getUserAppdata());
344 String appdat = me.readData(apd.getClientInputStream());
345 me.writeData(apd.getClientOutputStream(), appdat
346 + "\nUser Data merged\n" + userd + "\n");
349 vorbaclient.updateDocument(cdoc);
351 // tell app to finalize its session data prior to the
352 // storage of the current session as an archive.
353 } catch (Exception e) {
356 .println("Probable library problem - exception when trying to update document after writing merged appdata.");
357 e.printStackTrace(System.err);
360 .println("Recovering from exception when writing merged appdata");
361 e.printStackTrace(System.err);
364 vorbaclient.updateDocument(cdoc);
366 } catch (Exception e2) {
368 .println("Probable library problem - exception when trying to update document after an exception when writing merged appdata.");
369 e2.printStackTrace(System.err);
374 System.out.println("Application finalized appdata successfuly.");
380 public String Usage = "ExampleApplication :/n [-arena <vamsasFileDirectory>][-session <vamsasSessionURN>] <action> [+<arguments>]\n"
381 + "<action> is one of :\n\tsave,new,watch\n"+
382 "-arena and -session are not yet supported"; // TODO for release
386 String importFile = null;
388 String outputFile = null;
389 boolean newSession=false;
390 boolean imported=false;
391 private boolean parseArgs(String args[]) {
392 if (args.length == 0) {
396 boolean parsed = false;
397 while (!parsed && cpos < args.length) {
398 // TODO: note importDocument not yet supported.
399 //if (args[cpos].toLowerCase().equals("load") && cpos + 1 < args.length) {
400 // importFile = args[cpos + 1];
404 if (args[cpos].toLowerCase().equals("new") && cpos + 1 < args.length) {
405 importFile = args[cpos + 1];
410 if (args[cpos].toLowerCase().equals("save") && cpos + 1 < args.length) {
411 outputFile = args[cpos + 1];
415 // default behaviour - if not anything else its probably a session urn
416 if (!args[cpos].toLowerCase().equals("watch")) {
424 class ExamplePicker extends Thread {
427 public IPickManager pm = null;
429 ExamplePicker(String me, IPickManager pm) {
438 Thread.sleep(1000 + (long) Math.random() * 10000);
439 } catch (Exception e) {
443 pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage(
444 "Message " + mcount++ + " from " + me));
453 public void runMe(String[] args) {
454 if (!parseArgs(args)) {
455 System.err.print(Usage);
457 // get IClientFactory
459 clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
460 } catch (IOException e) {
461 System.err.println(e + "\n" + Usage);
465 // get an Iclient with session data
466 app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1");
467 user = new UserHandle("arnolduser", "deathsdoor");
468 if (sess!=null && importFile!=null)
470 System.err.println("Import of an existing document into an existing session is not fully supported yet.");
475 System.out.println("Connecting to " + sess);
476 vorbaclient = clientfactory.getIClient(app, user, sess);
480 if (importFile==null)
482 System.out.println("Connecting to a new VAMSAS Session.");
483 vorbaclient = clientfactory.getNewSessionIClient(app, user);
485 System.out.println("Connecting to a new VAMSAS Session to share data in existing document:"+importFile);
486 File vfile = new File(importFile);
487 vorbaclient = clientfactory.openAsNewSessionIClient(app, user, vfile);
488 System.out.println("Succesfully imported document into new session.");
493 vorbaclient = clientfactory.getIClient(app, user);
497 catch (InvalidSessionDocumentException e) {
498 System.err.println("Failed to create a session to share "+importFile);
499 System.err.println("Sorry it didn't work out. This is what went wrong:");
500 e.printStackTrace(System.err);
503 catch (NoDefaultSessionException e) {
505 .println("There appear to be several sessions to choose from :");
506 String[] sessions = clientfactory.getCurrentSessions();
507 for (int s = 0; s < sessions.length; s++)
508 System.err.println(sessions[s]);
511 addHandlers(vorbaclient);
513 vorbaclient.joinSession();
514 } catch (Exception se) {
515 se.printStackTrace();
516 System.err.println(se + " when joining session.\n" + Usage);
519 // register an update listener and a close listener.
520 // import any data if requested to
521 if (importFile != null) {
522 File vfile = new File(importFile);
524 vorbaclient.importDocument(vfile);
526 } catch (Exception e) {
527 System.err.println("Failed to import file " + importFile);
528 System.err.println("Exception received was " + e);
529 e.printStackTrace(System.err);
533 // Write out any data if requested to
534 if (outputFile != null) {
535 File vfile = new File(outputFile);
537 vorbaclient.storeDocument(vfile);
538 } catch (Exception e) {
539 System.err.println("Failed to export session as file " + outputFile);
540 System.err.println("Exception received was " + e);
541 e.printStackTrace(System.err);
546 IClientDocument cdoc = vorbaclient.getClientDocument();
549 if (cdoc.getVamsasRoots()==null || cdoc.getVamsasRoots()[0].getDataSetCount()<1)
551 System.err.println("Imported an Empty vamsas document. Is this correct ?");
554 processVamsasDocument(cdoc);
555 } catch (Exception e) {
557 .println("Unexpected exception when retrieving the client document for the first time!");
558 e.printStackTrace(System.err);
562 ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle()
563 .getClientUrn(), vorbaclient.getPickManager());
566 if (picker.pm != null) {
567 picker.pm.registerMessageHandler(new IMessageHandler() {
569 public void handleMessage(Message message) {
570 System.out.println("Received |" + message.getRawMessage() + "|");
571 shutdown += 100; // hang around for 5 seconds or so before dying
578 shutdown = System.currentTimeMillis() + 10000; // hang around for 10
579 // seconds or so before
581 while (!isShuttingdown && update < totalUpdates) {
582 // do something with data
583 // , update document, or something.
586 System.out.println("Update handler called " + (++update) + " times");
587 System.out.println("******************************************");
588 isUpdated = false; // TODO: saner update det method.
589 shutdown = System.currentTimeMillis() + 10000;
590 if (update % 2 == 1) {
592 IClientDocument cdoc = vorbaclient.getClientDocument();
593 processVamsasDocument(cdoc);
594 } catch (Exception e) {
596 .println("Error when updating document after an even numbered update.");
597 e.printStackTrace(System.err);
601 } catch (Exception e){}
604 if (System.currentTimeMillis() > shutdown) {
605 isShuttingdown = true;
611 } catch (Exception e) {
615 System.out.println("Finalizing.");
616 // call finalizeClient
617 vorbaclient.finalizeClient();
618 System.out.println("Shutting down picker.");
620 while (picker.isAlive()) {
621 System.out.println("Waiting for picker to die...");
624 } catch (Exception e) {
629 // { meanwhile, eventHandlers are called to do any saves if need be }
630 // and all registered listeners will be deregistered to avoid deadlock.
634 clientfactory = null;
635 System.out.println("Byee!");
636 // try { Thread.sleep(100000); } catch (Exception e) {}
639 public static void main(String[] args) {
640 ExampleApplication example = new ExampleApplication();