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