bugfixed org.vamsas.test.simpleclient.ArchiveClient and made VorbaId mechanism more...
[vamsas.git] / src / org / vamsas / test / simpleclient / ClientDoc.java
1 package org.vamsas.test.simpleclient;
2
3 import java.util.Hashtable;
4 import java.util.Vector;
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.vamsas.client.IClientAppdata;
9 import org.vamsas.client.Vobject;
10 import org.vamsas.client.VorbaId;
11 import org.vamsas.client.simpleclient.ClientDocument;
12 import org.vamsas.client.simpleclient.VamsasArchive;
13 import org.vamsas.client.simpleclient.VamsasArchiveReader;
14 import org.vamsas.objects.core.Entry;
15 import org.vamsas.objects.core.VAMSAS;
16 import org.vamsas.objects.core.VamsasDocument;
17 import org.vamsas.objects.utils.ProvenanceStuff;
18
19 // simple holder to pass to client.
20 public class ClientDoc extends org.vamsas.client.ClientDocument {
21   /* (non-Javadoc)
22    * @see org.vamsas.client.IClientDocument#getClientAppdata()
23    */
24   public IClientAppdata getClientAppdata() {
25     throw new Error("Appdata access is not implemented in the test.simpleclient.ClientDoc instance."); // TODO Auto-generated method stub
26   }
27   protected boolean isModified=false;
28   private Log log = LogFactory.getLog(ClientDoc.class);
29   protected VamsasDocument doc;
30   public org.vamsas.objects.core.VAMSAS[] _VamsasRoots;
31   protected VamsasArchive iohandler=null;
32   protected VamsasArchiveReader reader=null;
33   private String user=null;
34   private String app=null;
35   
36   /**
37    * @param doc
38    * @param iohandler
39    * @param reader
40    * @param app
41    * @param user
42    */
43   public ClientDoc(VamsasDocument doc, VamsasArchive iohandler, VamsasArchiveReader reader, String app, String user, Hashtable objrefs) {
44     super(objrefs, (iohandler!=null) ? iohandler.getVorba() : null);
45     this.doc = doc;
46     this.iohandler = iohandler;
47     this.reader = reader;
48     this.app = app;
49     this.user = user;
50     this.objrefs = objrefs;
51     _VamsasRoots = doc.getVAMSAS();
52   }
53   // AppDataOutputStream appd;
54   //AppDataOutputStream userd;
55   /* (non-Javadoc)
56    * @see java.lang.Object#finalize()
57    */
58   protected Entry getProvenanceEntry(String action) {
59     // VAMSAS: modify schema to allow referencing of user field (plus other issues, ClientUrn field, machine readable action, input parameters, additional data generated notes
60     Entry prov = ProvenanceStuff.newProvenanceEntry(app, user, action);
61     return prov;
62   }
63   public VAMSAS[] getVamsasRoots() {
64     if (doc==null) {
65       log.debug("Null document for getVamsasRoots(), returning null");
66       return null;
67     }
68     if (iohandler==null) {
69       // LATER: decide on read-only status of ClientDocument object
70       log.warn("getVamsasRoots() called on possibly read-only document.");
71     }
72     if (_VamsasRoots!=null)
73       return _VamsasRoots;
74     VAMSAS[] roots = doc.getVAMSAS();
75     if (roots == null) {
76       // Make a new one to return to client to get filled. 
77       _VamsasRoots = new VAMSAS[] { new VAMSAS() };
78       // Do provenance now. just in case.
79       doc.getProvenance().addEntry(getProvenanceEntry("Created new document root [id="+_VamsasRoots[0].getId()+"]"));
80       doc.addVAMSAS(_VamsasRoots[0]);
81     } else {
82       _VamsasRoots = new VAMSAS[roots.length];
83       for (int r=0;r<roots.length; r++)
84         _VamsasRoots[r] = roots[r];
85     }
86     return _VamsasRoots;
87   }
88   
89   private int _contains(VAMSAS root, VAMSAS[] docRoots) {
90     if (root==null)
91       return -1;
92     if (docRoots==null || docRoots.length==0)
93       return -1;
94     VorbaId r_id = root.getVorbaId();
95     for (int i=0,j=docRoots.length; i<j; i++) {
96       VorbaId n_id=null;
97       if (docRoots[i]==root || (docRoots[i]!=null && (n_id=docRoots[i].getVorbaId())!=null && n_id.equals(r_id)))
98         return i;
99     }
100     return -1;
101   }
102 /**
103  * verify that newr version is really an intact version of the 
104  * @param newVersion (may be modified)
105  * @param oldVersion 
106  * @return true if newVersion is a valid root that preserves original references
107  */
108   private boolean isValidUpdate(VAMSAS newVersion, final VAMSAS oldVersion) {
109     // ideal - this cascades down the two structures, ensuring that all ID'd objects in one are present in the other.
110     if (oldVersion==newVersion) {
111       // may be a virgin root element.
112       if (!newVersion.isRegistered())
113         iohandler.getVorba().makeVorbaId(newVersion);
114       // Should retrieve original version and compare - unless local hashes can be used to determine if resultSet has been truncated.
115       // just do internal validation for moment.
116       if (newVersion.isValid())
117         return true;
118       return false;
119     } else {
120       // redundant ? if (oldVersion.is__stored_in_document())
121       if (!newVersion.isRegistered())
122         iohandler.getVorba().makeVorbaId(newVersion);
123       if (newVersion.isValid())
124         return true;
125     }
126     return false;
127   }
128     /**
129   /**
130    * merge old and new root vectors
131    * @param newr This array may be written to
132    * @param original
133    * @param the client document (usually this) which this root set belongs to.
134    * @return merged vector of vamsas roots
135    */
136   private VAMSAS[] _combineRoots(VAMSAS[] newr, final VAMSAS[] original, ClientDoc modflag) {
137     Vector rts = new Vector();
138     boolean modified=false;
139     for (int i=0,j=original.length; i<j; i++) {
140       int k = _contains(original[i], newr);
141       if (k>-1) {
142         if (isValidUpdate(newr[k], original[i])) {
143           modified=true;
144           rts.add(newr[k]);
145           newr[k]=null;
146         } else {
147           // LATER: try harder to merge ducument roots.
148           log.warn("Couldn't merge new VAMSAS root "+newr[k].getId());
149           newr[k] = null; // LATER: this means we ignore mangled roots. NOT GOOD
150         }
151       } else {
152         // add in order.
153         rts.add(original[i]);
154       }
155     }
156     // add remaining (new) roots
157     for (int i=0,j=newr.length; i<j; i++) {
158       if (newr[i]!=null) {
159         rts.add(newr[i]);
160         modified=true;
161       }
162     }
163     newr = new VAMSAS[rts.size()];
164     for (int i=0,j=rts.size(); i<j; i++)
165       newr[i] = (VAMSAS) rts.get(i);
166     if (modflag!=null)
167       modflag.isModified = modified;
168     return newr;
169   }
170   
171   /**
172    * update the document with new roots.
173    * LATER: decide: this affects the next call to getVamsasRoots()
174    * @see org.vamsas.IClientDocument.setVamsasRoots
175    */
176   public void setVamsasRoots(VAMSAS[] newroots) {
177     if (doc==null) {
178       log.debug("setVamsasRoots called on null document.");
179       return;
180     }
181     VAMSAS[] newr;
182     if (newroots==null) {
183       log.debug("setVamsasRoots(null) - do nothing.");
184       return;
185     }
186     // are we dealing with same array ?
187     if (_VamsasRoots!=newroots) {
188       // merge roots into local version.
189       newr = new VAMSAS[newroots.length];
190       for (int i=0;i<newr.length;i++)
191         newr[i] = newroots[i];
192       newr=_combineRoots(newr,_VamsasRoots,this);
193     } else {
194       newr = new VAMSAS[_VamsasRoots.length];
195       for (int i=0;i<newr.length;i++)
196         newr[i]=_VamsasRoots[i];
197     }
198     //  actually compare with document root set for final combination (to ensure nothing is lost)
199     _VamsasRoots = _combineRoots(newr, doc.getVAMSAS(), this); 
200   }
201   
202   
203   /* (non-Javadoc)
204    * LATER: decide: this affects the next call to getVamsasRoots()
205    * @see org.vamsas.client.IClientDocument#addVamsasRoot(org.vamsas.objects.core.VAMSAS)
206    */
207   public void addVamsasRoot(VAMSAS newroot) {
208     if (doc==null) {
209       log.debug("addVamsasRoots called on null document.");
210       return;
211     }
212     VAMSAS[] newroots = _combineRoots(new VAMSAS[] {newroot}, _VamsasRoots, this);
213     _VamsasRoots = newroots;  
214   }
215
216   public VamsasArchiveReader getReader() {
217     return reader;
218   }
219   private void _finalize() {
220     log.debug("finalizing clientDoc");
221     if (doc!=null) {
222       doc = null;
223     }
224     if (_VamsasRoots!=null) {
225       for (int i=0; i<_VamsasRoots.length; i++)
226         _VamsasRoots[i]=null;
227       _VamsasRoots=null;
228        
229     }
230       
231     if (reader!=null) {
232       log.debug("Closing and removing reader reference");
233       reader.close();
234       reader=null;
235     }
236     if (iohandler!=null) {
237       log.debug("Removing ioHandler reference.");
238       iohandler.cancelArchive();
239       iohandler=null;
240     }
241   }
242   protected void finalize() throws Throwable {
243     _finalize();
244     super.finalize();
245   }
246   private java.util.Hashtable objrefs=null;
247   
248   public VorbaId[] registerObjects(Vobject[] unregistered) {
249     if (doc==null) {
250       log.warn("registerObjects[] called on null document.");
251       return null;
252     }
253     if (objrefs==null) {
254       log.warn("registerObjects[] called for null objrefs hasharray.");
255       return null;
256     }
257     if (unregistered!=null) {
258       VorbaId ids[] = new VorbaId[unregistered.length];
259       for (int i=0,k=unregistered.length; i<k; i++)
260         if (unregistered[i]!=null) {
261           log.warn("Null Vobject passed to registerObject[] at position "+i);
262           return null;
263         } else {
264           ids[i]=registerObject(unregistered[i]);
265         }
266       log.debug("Registered "+unregistered.length+" objects - total of "+objrefs.size()+" ids.");
267       return ids;
268     }
269     return null;
270   }
271   /* (non-Javadoc)
272    * @see org.vamsas.client.IClientDocument#registerObject(org.vamsas.client.Vobject)
273    */
274   public VorbaId registerObject(Vobject unregistered) {
275     if (doc==null) {
276       log.warn("registerObjects called on null document.");
277       return null;
278     }
279     if (objrefs==null) {
280       log.warn("registerObjects called for null objrefs hasharray.");
281       return null;
282     }
283     if (iohandler==null) {
284       log.warn("registerObjects called for read only document.");
285       return null;
286     }
287     
288     if (unregistered!=null) {
289       VorbaId id = this._registerObject(unregistered);
290       log.debug("Registered object - total of "+objrefs.size()+" ids.");
291       return id;
292     }
293     log.warn("Null Vobject passed to registerObject.");
294     return null;
295   }
296   /*
297    * (non-Javadoc)
298    * 
299    * @see org.vamsas.client.IClientDocument#getObject(org.vamsas.client.VorbaId)
300    */
301   public Vobject getObject(VorbaId id) {
302     if (objrefs==null) {
303       log.debug("getObject called on null objrefs list.");
304       return null;
305     }
306     if (objrefs.containsKey(id.getId()))
307       return (Vobject) objrefs.get(id.getId());
308     log.debug("Returning null Vobject reference for id "+id.getId());
309     return null;
310   }
311   
312   /*
313    * (non-Javadoc)
314    * 
315    * @see org.vamsas.client.IClientDocument#getObjects(org.vamsas.client.VorbaId[])
316    */
317   public Vobject[] getObjects(VorbaId[] ids) {
318     if (objrefs==null) {
319       log.debug("getObject[]  called on null objrefs list.");
320       return null;
321     }
322     Vobject[] vo = new Vobject[ids.length];
323     for (int i=0,j=ids.length; i<j;i++) 
324       if (objrefs.containsKey(ids[i]))
325         vo[i] = (Vobject) objrefs.get(ids[i]);
326       else
327         log.debug("Returning null Vobject reference for id "+ids[i].getId());
328     return vo;
329   }
330   protected void updateDocumentRoots() {
331     if (doc==null) {
332       log.error("updateDocumentRoots called on null document. Probably an implementation error.");
333       return;
334     }
335     if (isModified) {
336       if (_VamsasRoots!=null) {
337         doc.setVAMSAS(_VamsasRoots);
338         _VamsasRoots=null;
339       }
340     }
341   }
342   /**
343    * tell vamsas client to close the document and reset the object. Once closed, nothing can be done with the object.
344    *
345    */
346   public void closeDoc() {
347     if (doc!=null) {
348       log.debug("Closing open document.");
349       _finalize();
350     } else {
351       log.warn("Ignoring closeDoc on invalid document.");
352     }
353   }
354   
355 }