4 package org.vamsas.client;
6 import java.io.IOException;
9 import java.lang.reflect.Field;
10 import java.util.Hashtable;
11 import java.util.Iterator;
12 import java.util.Vector;
14 import org.exolab.castor.xml.IDResolver;
15 import org.exolab.castor.xml.MarshalException;
16 import org.exolab.castor.xml.Marshaller;
17 import org.exolab.castor.xml.UnmarshalListener;
18 import org.exolab.castor.xml.Unmarshaller;
19 import org.exolab.castor.xml.ValidationException;
20 import org.vamsas.objects.core.VamsasDocument;
22 * Implements the Vamsas object ID machinery for translating
23 * between non-volatile XML IDs and object references. Use the
24 * marshalling and unmarshalling methods in this class in order
25 * to avoid validation exceptions when marshalling new objects
26 * into the vamsas document.
28 public class VorbaXmlBinder implements UnmarshalListener {
29 private final IVorbaIdFactory vorbafactory;
31 private final Vector obj;
33 private final Hashtable objrefs;
35 public VorbaXmlBinder(IVorbaIdFactory vorbafactory, Vector obj, Hashtable objrefs) {
36 this.vorbafactory = vorbafactory;
38 this.objrefs = objrefs;
44 * @see org.exolab.castor.xml.UnmarshalListener#attributesProcessed(java.lang.Object)
46 public void attributesProcessed(Object object) {
52 * @see org.exolab.castor.xml.UnmarshalListener#fieldAdded(java.lang.String,
53 * java.lang.Object, java.lang.Object)
55 public void fieldAdded(String fieldName, Object parent, Object child) {
61 * @see org.exolab.castor.xml.UnmarshalListener#initialized(java.lang.Object)
63 public void initialized(Object object) {
67 * Check if the object has an 'id' field - if it does, copy the value into
68 * the VorbaId field of object, and add the object to the VorbaId hash.
70 * @see org.exolab.castor.xml.UnmarshalListener#unmarshalled(java.lang.Object)
72 public void unmarshalled(Object newobj) {
73 if (newobj instanceof object) {
74 object nobj = (object) newobj;
75 nobj.set__stored_in_document(true);
78 if (nobj.isRegisterable()) {
79 // look for the id field (should be an NCName string)
80 nobj.__vorba = vorbafactory;
81 fd = nobj.getClass().getField("id");
83 if (fd.get(nobj) != null) {
84 idstring = (String) fd.get(nobj);
85 if (idstring.length() > 0) {
86 if (!objrefs.containsKey(idstring)) {
87 objrefs.put(idstring, nobj);
88 nobj.setVorbaId(VorbaId.newId(idstring));
90 System.err.println("Serious problem : duplicate id '"+idstring+"' found! expect badness.");
91 // TODO: HANDLE duplicate XML ids correctly
94 // add to list of objects without a valid vorbaId
98 // add to list of objects without a valid vorbaId
104 } catch (Exception e) {
112 * writes the VamsasDocument to the given stream.
113 * TODO: ensure that (at least) default provenance entries are written for objects.
116 * @throws IOException
117 * @throws MarshalException
118 * @throws ValidationException
120 private static void setVamsasDocument(Writer outstream, VamsasDocument doc)
121 throws IOException, MarshalException, ValidationException {
122 Marshaller marshaller = new Marshaller(outstream);
123 marshaller.marshal(doc);
127 * Unmarshals a vamsasDocument object from a stream, registers
128 * unregistered objects, records existing VorbaIds, and completes
129 * the org.vamsas.client.object housekeeping fields.
130 * For a valid unmarshalling, the array of returned objects also includes
131 * a <return>sync</return> parameter which is true if new VorbaIds
132 * were created. If sync is false, then the caller should ensure that the
133 * vamsasDocument is written back to disk to propagate the new VorbaIds.
134 * TODO: ensure that provenance is correct for newly registered objects
135 * @param instream - the XML input stream
136 * @param factory - the SimpleClient's properly configured VorbaId factory to make new references.
137 * @return null or {(Object) VamsasDocument object, (Object) Hashtable of object references, (Object) Boolean(sync) }
139 public static Object[] getVamsasDocument(Reader instream,
140 IVorbaIdFactory factory) {
141 Unmarshaller unmarshaller = new Unmarshaller(instream);
142 unmarshaller.setIDResolver(new IDResolver() {
143 public Object resolve(String id) {
144 System.err.println("Warning - id " + id
145 + " is not found in the VamsasDocument!");
149 Hashtable refbase = new Hashtable();
150 Vector unrefed = new Vector();
151 final Hashtable objrefs = refbase;
152 final IVorbaIdFactory vorbafactory = factory;
153 final Vector unrefedObj = unrefed;
154 unmarshaller.setUnmarshalListener(new VorbaXmlBinder(vorbafactory, unrefedObj, objrefs));
155 // Call the unmarshaller.
157 while (instream.ready()) {
158 Object obj = unmarshaller.unmarshal(instream);
160 if (obj instanceof VamsasDocument) {
161 if (unrefed.size()>0) {
162 sync=false; // document is out of sync - ids have been created.
163 java.util.Iterator newobj = unrefed.listIterator();
164 while (newobj.hasNext()) {
165 object o = (object) newobj.next();
166 // forces registration and id field update.
167 VorbaId id = o.getVorbaId();
168 if (!objrefs.containsKey(id)) {
169 objrefs.put(id.id, o);
171 throw new Error("Serious! Duplicate reference made by vorbaIdFactory!");
175 return new Object[] { obj, objrefs, new Boolean(sync)};
178 } catch (MarshalException e) {
179 // TODO Auto-generated catch block
181 } catch (ValidationException e) {
182 // TODO Auto-generated catch block
184 } catch (IOException e) {
185 // TODO Auto-generated catch block