implemented state flags and automatic call to VorbaIdFactory for unregistered (but...
[vamsas.git] / src / org / vamsas / client / SimpleClient.java
1 /*
2  * Created on 15-Sep-2005
3  *
4  * TODO To change the template for this generated file go to
5  * Window - Preferences - Java - Code Style - Code Templates
6  */
7 package org.vamsas.client;
8
9 import java.beans.EventHandler;
10 import java.beans.PropertyChangeEvent;
11 import java.beans.PropertyChangeListener;
12 import java.beans.PropertyChangeSupport;
13 import java.io.BufferedReader;
14 import java.io.File;
15 import java.io.IOException;
16 import java.io.Reader;
17 import java.io.Writer;
18 import java.lang.reflect.Field;
19 import java.util.Hashtable;
20 import java.util.Vector;
21
22 import org.exolab.castor.xml.IDResolver;
23 import org.exolab.castor.xml.MarshalException;
24 import org.exolab.castor.xml.Marshaller;
25 import org.exolab.castor.xml.UnmarshalListener;
26 import org.exolab.castor.xml.Unmarshaller;
27 import org.exolab.castor.xml.ValidationException;
28 import org.vamsas.objects.core.VamsasDocument;
29
30 /**
31  * @author jimp
32  */
33 public class SimpleClient implements IClient {
34
35   UserHandle user = null;
36
37   SessionHandle session = null;
38
39   ClientHandle client = null;
40
41   /*
42    * (non-Javadoc)
43    * 
44    * @see org.vamsas.client.IClient#getAbout()
45    */
46   public String getAbout() {
47     return new String("VORBA SimpleClient version $version$ build $build$");
48   }
49
50   /*
51    * (non-Javadoc)
52    * 
53    * @see org.vamsas.client.IClient#getSessionUrn()
54    */
55   public String getSessionUrn() {
56     return session.getSessionUrn();
57   }
58
59   /*
60    * (non-Javadoc)
61    * 
62    * @see org.vamsas.client.IClient#getSessionHandle()
63    */
64   public SessionHandle getSessionHandle() {
65     return session;
66   }
67
68   /*
69    * (non-Javadoc)
70    * 
71    * @see org.vamsas.client.IClient#getClientHandle()
72    */
73   public ClientHandle getClientHandle() {
74     return client;
75   }
76
77   /*
78    * (non-Javadoc)
79    * 
80    * @see org.vamsas.client.IClient#getUserHandle()
81    */
82   public UserHandle getUserHandle() {
83     return user;
84   }
85
86   private Hashtable handlers = initHandlers();
87
88   private Vector listeners = new Vector();
89
90   /**
91    * make all the PropertyChangeSupport objects for the
92    * events described in org.vamsas.client.Event
93    * @return
94    */
95   private static Hashtable initHandlers() {
96     Hashtable events = new Hashtable();
97     java.util.Iterator evt = Events.EventList.iterator();
98     while (evt.hasNext()) {
99       Object ths = evt.next();
100       events.put(ths, (Object) new PropertyChangeSupport(ths));
101     }
102     return events;
103   }
104
105   /*
106    * (non-Javadoc)
107    * 
108    * @see org.vamsas.client.IClient#addDocumentUpdateHandler(java.util.EventListener)
109    */
110   public void addDocumentUpdateHandler(PropertyChangeListener evt) {
111     if (handlers.containsKey(Events.DOCUMENT_UPDATE)) {
112       Object handler;
113       ((PropertyChangeSupport) (handler = handlers.get(Events.DOCUMENT_UPDATE)))
114           .addPropertyChangeListener(evt);
115       listeners.add(handler);
116       listeners.add((Object) evt);
117     }
118   }
119
120   /*
121    * (non-Javadoc)
122    * 
123    * @see org.vamsas.client.IClient#finalizeClient()
124    */
125   public void finalizeClient() {
126     // TODO: raise events
127     // deregister listeners.
128     // mark this instance as finalized
129   }
130
131   /**
132    * writes the VamsasDocument to the given stream.
133    * TODO: ensure that (at least) default provenance entries are written for objects.
134    * @param outstream
135    * @param doc
136    * @throws IOException
137    * @throws MarshalException
138    * @throws ValidationException
139    */
140   private static void setVamsasDocument(Writer outstream, VamsasDocument doc)
141       throws IOException, MarshalException, ValidationException {
142     Marshaller marshaller = new Marshaller(outstream);
143     marshaller.marshal(doc);
144   }
145
146   /**
147    * Unmarshals a vamsasDocument object from a stream, registers
148    * unregistered objects, records existing VorbaIds, and completes 
149    * the org.vamsas.client.object housekeeping fields.
150    * For a valid unmarshalling, the array of returned objects also includes
151    * a <return>sync</return> parameter which is true if new VorbaIds
152    * were created. If sync is false, then the caller should ensure that the
153    * vamsasDocument is written back to disk to propagate the new VorbaIds.
154    *  TODO: ensure that provenance is correct for newly registered objects
155    * @param instream - the XML input stream 
156    * @param factory - the SimpleClient's properly configured VorbaId factory to make new references.
157    * @return null or {(Object) VamsasDocument object, (Object) Hashtable of object references, (Object) Boolean(sync) }
158    */
159 private static Object[] getVamsasDocument(Reader instream,
160       IVorbaIdFactory factory) {
161     Unmarshaller unmarshaller = new Unmarshaller(instream);
162     unmarshaller.setIDResolver(new IDResolver() {
163       public Object resolve(String id) {
164         System.err.println("Warning - id " + id
165             + " is not found in the VamsasDocument!");
166         return null;
167       }
168     });
169     Hashtable refbase = new Hashtable();
170     Vector unrefed = new Vector();
171     final Hashtable objrefs = refbase;
172     final IVorbaIdFactory vorbafactory = factory;
173     final Vector unrefedObj =  unrefed;
174     unmarshaller.setUnmarshalListener(new UnmarshalListener() {
175
176       /*
177        * (non-Javadoc)
178        * 
179        * @see org.exolab.castor.xml.UnmarshalListener#attributesProcessed(java.lang.Object)
180        */
181       public void attributesProcessed(Object object) {
182       }
183
184       /*
185        * (non-Javadoc)
186        * 
187        * @see org.exolab.castor.xml.UnmarshalListener#fieldAdded(java.lang.String,
188        *      java.lang.Object, java.lang.Object)
189        */
190       public void fieldAdded(String fieldName, Object parent, Object child) {
191       }
192
193       /*
194        * (non-Javadoc)
195        * 
196        * @see org.exolab.castor.xml.UnmarshalListener#initialized(java.lang.Object)
197        */
198       public void initialized(Object object) {
199       }
200
201       /*
202        * Check if the object has an 'id' field - if it does, copy the value into
203        * the VorbaId field of object, and add the object to the VorbaId hash.
204        * 
205        * @see org.exolab.castor.xml.UnmarshalListener#unmarshalled(java.lang.Object)
206        */
207       public void unmarshalled(Object newobj) {
208         if (newobj instanceof object) {
209           object nobj = (object) newobj;
210           nobj.set__stored_in_document(true);
211           Field fd = null;
212           try {
213             if (nobj.isRegisterable()) {
214               // look for the id field (should be an NCName string)
215               nobj.__vorba = vorbafactory;
216               fd = nobj.getClass().getField("id");
217               String idstring;
218               if (fd.get(nobj) != null) {
219                 idstring = (String) fd.get(nobj);
220                 if (idstring.length() > 0) {
221                   if (!objrefs.containsKey(idstring)) {
222                     objrefs.put(idstring, nobj);
223                     nobj.setVorbaId(VorbaId.newId(idstring));
224                   } else {
225                     System.err.println("Serious problem : duplicate id '"+idstring+"' found! expect badness.");
226                     // TODO: HANDLE duplicate XML ids correctly
227                   }
228                 } else {
229                   // add to list of objects without a valid vorbaId
230                   unrefedObj.add(nobj);
231                 }
232               } else {
233                 // add to list of objects without a valid vorbaId
234                 unrefedObj.add(nobj);
235               }
236               
237             nobj.doHash();
238           }
239           } catch (Exception e) {
240             return;
241           };
242           
243         }
244       }
245
246     });
247     // Call the unmarshaller.
248     try {
249       while (instream.ready()) {
250         Object obj = unmarshaller.unmarshal(instream);
251         boolean sync=true;
252         if (obj instanceof VamsasDocument) {
253           if (unrefed.size()>0) {
254             sync=false; // document is out of sync - ids have been created.
255             java.util.Iterator newobj = unrefed.listIterator();
256             while (newobj.hasNext()) {
257               object o = (object) newobj.next();
258               // forces registration and id field update.
259               VorbaId id = o.getVorbaId();
260               if (!objrefs.containsKey(id)) {
261                 objrefs.put(id.id, o);
262               } else {
263                 throw new Error("Serious! Duplicate reference made by vorbaIdFactory!");
264               }
265             }
266           }
267           return new Object[] { obj, objrefs, new Boolean(sync)};
268         }
269       }
270     } catch (MarshalException e) {
271       // TODO Auto-generated catch block
272       e.printStackTrace();
273     } catch (ValidationException e) {
274       // TODO Auto-generated catch block
275       e.printStackTrace();
276     } catch (IOException e) {
277       // TODO Auto-generated catch block
278       e.printStackTrace();
279     }
280     return null;
281   }
282   /**
283    * extract data appropriate for client, session and user
284    * from vamsas document.
285    * @return application's byte array
286    */
287   private byte[] getApplicationData() {
288     // TODO: extract correct byte object from Jar and return it to application.
289     return null;
290   }
291
292   /*
293    * (non-Javadoc)
294    * 
295    * @see org.vamsas.client.IClient#getClientDocument()
296    */
297   public IClientDocument getClientDocument() {
298     Object[] vdoc;//  TODO: = getVamsasDocument(new Reader());
299     // ClientDocument cdoc = new ClientDocument(getApplicationData(),
300         // ((VamsasDocument) vdoc[0]).getVAMSAS(), (Hashtable) vdoc[1], this);
301     // 
302     return null;
303   }
304
305   /*
306    * (non-Javadoc)
307    * 
308    * @see org.vamsas.client.IClient#updateDocument(org.vamsas.client.IClientDocument)
309    */
310   public void updateDocument(IClientDocument newdoc) {
311     // TODO Auto-generated method stub
312     // 
313   }
314
315   /*
316    * (non-Javadoc)
317    * 
318    * @see org.vamsas.client.IClient#storeDocument(java.io.File)
319    */
320   public void storeDocument(File location) {
321     // TODO Auto-generated method stub
322
323   }
324
325   /*
326    * (non-Javadoc)
327    * 
328    * @see org.vamsas.client.IClient#addVorbaEventHandler(java.lang.String,
329    *      java.beans.PropertyChangeListener)
330    */
331   public void addVorbaEventHandler(String EventChain, PropertyChangeListener evt) {
332     if (handlers.containsKey(EventChain)) {
333       Object handler;
334       ((PropertyChangeSupport) (handler = handlers.get(EventChain)))
335           .addPropertyChangeListener(evt);
336       listeners.add(handler);
337       listeners.add((Object) evt);
338     }
339   }
340
341   /* (non-Javadoc)
342    * @see org.vamsas.client.IClient#pollUpdate()
343    */
344   public void pollUpdate() {
345     // TODO wake up UpdateWatcher thread to check for updates.
346
347   }
348
349   public static void main(String[] args) {
350   }
351 }