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