/* * This file is part of the Vamsas Client version 0.1. * Copyright 2009 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.test.simpleclient; import java.util.Hashtable; import java.util.Vector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import uk.ac.vamsas.client.IClientAppdata; import uk.ac.vamsas.client.Vobject; import uk.ac.vamsas.client.VorbaId; import uk.ac.vamsas.client.simpleclient.ClientDocument; import uk.ac.vamsas.client.simpleclient.VamsasArchive; import uk.ac.vamsas.client.simpleclient.VamsasArchiveReader; import uk.ac.vamsas.objects.core.Entry; import uk.ac.vamsas.objects.core.VAMSAS; import uk.ac.vamsas.objects.core.VamsasDocument; import uk.ac.vamsas.objects.utils.ProvenanceStuff; // simple holder to pass to client. public class ClientDoc extends uk.ac.vamsas.client.ClientDocument { /* * (non-Javadoc) * * @see uk.ac.vamsas.client.IClientDocument#getClientAppdata() */ public IClientAppdata getClientAppdata() { throw new Error( "Appdata access is not implemented in the test.simpleclient.ClientDoc instance."); // TODO // Auto-generated // method // stub } protected boolean isModified = false; private Log log = LogFactory.getLog(ClientDoc.class); protected VamsasDocument doc; public uk.ac.vamsas.objects.core.VAMSAS[] _VamsasRoots; protected VamsasArchive iohandler = null; protected VamsasArchiveReader reader = null; private String user = null; private String app = null; /** * @param doc * @param iohandler * @param reader * @param app * @param user */ public ClientDoc(VamsasDocument doc, VamsasArchive iohandler, VamsasArchiveReader reader, String app, String user, Hashtable objrefs) { super(objrefs, (iohandler != null) ? iohandler.getVorba() : null); this.doc = doc; this.iohandler = iohandler; this.reader = reader; this.app = app; this.user = user; this.objrefs = objrefs; _VamsasRoots = doc.getVAMSAS(); } // AppDataOutputStream appd; // AppDataOutputStream userd; /* * (non-Javadoc) * * @see java.lang.Object#finalize() */ protected Entry getProvenanceEntry(String action) { // VAMSAS: modify schema to allow referencing of user field (plus other // issues, ClientUrn field, machine readable action, input parameters, // additional data generated notes Entry prov = ProvenanceStuff.newProvenanceEntry(app, user, action); return prov; } public VAMSAS[] getVamsasRoots() { if (doc == null) { log.debug("Null document for getVamsasRoots(), returning null"); return null; } if (iohandler == null) { // LATER: decide on read-only status of ClientDocument object log.warn("getVamsasRoots() called on possibly read-only document."); } if (_VamsasRoots != null) return _VamsasRoots; VAMSAS[] roots = doc.getVAMSAS(); if (roots == null) { // Make a new one to return to client to get filled. _VamsasRoots = new VAMSAS[] { new VAMSAS() }; // Do provenance now. just in case. doc.getProvenance().addEntry( getProvenanceEntry("Created new document root [id=" + _VamsasRoots[0].getId() + "]")); doc.addVAMSAS(_VamsasRoots[0]); } else { _VamsasRoots = new VAMSAS[roots.length]; for (int r = 0; r < roots.length; r++) _VamsasRoots[r] = roots[r]; } return _VamsasRoots; } private int _contains(VAMSAS root, VAMSAS[] docRoots) { if (root == null) return -1; if (docRoots == null || docRoots.length == 0) return -1; VorbaId r_id = root.getVorbaId(); for (int i = 0, j = docRoots.length; i < j; i++) { VorbaId n_id = null; if (docRoots[i] == root || (docRoots[i] != null && (n_id = docRoots[i].getVorbaId()) != null && n_id .equals(r_id))) return i; } return -1; } /** * verify that newr version is really an intact version of the * * @param newVersion * (may be modified) * @param oldVersion * @return true if newVersion is a valid root that preserves original * references */ private boolean isValidUpdate(VAMSAS newVersion, final VAMSAS oldVersion) { // ideal - this cascades down the two structures, ensuring that all ID'd // objects in one are present in the other. if (oldVersion == newVersion) { // may be a virgin root element. if (!newVersion.isRegistered()) iohandler.getVorba().makeVorbaId(newVersion); // Should retrieve original version and compare - unless local hashes can // be used to determine if resultSet has been truncated. // just do internal validation for moment. if (newVersion.isValid()) return true; return false; } else { // redundant ? if (oldVersion.is__stored_in_document()) if (!newVersion.isRegistered()) iohandler.getVorba().makeVorbaId(newVersion); if (newVersion.isValid()) return true; } return false; } /** * /** merge old and new root vectors * * @param newr * This array may be written to * @param original * @param the * client document (usually this) which this root set belongs to. * @return merged vector of vamsas roots */ private VAMSAS[] _combineRoots(VAMSAS[] newr, final VAMSAS[] original, ClientDoc modflag) { Vector rts = new Vector(); boolean modified = false; for (int i = 0, j = original.length; i < j; i++) { int k = _contains(original[i], newr); if (k > -1) { if (isValidUpdate(newr[k], original[i])) { modified = true; rts.add(newr[k]); newr[k] = null; } else { // LATER: try harder to merge ducument roots. log.warn("Couldn't merge new VAMSAS root " + newr[k].getId()); newr[k] = null; // LATER: this means we ignore mangled roots. NOT GOOD } } else { // add in order. rts.add(original[i]); } } // add remaining (new) roots for (int i = 0, j = newr.length; i < j; i++) { if (newr[i] != null) { rts.add(newr[i]); modified = true; } } newr = new VAMSAS[rts.size()]; for (int i = 0, j = rts.size(); i < j; i++) newr[i] = (VAMSAS) rts.get(i); if (modflag != null) modflag.isModified = modified; return newr; } /** * update the document with new roots. LATER: decide: this affects the next * call to getVamsasRoots() * * @see org.vamsas.IClientDocument.setVamsasRoots */ public void setVamsasRoots(VAMSAS[] newroots) { if (doc == null) { log.debug("setVamsasRoots called on null document."); return; } VAMSAS[] newr; if (newroots == null) { log.debug("setVamsasRoots(null) - do nothing."); return; } // are we dealing with same array ? if (_VamsasRoots != newroots) { // merge roots into local version. newr = new VAMSAS[newroots.length]; for (int i = 0; i < newr.length; i++) newr[i] = newroots[i]; newr = _combineRoots(newr, _VamsasRoots, this); } else { newr = new VAMSAS[_VamsasRoots.length]; for (int i = 0; i < newr.length; i++) newr[i] = _VamsasRoots[i]; } // actually compare with document root set for final combination (to ensure // nothing is lost) _VamsasRoots = _combineRoots(newr, doc.getVAMSAS(), this); } /* * (non-Javadoc) LATER: decide: this affects the next call to getVamsasRoots() * * @see * uk.ac.vamsas.client.IClientDocument#addVamsasRoot(uk.ac.vamsas.objects. * core.VAMSAS) */ public void addVamsasRoot(VAMSAS newroot) { if (doc == null) { log.debug("addVamsasRoots called on null document."); return; } VAMSAS[] newroots = _combineRoots(new VAMSAS[] { newroot }, _VamsasRoots, this); _VamsasRoots = newroots; } public VamsasArchiveReader getReader() { return reader; } private void _finalize() { log.debug("finalizing clientDoc"); if (doc != null) { doc = null; } if (_VamsasRoots != null) { for (int i = 0; i < _VamsasRoots.length; i++) _VamsasRoots[i] = null; _VamsasRoots = null; } if (reader != null) { log.debug("Closing and removing reader reference"); reader.close(); reader = null; } if (iohandler != null) { log.debug("Removing ioHandler reference."); iohandler.cancelArchive(); iohandler = null; } } protected void finalize() throws Throwable { _finalize(); super.finalize(); } private java.util.Hashtable objrefs = null; public VorbaId[] registerObjects(Vobject[] unregistered) { if (doc == null) { log.warn("registerObjects[] called on null document."); return null; } if (objrefs == null) { log.warn("registerObjects[] called for null objrefs hasharray."); return null; } if (unregistered != null) { VorbaId ids[] = new VorbaId[unregistered.length]; for (int i = 0, k = unregistered.length; i < k; i++) if (unregistered[i] != null) { log.warn("Null Vobject passed to registerObject[] at position " + i); return null; } else { ids[i] = registerObject(unregistered[i]); } log.debug("Registered " + unregistered.length + " objects - total of " + objrefs.size() + " ids."); return ids; } return null; } /* * (non-Javadoc) * * @see * uk.ac.vamsas.client.IClientDocument#registerObject(uk.ac.vamsas.client. * Vobject) */ public VorbaId registerObject(Vobject unregistered) { if (doc == null) { log.warn("registerObjects called on null document."); return null; } if (objrefs == null) { log.warn("registerObjects called for null objrefs hasharray."); return null; } if (iohandler == null) { log.warn("registerObjects called for read only document."); return null; } if (unregistered != null) { VorbaId id = this._registerObject(unregistered); log.debug("Registered object - total of " + objrefs.size() + " ids."); return id; } log.warn("Null Vobject passed to registerObject."); return null; } /* * (non-Javadoc) * * @see * uk.ac.vamsas.client.IClientDocument#getObject(uk.ac.vamsas.client.VorbaId) */ public Vobject getObject(VorbaId id) { if (objrefs == null) { log.debug("getObject called on null objrefs list."); return null; } if (objrefs.containsKey(id.getId())) return (Vobject) objrefs.get(id.getId()); log.debug("Returning null Vobject reference for id " + id.getId()); return null; } /* * (non-Javadoc) * * @see * uk.ac.vamsas.client.IClientDocument#getObjects(uk.ac.vamsas.client.VorbaId * []) */ public Vobject[] getObjects(VorbaId[] ids) { if (objrefs == null) { log.debug("getObject[] called on null objrefs list."); return null; } Vobject[] vo = new Vobject[ids.length]; for (int i = 0, j = ids.length; i < j; i++) if (objrefs.containsKey(ids[i])) vo[i] = (Vobject) objrefs.get(ids[i]); else log.debug("Returning null Vobject reference for id " + ids[i].getId()); return vo; } protected void updateDocumentRoots() { if (doc == null) { log .error("updateDocumentRoots called on null document. Probably an implementation error."); return; } if (isModified) { if (_VamsasRoots != null) { doc.setVAMSAS(_VamsasRoots); _VamsasRoots = null; } } } /** * tell vamsas client to close the document and reset the object. Once closed, * nothing can be done with the object. * */ public void closeDoc() { if (doc != null) { log.debug("Closing open document."); _finalize(); } else { log.warn("Ignoring closeDoc on invalid document."); } } }