X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fuk%2Fac%2Fvamsas%2Fclient%2FVorbaXmlBinder.java;h=994e1a186fcf5772612506c161fc13b86fe4fa69;hb=1eea4b639911330e7cd65e17c5421cc584f0d22e;hp=1834e95a8b8b31232f23256681aec0667b2851bd;hpb=63b0b269c333a317ddd018c70a336c4cf839a2ee;p=vamsas.git
diff --git a/src/uk/ac/vamsas/client/VorbaXmlBinder.java b/src/uk/ac/vamsas/client/VorbaXmlBinder.java
index 1834e95..994e1a1 100644
--- a/src/uk/ac/vamsas/client/VorbaXmlBinder.java
+++ b/src/uk/ac/vamsas/client/VorbaXmlBinder.java
@@ -1,242 +1,315 @@
-/**
- *
- */
-package uk.ac.vamsas.client;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.lang.reflect.Field;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Vector;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.exolab.castor.mapping.FieldHandler;
-import org.exolab.castor.mapping.GeneralizedFieldHandler;
-import org.exolab.castor.mapping.ValidityException;
-import org.exolab.castor.xml.IDResolver;
-import org.exolab.castor.xml.MarshalException;
-import org.exolab.castor.xml.MarshalListener;
-import org.exolab.castor.xml.Marshaller;
-import org.exolab.castor.xml.UnmarshalListener;
-import org.exolab.castor.xml.Unmarshaller;
-import org.exolab.castor.xml.ValidationException;
-
-import uk.ac.vamsas.objects.core.VamsasDocument;
-/**
- * Implements the Vamsas Vobject ID machinery for translating
- * between non-volatile XML IDs and Vobject references. Use the
- * marshalling and unmarshalling methods in this class in order
- * to add automatically computed values for required fields in objects,
- * so as to avoid validation exceptions when marshalling new objects
- * into the vamsas document.
- */
-public class VorbaXmlBinder implements UnmarshalListener {
- private static Log log = LogFactory.getLog(VorbaXmlBinder.class);
- private final IVorbaIdFactory vorbafactory;
-
- private final Vector obj;
- private final Hashtable oldobjhashes;
- private final Hashtable objrefs;
- private final Vector updatedobjs;
-
- public VorbaXmlBinder(IVorbaIdFactory vorbafactory, Vector obj, Hashtable objrefs, Hashtable oldobjhashes, Vector updatedobjs) {
- this.vorbafactory = vorbafactory;
- this.obj = obj;
- this.objrefs = objrefs;
- this.oldobjhashes = oldobjhashes;
- this.updatedobjs = updatedobjs;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.exolab.castor.xml.UnmarshalListener#attributesProcessed(java.lang.Object)
- */
- public void attributesProcessed(Object object) {
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.exolab.castor.xml.UnmarshalListener#fieldAdded(java.lang.String,
- * java.lang.Object, java.lang.Object)
- */
- public void fieldAdded(String fieldName, Object parent, Object child) {
- if (parent instanceof Vobject && child instanceof Vobject) {
- if (((Vobject) child).V_parent==null) {
- // System.err.println("Setting parent of "+fieldName);
- ((Vobject) child).setV_parent((Vobject) parent);
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.exolab.castor.xml.UnmarshalListener#initialized(java.lang.Object)
- */
- public void initialized(Object object) {
- }
-
- /*
- * Check if the object has an 'id' field - if it does, copy the value into
- * the VorbaId field of Vobject, and add the Vobject to the VorbaId hash.
- *
- * @see org.exolab.castor.xml.UnmarshalListener#unmarshalled(java.lang.Object)
- */
- public void unmarshalled(Object newobj) {
- if (newobj instanceof Vobject) {
- Vobject nobj = (Vobject) newobj;
- nobj.set__stored_in_document(true);
- try {
- if (nobj.isRegisterable() && nobj.___id_field!=null) {
- VorbaId nobj_id=null;
- // look for the id field (should be an NCName string)
- nobj.__vorba = vorbafactory;
- // use the Vobject accessor method to avoid unpleasant security exceptions.
- String idstring = nobj.__getInstanceIdField();
- if (idstring!=null) {
- if (idstring.length() > 0) {
- nobj.setVorbaId(VorbaId.newId(idstring));
- if (objrefs.containsKey(nobj_id=nobj.getVorbaId()) && !objrefs.get(nobj.getVorbaId()).equals(nobj)) {
- System.err.println("Serious problem : duplicate id '"+idstring+"' found! expect badness.");
- // TODO: HANDLE duplicate XML ids correctly
- }
- objrefs.put(nobj_id, nobj);
- } else {
- // add to list of objects without a valid vorbaId
- obj.add(nobj);
- }
- } else {
- // TODO: add to list of objects without a valid vorbaId
- obj.add(nobj);
- }
-
- nobj.doHash();
- // check to see if new object was present in old object hash
- if (oldobjhashes.containsKey(nobj.getVorbaId())) {
- Vobjhash oldhash = (Vobjhash) oldobjhashes.get(nobj.getVorbaId());
- if (oldhash.isUpdated(nobj)) {
- // mark the object as updated in this document read.
- nobj.set__updated_since_last_read(true);
- oldobjhashes.put(nobj_id, new Vobjhash(nobj));
- updatedobjs.addElement(nobj);
- }
- }
- }
- } catch (Exception e) {
- return;
- };
-
- }
- }
-
- /**
- * writes the VamsasDocument to the given stream.
- * TODO: ensure that (at least) default provenance entries are written for objects.
- * @param outstream
- * @param vorba valid VorbaIdFactory to construct any missing IDs
- * @param doc
- * @throws IOException
- * @throws MarshalException
- * @throws ValidationException
- */
- public static void putVamsasDocument(PrintWriter outstream, VorbaIdFactory vorba, VamsasDocument doc)
- throws IOException, MarshalException, ValidationException {
- // Ensure references
- if (vorba==null)
- throw new Error("Null VorbaIdFactory Parameter");
- if (doc.__vorba==null)
- doc.__vorba = vorba;
- doc.__ensure_instance_ids(); // this may take a while. Do we allow for cyclic references ?
- doc.marshal(outstream);
-
- }
- /**
- * creates new VorbaId references where necessary for newly unmarshalled objects
- * @param unrefed
- * @param objrefs
- * @return false if any new object references were made
- */
- private static boolean ensure_references(Vector unrefed, Hashtable objrefs) {
- boolean sync=true;
- if (unrefed.size()>0) {
- sync=false; // document is out of sync - ids have been created.
- java.util.Iterator newobj = unrefed.listIterator();
- while (newobj.hasNext()) {
- Vobject o = (Vobject) newobj.next();
- // forces registration and id field update.
- VorbaId id = o.getVorbaId();
- if (!objrefs.containsKey(id)) {
- objrefs.put(id, o);
- } else {
- if (!objrefs.get(id).equals(o))
- throw new Error("Serious! Duplicate reference made by vorbaIdFactory!");
- }
- }
- }
- return sync;
- }
- /**
- * Unmarshals a vamsasDocument Vobject from a stream, registers
- * unregistered objects, records existing VorbaIds, and completes
- * the uk.ac.vamsas.client.Vobject housekeeping fields.
- * For a valid unmarshalling, the array of returned objects also includes
- * a sync parameter which is true if new VorbaIds
- * were created. If sync is false, then the caller should ensure that the
- * vamsasDocument is written back to disk to propagate the new VorbaIds.
- * TODO: ensure that provenance is correct for newly registered objects
- * as getVamsasObjects but will detect updated objects based on differing hash values
- * obtained from the VorbaIdFactory's VorbaId, Vobject.get__last_Hash() pairs (if any)
- * @param instream - the XML input stream
- * @param factory - the SimpleClient's properly configured VorbaId factory to make new references.
- * @param root the root element's uk.ac.vamsas.objects.core Vobject.
- * @return null or {(Object) VamsasDocument Vobject, (Object) Hashtable of Vobject references, (Object) Boolean(sync), (Object) Vector of updated objects in document }
- */
- public static Object[] getVamsasObjects(Reader instream,
- VorbaIdFactory factory, Vobject root) {
- Unmarshaller unmarshaller = new Unmarshaller(root);
- unmarshaller.setIDResolver(new IDResolver() {
- public Object resolve(String id) {
- VorbaXmlBinder.log.warn("Warning - id " + id
- + " is not found in the Vamsas XML!");
- return null;
- }
- });
- final Hashtable objrefs = new Hashtable();
- if (factory.extanthashv==null)
- factory.extanthashv=new Hashtable();
- final Hashtable oobjhashes=factory.extanthashv;
- final VorbaIdFactory vorbafactory = factory;
- final Vector unrefedObj = new Vector();
- final Vector updatedObj = new Vector();
- unmarshaller.setUnmarshalListener(new VorbaXmlBinder(vorbafactory, unrefedObj, objrefs, oobjhashes, updatedObj));
- // Call the unmarshaller.
- try {
- while (instream.ready()) {
- // TODO: mark objects in oobjhash prior to unmarshalling, to detect when objects have been lost through an update.
- //tohere
- Object obj = unmarshaller.unmarshal(instream);
- boolean sync=ensure_references(unrefedObj, objrefs);
- if (!(obj instanceof Vobject))
- return null;
- vorbafactory.setNewIdHash(objrefs); // update the Document IO Handler's set of vorbaId<>Object bindings.
- return new Object[] { obj, objrefs, new Boolean(sync),updatedObj};
- }
- } catch (MarshalException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ValidationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
-}
\ No newline at end of file
+/*
+ * This file is part of the Vamsas Client version 0.2.
+ * Copyright 2010 by Jim Procter, Iain Milne, Pierre Marguerite,
+ * Andrew Waterhouse and Dominik Lindner.
+ *
+ * Earlier versions have also been incorporated into Jalview version 2.4
+ * since 2008, and TOPALi version 2 since 2007.
+ *
+ * The Vamsas Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Vamsas Client is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Vamsas Client. If not, see .
+ */
+package uk.ac.vamsas.client;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.exolab.castor.mapping.FieldHandler;
+import org.exolab.castor.mapping.GeneralizedFieldHandler;
+import org.exolab.castor.mapping.ValidityException;
+import org.exolab.castor.xml.IDResolver;
+import org.exolab.castor.xml.MarshalException;
+import org.exolab.castor.xml.MarshalListener;
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.UnmarshalListener;
+import org.exolab.castor.xml.Unmarshaller;
+import org.exolab.castor.xml.ValidationException;
+
+import uk.ac.vamsas.objects.core.VamsasDocument;
+
+/**
+ * Implements the Vamsas Vobject ID machinery for translating between
+ * non-volatile XML IDs and Vobject references. Use the marshalling and
+ * unmarshalling methods in this class in order to add automatically computed
+ * values for required fields in objects, so as to avoid validation exceptions
+ * when marshalling new objects into the vamsas document.
+ */
+public class VorbaXmlBinder implements UnmarshalListener {
+ private static Log log = LogFactory.getLog(VorbaXmlBinder.class);
+
+ private final IVorbaIdFactory vorbafactory;
+
+ private final Vector obj;
+
+ private final Hashtable oldobjhashes;
+
+ private final Hashtable objrefs;
+
+ private final Vector updatedobjs; // not yet used elswhere ?
+
+ public VorbaXmlBinder(IVorbaIdFactory vorbafactory2, Vector unrefedObj,
+ Hashtable objrefs2, Hashtable oldobjhashes, Vector updatedObj) {
+ this.vorbafactory = vorbafactory2;
+ this.obj = unrefedObj;
+ this.objrefs = objrefs2;
+ this.oldobjhashes = oldobjhashes;
+ this.updatedobjs = updatedObj;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.exolab.castor.xml.UnmarshalListener#attributesProcessed(java.lang.Object
+ * )
+ */
+ public void attributesProcessed(Object object) {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.exolab.castor.xml.UnmarshalListener#fieldAdded(java.lang.String,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void fieldAdded(String fieldName, Object parent, Object child) {
+ if (parent instanceof Vobject && child instanceof Vobject) {
+ if (((Vobject) child).V_parent == null) {
+ // System.err.println("Setting parent of "+fieldName);
+ ((Vobject) child).setV_parent((Vobject) parent);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.exolab.castor.xml.UnmarshalListener#initialized(java.lang.Object)
+ */
+ public void initialized(Object object) {
+ if (object instanceof Vobject) {
+ Vobject nobj = (Vobject) object;
+ }
+ }
+
+ /*
+ * Check if the object has an 'id' field - if it does, copy the value into the
+ * VorbaId field of Vobject, and add the Vobject to the VorbaId hash.
+ *
+ * @see org.exolab.castor.xml.UnmarshalListener#unmarshalled(java.lang.Object)
+ */
+ public void unmarshalled(Object newobj) {
+ if (newobj instanceof Vobject) {
+ Vobject nobj = (Vobject) newobj;
+ nobj.set__stored_in_document(true);
+ try {
+ if (nobj.isRegisterable() && nobj.___id_field != null) {
+ VorbaId nobj_id = null;
+ // look for the id field (should be an NCName string)
+ nobj.__vorba = vorbafactory;
+ // use the Vobject accessor method to avoid unpleasant security
+ // exceptions.
+ String idstring = nobj.__getInstanceIdField();
+ if (idstring != null) {
+ if (idstring.length() > 0) {
+ nobj.setVorbaId(VorbaId.newId(idstring));
+ nobj_id = nobj.getVorbaId();
+ if (objrefs.containsKey(nobj_id)
+ && !objrefs.get(nobj_id).equals(nobj)) {
+ System.err.println("Serious problem : duplicate id '"
+ + idstring + "' found! expect badness.");
+ // TODO: HANDLE duplicate XML ids correctly
+ }
+ objrefs.put(nobj_id, nobj);
+ } else {
+ // add to list of objects without a valid vorbaId
+ obj.add(nobj);
+ }
+ } else {
+ // TODO: add to list of objects without a valid vorbaId
+ obj.add(nobj);
+ }
+ nobj.doHash(); // updates detected by comparing with last hash when
+ // marshalling
+ // check to see if new object was present in old object hash
+ if (nobj_id != null) {
+ if (oldobjhashes.containsKey(nobj_id)) {
+ Vobjhash oldhash = (Vobjhash) oldobjhashes.get(nobj_id);
+ if (oldhash.isUpdated(nobj)) {
+ // mark the object as updated in this document read.
+ nobj.set__updated_since_last_read(true);
+ updatedobjs.addElement(nobj);
+ }
+ } else {
+ // object has no entry in the oldhashvalue list but
+ // there is a valid vorbaId so
+ nobj.set__added_since_last_read(true);
+ }
+ // and record the just-unmarshalled hash value
+ oldobjhashes.put(nobj_id, new Vobjhash(nobj));
+ } else {
+ // for objects yet to get a valid vorba_id
+ nobj.set__added_since_last_read(true);
+ }
+ }
+
+ } catch (Exception e) {
+ return;
+ }
+ ;
+
+ }
+ }
+
+ /**
+ * writes the VamsasDocument to the given stream. TODO: ensure that (at least)
+ * default provenance entries are written for objects.
+ *
+ * @param outstream
+ * @param vorba
+ * valid VorbaIdFactory to construct any missing IDs
+ * @param doc
+ * @throws IOException
+ * @throws MarshalException
+ * @throws ValidationException
+ */
+ public static void putVamsasDocument(PrintWriter outstream,
+ VorbaIdFactory vorba, VamsasDocument doc) throws IOException,
+ MarshalException, ValidationException {
+ // Ensure references
+ if (vorba == null)
+ throw new Error("Null VorbaIdFactory Parameter");
+ if (doc.__vorba == null)
+ doc.__vorba = vorba;
+ doc.__ensure_instance_ids(); // this may take a while. Do we allow for
+ // cyclic references ?
+ Marshaller mshl = new Marshaller(outstream);
+ mshl.marshal(doc);
+
+ }
+
+ /**
+ * creates new VorbaId references where necessary for newly unmarshalled
+ * objects
+ *
+ * @param unrefed
+ * @param objrefs
+ * @return false if any new object references were made
+ */
+ private static boolean ensure_references(Vector unrefed, Hashtable objrefs) {
+ boolean sync = true;
+ if (unrefed.size() > 0) {
+ sync = false; // document is out of sync - ids have been created.
+ java.util.Iterator newobj = unrefed.listIterator();
+ while (newobj.hasNext()) {
+ Vobject o = (Vobject) newobj.next();
+ // forces registration and id field update.
+ VorbaId id = o.getVorbaId();
+ if (!objrefs.containsKey(id)) {
+ objrefs.put(id, o);
+ } else {
+ if (!objrefs.get(id).equals(o))
+ throw new Error(
+ "Serious! Duplicate reference made by vorbaIdFactory!");
+ }
+ }
+ }
+ return sync;
+ }
+
+ /**
+ * Unmarshals a vamsasDocument Vobject from a stream, registers unregistered
+ * objects, records existing VorbaIds, and completes the
+ * uk.ac.vamsas.client.Vobject housekeeping fields. For a valid unmarshalling,
+ * the array of returned objects also includes a sync
+ * parameter which is true if new VorbaIds were created. If sync is false,
+ * then the caller should ensure that the vamsasDocument is written back to
+ * disk to propagate the new VorbaIds. TODO: ensure that provenance is correct
+ * for newly registered objects as getVamsasObjects but will detect updated
+ * objects based on differing hash values obtained from the VorbaIdFactory's
+ * VorbaId, Vobject.get__last_Hash() pairs (if any)
+ *
+ * @param instream
+ * - the XML input stream
+ * @param factory
+ * - the SimpleClient's properly configured VorbaId factory to make
+ * new references.
+ * @param root
+ * the root element's uk.ac.vamsas.objects.core Vobject.
+ * @return null or {(Object) VamsasDocument Vobject, (Object) Hashtable of
+ * Vobject references, (Object) Boolean(sync), (Object) Vector of
+ * updated objects in document }
+ */
+ public static Object[] getVamsasObjects(Reader instream,
+ VorbaIdFactory factory, Vobject root) {
+ Unmarshaller unmarshaller = new Unmarshaller(root);
+ final VorbaIdFactory ourfactory = factory;
+ unmarshaller.setIDResolver(new IDResolver() {
+ public Object resolve(String id) {
+ if (ourfactory.warnUnresolved) {
+ // TODO: allow for external ID resolution
+ VorbaXmlBinder.log
+ .warn("Warning - id "
+ + id
+ + " is not found in the Vamsas XML! (TODO: Ignore if this is a forward reference!)");
+ }
+ return null;
+ }
+ });
+ final Hashtable objrefs = new Hashtable();
+ if (factory.extanthashv == null)
+ factory.extanthashv = new Hashtable();
+ final Hashtable oobjhashes = factory.extanthashv;
+ final VorbaIdFactory vorbafactory = factory;
+ final Vector unrefedObj = new Vector();
+ final Vector updatedObj = new Vector();
+ unmarshaller.setUnmarshalListener(new VorbaXmlBinder(vorbafactory,
+ unrefedObj, objrefs, oobjhashes, updatedObj));
+ // Call the unmarshaller.
+ try {
+ while (instream.ready()) {
+ // TODO: mark objects in oobjhash prior to unmarshalling, to detect when
+ // objects have been lost through an update.
+ // tohere
+ factory.warnUnresolved = false;
+ Object obj = unmarshaller.unmarshal(instream);
+ factory.warnUnresolved = true;
+ boolean sync = ensure_references(unrefedObj, objrefs);
+ if (!(obj instanceof Vobject))
+ return null;
+ vorbafactory.setNewIdHash(objrefs); // update the Document IO Handler's
+ // set of vorbaId<>Object bindings.
+ return new Object[] { obj, objrefs, new Boolean(sync), updatedObj };
+ }
+ } catch (MarshalException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (ValidationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+}