pick manager and simulation of alignment modification within existing document.
[vamsas.git] / src / uk / ac / vamsas / test / ExampleApplication.java
1 package uk.ac.vamsas.test;
2
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;
9
10 import java.awt.Event;
11 import java.beans.PropertyChangeEvent;
12 import java.beans.PropertyChangeListener;
13 import java.io.IOException;
14 import java.util.Vector;
15
16 /**
17  * Toy vamsas command line client application demonstrating the API. 
18  * Currently runs with one argument: ExampleApplication.main(new String("watch"))
19  * Test: Start up at least two of these processes independently and they will 
20  * successively modify and handle update events from the document model.
21  * 
22  * Behaviour of each client:
23  * Event handlers are registered for documentUpdate.
24  * - every document update:
25  *   * the vamsas document will be dumped to standard out using uk.ac.vamsas.test.simpleclient.ArchiveReports
26  *   * 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. 
27  * 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).
28  * A new vamsas root generated from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document.
29  * Then a while loop waits around for events until shutdown:
30  *  - currently it will shutdown after 9 updates (totalUpdates)
31  *  - an update will be made after every other update that is detected.
32  *  
33  * 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).
34  * 
35  * TODO: test
36  * appData get/set methods 
37  * 
38  * TODO: verify and test pickManager and interaction
39  * between it and other session events 
40  * 
41  * TODO: add more session interaction events
42  * 
43  * TODO: test client add/leave events - currently library generates exceptions for sessionlist and clientlist modifications.
44  * 
45  * @author jimp
46  */
47
48 public class ExampleApplication
49 {
50   private ClientHandle app;
51
52   private UserHandle user; // TODO: make this something defined by the
53   // api
54
55   private IClientFactory clientfactory;
56
57   private IClient vorbaclient;
58
59   private byte[] mydata;
60
61   private Vector vamsasObjects;
62
63   private boolean isUpdated = false;
64
65   private boolean isShuttingdown = false;
66
67   private boolean isFinalizing = false;
68   private int totalUpdates = 9;
69   private void processVamsasDocument(IClientDocument doc)
70   {
71     if (doc.getVamsasRoots().length<4) {
72     doc.addVamsasRoot(Core.getDemoVamsas());
73     } else {
74       try {
75         uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1].getDataSet(0);
76         uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0);
77         System.out.println("Modifying Sequence:\n"+alsq.hashCode());
78         alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar());
79         System.out.println("Modifying Sequence:\n"+alsq.hashCode());
80         System.out.println("Modified Sequence:\n"+alsq.getSequence());
81         doc.setVamsasRoots(doc.getVamsasRoots());
82       } catch (Exception ee) {
83       
84       }
85     }
86     vorbaclient.updateDocument(doc);
87     // merge vamsasObjects with vamsas objects in document
88     // get this apps 'mydata' if it hasn't got it already.
89     // .. access this application's 'public' mydata' if there is any.
90   }
91
92   private void addHandlers(IClient avorbaclient)
93   {
94     // make a non-volatile reference to the client instance.
95     final IClient vorbaclient = avorbaclient;
96     // register update handler
97     vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() {
98       public void propertyChange(PropertyChangeEvent evt)
99       {
100         System.out.println("Vamsas document update for "
101             + evt.getPropertyName() + ": " + evt.getOldValue()
102             + " to " + evt.getNewValue());
103         // merge new data into ours.
104         // example - output doc
105         try
106         {
107           IClientDocument cdoc = vorbaclient.getClientDocument();
108           uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(
109               cdoc.getVamsasRoots(), true, System.out);
110           // Simple update
111           try {
112             if (cdoc.getVamsasRoots().length>2) {
113               uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1].getDataSet(0);
114               uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0).getAlignmentSequence(0);
115               if (alsq.isUpdated())
116                 System.out.println("Seqeuence was updated since last time.");
117               alsq.setSequence(alsq.getSequence()+ds.getAlignment(0).getGapChar());
118               System.out.println("Newly Modified Sequence:\n"+alsq.getSequence());
119               cdoc.setVamsasRoots(cdoc.getVamsasRoots());
120             }
121           } catch (Exception ee) {
122             System.err.println("Exception whilst updating :");
123             ee.printStackTrace(System.err);
124           }
125           vorbaclient.updateDocument(cdoc);
126         }
127         catch (Exception e)
128         {
129           System.err
130           .println("Exception whilst dumping document tree after an update.");
131           e.printStackTrace(System.err);
132         }
133         isUpdated = true; // tell main thread to reflect change...
134       }
135     });
136     // register close handler
137     vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE,
138         new PropertyChangeListener() {
139       public void propertyChange(PropertyChangeEvent evt)
140       {
141         System.out
142         .println("Received request to close vamsas document.");
143         // ask user for a filename to save it to.
144         // Then pass it to the vorba object...
145         vorbaclient.storeDocument(new java.io.File(
146         "UserLocation"));
147       }
148     });
149
150     // register some more handlers to monitor the session :
151
152     vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION,
153         new PropertyChangeListener() {
154       public void propertyChange(PropertyChangeEvent evt)
155       {
156         System.out.println("New Vamsas client for "
157             + evt.getPropertyName() + ": "
158             + evt.getOldValue() + " to "
159             + evt.getNewValue());
160         // tell app add new client to its list of clients.
161       }
162     });
163     vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION,
164         new PropertyChangeListener() {
165       public void propertyChange(PropertyChangeEvent evt)
166       {
167         System.out.println("Vamsas client finalizing for "
168             + evt.getPropertyName() + ": "
169             + evt.getOldValue() + " to "
170             + evt.getNewValue());
171         // tell app to update its list of clients to communicate
172         // with.
173       }
174     });
175     vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN,
176         new PropertyChangeListener() {
177       public void propertyChange(PropertyChangeEvent evt)
178       {
179         System.out.println("Session " + evt.getPropertyName()
180             + " is shutting down.");
181         // tell app to finalize its session data before
182         // shutdown.
183       }
184     });
185     vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA,
186         new PropertyChangeListener() {
187       public void propertyChange(PropertyChangeEvent evt)
188       {
189         System.out
190         .println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
191         // tell app to finalize its session data prior to the
192         // storage of the current session as an archive.
193       }
194     });
195
196   }
197
198   public String Usage = "ExampleApplication [session urn] watch/n( future usage is :/n <vamsasFileDirectory> <vamsasSessionURN> <action> [+<arguments>]\n"
199     + "<action> is one of :\n\tsave,update,close,watch";
200
201   String sess = null;
202
203   private boolean parseArgs(String args[])
204   {
205     if (args.length == 0)
206     {
207       return false;
208     }
209     if (!args[0].toLowerCase().equals("watch"))
210     {
211       sess = args[0];
212     }
213     return true;
214   }
215
216   class ExamplePicker extends Thread
217   {
218     String me = null;
219
220     public IPickManager pm = null;
221
222     ExamplePicker(String me, IPickManager pm)
223     {
224       this.me = me;
225       this.pm = pm;
226     }
227
228     public void run()
229     {
230       int mcount = 1;
231       while (pm != null)
232       {
233         try { Thread.sleep(1000 + (long) Math.random() * 10000); }
234         catch (Exception e) {}
235
236         if (pm != null)
237         {
238           pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage("Message " + mcount++ + " from " + me));
239         }
240       }
241     }
242
243   }
244
245   public void runMe(String[] args)
246   {
247     if (!parseArgs(args))
248     {
249       System.err.print(Usage);
250     }
251     // get IClientFactory
252     try
253     {
254       clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
255     }
256     catch (IOException e)
257     {
258       System.err.println(e + "\n" + Usage);
259       System.exit(1);
260     }
261
262     // get an Iclient with session data
263     app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1");
264     user = new UserHandle("arnolduser", "deathsdoor");
265     try
266     {
267       vorbaclient = clientfactory.getIClient(app, user);
268     }
269     catch (NoDefaultSessionException e)
270     {
271       System.err
272       .println("There appear to be several sessions to choose from :");
273       String[] sessions = clientfactory.getCurrentSessions();
274       for (int s = 0; s < sessions.length; s++)
275         System.err.println(sessions[s]);
276       System.exit(2);
277     }
278     addHandlers(vorbaclient);
279     try
280     {
281       vorbaclient.joinSession();
282     }
283     catch (Exception se)
284     {
285       se.printStackTrace();
286       System.err.println(se + " when joining session.\n" + Usage);
287       System.exit(1);
288     }
289     // register an update listener and a close listener.
290     // get document data
291     try
292     {
293       IClientDocument cdoc = vorbaclient.getClientDocument();
294       processVamsasDocument(cdoc);
295     }
296     catch (Exception e)
297     {
298       System.err
299       .println("Unexpected exception when retrieving the client document for the first time!");
300       e.printStackTrace(System.err);
301       System.exit(1);
302     }
303     int update = 0;
304     ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle()
305         .getClientUrn(), vorbaclient.getPickManager());
306
307     picker.start();
308     if (picker.pm!=null) {
309       picker.pm.registerMessageHandler(new IMessageHandler() {
310
311         public void handleMessage(Message message)
312         {
313           System.out
314           .println("Received |" + message.getRawMessage() + "|");
315         }
316
317       });
318     }
319     while (!isShuttingdown && update < totalUpdates)
320     {
321       // do something with data
322       // , update document, or something.
323       // ..
324       if (isUpdated)
325       {
326         System.out.println("Update handler called " + (++update)
327             + " times");
328         System.out
329         .println("******************************************");
330         isUpdated = false; // TODO: saner update det method.
331         if (update % 2 == 1)
332         {
333           try
334           {
335             IClientDocument cdoc = vorbaclient.getClientDocument();
336             processVamsasDocument(cdoc);
337           }
338           catch (Exception e)
339           {
340             System.err
341             .println("Error when updating document after an even numbered update.");
342             e.printStackTrace(System.err);
343           }
344         }
345       }
346
347       try       { Thread.sleep(15); }
348       catch (Exception e) {}
349
350     }
351     System.out.println("Finalizing.");
352     // call finalizeClient
353     vorbaclient.finalizeClient();
354     System.out.println("Shutting down picker.");
355     picker.pm = null;
356     while (picker.isAlive())
357     {
358       System.out.println("Waiting for picker to die...");
359       try
360       {
361         Thread.sleep(1000);
362       }
363       catch (Exception e)
364       {
365       }
366       ;
367     }
368
369     // { meanwhile, eventHandlers are called to do any saves if need be }
370     // and all registered listeners will be deregistered to avoid deadlock.
371
372     // finish
373     System.out.println("Byee!");
374   }
375   public static void main(String[] args)
376   {
377     ExampleApplication example = new ExampleApplication();
378     example.runMe(args);
379   }
380 }