--- /dev/null
+/**
+ *
+ */
+package org.vamsas.test.simpleclient.simpleapp;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Vector;
+import java.util.jar.JarOutputStream;
+
+import javax.swing.JInternalFrame;
+
+import org.vamsas.client.UserHandle;
+import org.vamsas.client.simpleclient.FileWatcher;
+import org.vamsas.client.simpleclient.VamsasArchive;
+import org.vamsas.client.simpleclient.VamsasFile;
+import org.vamsas.objects.core.Entry;
+import org.vamsas.objects.core.VamsasDocument;
+import org.vamsas.test.simpleclient.ArchiveClient;
+import org.vamsas.test.simpleclient.ClientDoc;
+
+/**
+ * @author jimp
+ *
+ */
+public class VamsasClient extends ArchiveClient {
+ org.apache.commons.logging.Log log=org.apache.commons.logging.LogFactory.getLog(VamsasClient.class);
+ /**
+ * create a new vamsas client session from the archive at sessionPath.
+ * @param sessionPath
+ */
+ public VamsasClient(File sessionPath) {
+ super(System.getProperty("user.name"),System.getProperty("host.name"), "SimpleVamsasClientApp","0.1",
+ sessionPath);
+ }
+ /**
+ * Called by gui to read anything from the vamsas session into the apps datamodel
+ * after it has started up.
+ *
+ */
+ public void initial_update() {
+ log.info("Jalview loading the Vamsas Session.");
+ // load in the vamsas archive for the first time
+ ClientDoc cdoc = this.getUpdateable();
+ updateJalview(cdoc);
+ // TODO: flush any new VorbaIds to the document : updateVamsasClient may actually generate new Vamsas Document data in the form of vamsas element ids - these should be written back to the document.
+ //doUpdate(cdoc); // JBPNote: this should flush new VorbaIds but I've not tested it yet.
+ cdoc.closeDoc();
+ // then tell app to update its display based on the datamodel changes.
+ }
+ VamsasClientWatcher watcher=null;
+ /**
+ * Called by app when internal datamodel should exported (syncrhonised outwards) to vamsas document
+ *
+ */
+ public void push_update() {
+
+ watchForChange=false; // this makes any watch(long) loops return.
+ // we should also wait arount for this.WATCH_SLEEP to really make sure the watcher thread has stopped.
+ try {
+ Thread.sleep(WATCH_SLEEP);
+ } catch (Exception e) {
+
+ };
+
+ ClientDoc cdoc = getUpdateable();
+ updateVamsasDocument(cdoc);
+ doUpdate(cdoc);
+ cdoc.closeDoc();
+ cdoc=null;
+ watchForChange=true;
+ startWatcher();
+ }
+ public void end_session() {
+ watchForChange=false; // this makes any watch(long) loops return.
+ // we should also wait arount for this.WATCH_SLEEP to really make sure the watcher thread has stopped.
+ try {
+ Thread.sleep(WATCH_SLEEP);
+ } catch (Exception e) {
+
+ };
+
+ // stop any update/watcher thread.
+ log.info("VamsasClientApplication disconnecting from the Vamsas Session.");
+ }
+ public void updateJalview(ClientDoc cdoc) {
+ ensureVamsasBindings();
+ VamsasDatastore vds = new VamsasDatastore(cdoc, vobj2jv, jv2vobj, baseProvEntry());
+ vds.updateToJalview();
+ }
+ private void ensureVamsasBindings() {
+ if (jv2vobj==null) {
+ jv2vobj = new IdentityHashMap();
+ vobj2jv = new Hashtable();
+ }
+ }
+ /**
+ * App's object binding to VorbaIds
+ */
+ IdentityHashMap jv2vobj = null;
+ Hashtable vobj2jv = null;
+ /**
+ * called with a vamsas document which will be updated with new data from the app
+ * @param doc
+ */
+ public void updateVamsasDocument(ClientDoc doc) {
+ ensureVamsasBindings();
+ VamsasDatastore vds = new VamsasDatastore(doc, vobj2jv, jv2vobj, baseProvEntry());
+ // wander through frames
+ vds.storeVAMSAS(new Object()); // Object is the apps datamodel ;)
+ }
+ /**
+ *
+ * @return a base provenance entry used by the VamsasDatastore object to get attributes from. this isn't particularly elegant either.
+ */
+ private Entry baseProvEntry() {
+ org.vamsas.objects.core.Entry pentry = new org.vamsas.objects.core.Entry();
+ pentry.setUser(this.getProvenanceUser());
+ pentry.setApp(this.getClientHandle().getClientName());
+ pentry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));
+ pentry.setAction("created");
+ return pentry;
+ }
+ protected class VamsasClientWatcher extends Thread implements Runnable {
+ /* (non-Javadoc)
+ * @see java.lang.Thread#run()
+ */
+ VamsasClient client=null;
+ VamsasClientWatcher(VamsasClient client) {
+ this.client = client;
+ }
+ boolean running=false;
+ public void run() {
+ running=true;
+ while (client.watchForChange) {
+ ClientDoc docio = client.watch(0);
+ if (docio!=null) {
+ // VamsasClient GUI bits should be disabled whilst an update is in progress so the user doesn't screw anything up.
+ client.disableGui(true);
+ log.debug("Updating VamsasClient app from changed vamsas document.");
+ client.updateJalview(docio);
+ log.debug("Finished updating from document change.");
+ docio.closeDoc();
+ docio=null;
+ client.disableGui(false);
+ }
+ }
+ running=false;
+
+ }
+
+ }
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ /**
+ * disable (if b is true) or enable (if b is true) the VamsasClient's vamsas session gui bits whilst a document change is being updated to the app.
+ * @param b
+ */
+ public void disableGui(boolean b) {
+ // in jalview, we turn off the VAMSAS Session menu : Desktop.instance.setVamsasUpdate(b);
+ }
+ /**
+ * spawn a new thread to start the VamsasClientWatcher.
+ *
+ */
+ public void startWatcher() {
+ if (watcher==null)
+ watcher=new VamsasClientWatcher(this);
+ Thread thr = new Thread() {
+ public void run() {
+ watcher.start();
+ }
+ };
+ thr.start();
+ }
+
+}
--- /dev/null
+/*\r
+ * VamsasClientSimpleApp - A framework for interoparable Sequence analysis\r
+ * Copyright (C) 2006 VAMSAS\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+package org.vamsas.test.simpleclient.simpleapp;\r
+\r
+import org.vamsas.client.Vobject;\r
+import org.vamsas.client.VorbaId;\r
+import org.vamsas.objects.core.*;\r
+import org.vamsas.objects.utils.DocumentStuff;\r
+import org.vamsas.test.simpleclient.ClientDoc;\r
+\r
+\r
+import java.io.*;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Hashtable;\r
+import java.util.IdentityHashMap;\r
+import java.util.Vector;\r
+import java.util.jar.*;\r
+import org.exolab.castor.xml.*;\r
+import org.exolab.castor.mapping.Mapping;\r
+\r
+/*\r
+ * \r
+ * static {\r
+ * org.exolab.castor.util.LocalConfiguration.getInstance().getProperties().setProperty(\r
+ * "org.exolab.castor.serializer", "org.apache.xml.serialize.XMLSerilazizer"); }\r
+ * \r
+ */\r
+\r
+public class VamsasDatastore {\r
+ org.apache.commons.logging.Log log=org.apache.commons.logging.LogFactory.getLog(VamsasDatastore.class);\r
+ Entry provEntry = null;\r
+\r
+\r
+ org.exolab.castor.types.Date date = new org.exolab.castor.types.Date(\r
+ new java.util.Date());\r
+\r
+ ClientDoc cdoc;\r
+\r
+ Hashtable vobj2jv;\r
+\r
+ IdentityHashMap jv2vobj;\r
+\r
+ public VamsasDatastore(ClientDoc cdoc, Hashtable vobj2jv,\r
+ IdentityHashMap jv2vobj, Entry provEntry) {\r
+ this.cdoc = cdoc;\r
+ this.vobj2jv = vobj2jv;\r
+ this.jv2vobj = jv2vobj;\r
+ this.provEntry = provEntry;\r
+ }\r
+\r
+ /*\r
+ * public void storeJalview(String file, AlignFrame af) { try { // 1. Load the\r
+ * mapping information from the file Mapping map = new\r
+ * Mapping(getClass().getClassLoader()); java.net.URL url =\r
+ * getClass().getResource("/jalview_mapping.xml"); map.loadMapping(url); // 2.\r
+ * Unmarshal the data // Unmarshaller unmar = new Unmarshaller();\r
+ * //unmar.setIgnoreExtraElements(true); //unmar.setMapping(map); // uni =\r
+ * (UniprotFile) unmar.unmarshal(new FileReader(file)); // 3. marshal the data\r
+ * with the total price back and print the XML in the console Marshaller\r
+ * marshaller = new Marshaller( new FileWriter(file) );\r
+ * \r
+ * marshaller.setMapping(map); marshaller.marshal(af); } catch (Exception e) {\r
+ * e.printStackTrace(); } }\r
+ * \r
+ * \r
+ */\r
+ /**\r
+ * @return the Vobject bound to Jalview datamodel object\r
+ */\r
+ protected Vobject getjv2vObj(Object jvobj) {\r
+ if (jv2vobj.containsKey(jvobj))\r
+ return cdoc.getObject((VorbaId) jv2vobj.get(jvobj));\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @param vobj\r
+ * @return Jalview datamodel object bound to the vamsas document object\r
+ */\r
+ protected Object getvObj2jv(org.vamsas.client.Vobject vobj) {\r
+ VorbaId id = vobj.getVorbaId();\r
+ if (id == null)\r
+ {\r
+ id = cdoc.registerObject(vobj);\r
+ log\r
+ .debug("Registering new object and returning null for getvObj2jv");\r
+ return null;\r
+ }\r
+ if (vobj2jv.containsKey(vobj.getVorbaId()))\r
+ return vobj2jv.get(vobj.getVorbaId());\r
+ return null;\r
+ }\r
+\r
+ protected void bindjvvobj(Object jvobj, org.vamsas.client.Vobject vobj) {\r
+ VorbaId id = vobj.getVorbaId();\r
+ if (id == null)\r
+ {\r
+ id = cdoc.registerObject(vobj);\r
+ if (id==null || vobj.getVorbaId()==null)\r
+ log.error("Failed to get id for "+(vobj.isRegisterable() ? "registerable" : "unregisterable") +" object "+vobj);\r
+ }\r
+ if (vobj2jv.containsKey(vobj.getVorbaId()) || jv2vobj.containsKey(jvobj))\r
+ {\r
+ log.error("Duplicate object binding! "+vobj+" id " +vobj.getVorbaId().getId()+" to "+jvobj);\r
+ }\r
+ else\r
+ {\r
+ vobj2jv.put(vobj.getVorbaId(), jvobj);// JBPNote - better implementing a\r
+ // hybrid invertible hash.\r
+ jv2vobj.put(jvobj, vobj.getVorbaId());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * put the alignment viewed by AlignViewport into cdoc.\r
+ * \r
+ * @param av\r
+ */\r
+ public void storeVAMSAS(Object fromAppsDatamodel) {\r
+ boolean nw = false;\r
+ VAMSAS root = null; // will be resolved based on Dataset Parent.\r
+ DataSet dataset = (DataSet) getjv2vObj(fromAppsDatamodel);\r
+ if (dataset == null)\r
+ {\r
+ root = cdoc.getVamsasRoots()[0]; // default vamsas root for modifying.\r
+ dataset = new DataSet();\r
+ root.addDataSet(dataset);\r
+ bindjvvobj(fromAppsDatamodel, dataset);\r
+ dataset.setProvenance(dummyProvenance());\r
+ dataset.getProvenance().addEntry(provEntry);\r
+ nw = true;\r
+ } else {\r
+ root = (VAMSAS) dataset.getV_parent();\r
+ }\r
+ // etc...\r
+ }\r
+\r
+ private Property newProperty(String name, String type, String content) {\r
+ Property vProperty=new Property();\r
+ vProperty.setName(name);\r
+ if (type!=null)\r
+ vProperty.setType(type);\r
+ vProperty.setContent(content);\r
+ return vProperty;\r
+ }\r
+\r
+ /**\r
+ * get start<end range of segment, adjusting for inclusivity flag and\r
+ * polarity.\r
+ * \r
+ * @param visSeg\r
+ * @param ensureDirection when true - always ensure start is less than end.\r
+ * @return int[] { start, end, direction} where direction==1 for range running from end to start.\r
+ */\r
+ private int[] getSegRange(Seg visSeg, boolean ensureDirection) {\r
+ boolean incl = visSeg.getInclusive();\r
+ // adjust for inclusive flag.\r
+ int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of\r
+ // region.\r
+ int start = visSeg.getStart() + (incl ? 0 : pol);\r
+ int end = visSeg.getEnd() + (incl ? 0 : -pol);\r
+ if (ensureDirection && pol==-1)\r
+ {\r
+ // jalview doesn't deal with inverted ranges, yet.\r
+ int t = end;\r
+ end = start;\r
+ start = t;\r
+ }\r
+ return new int[] { start, end, pol<0 ? 1 : 0 };\r
+ }\r
+\r
+ public void updateToJalview() {\r
+ VAMSAS _roots[] = cdoc.getVamsasRoots();\r
+\r
+ for (int _root = 0; _root<_roots.length; _root++) {\r
+ VAMSAS root = _roots[_root];\r
+ boolean newds=false;\r
+ for (int _ds=0,_nds=root.getDataSetCount(); _ds<_nds; _ds++) {\r
+ // ///////////////////////////////////\r
+ // ///LOAD DATASET\r
+ DataSet dataset = root.getDataSet(_ds);\r
+ int i, iSize = dataset.getSequenceCount();\r
+ Vector dsseqs;\r
+ Object appsdataset = (Object) getvObj2jv(dataset);\r
+ int jremain=0;\r
+ if (appsdataset==null) {\r
+ log.debug("Initialising new dataset fields");\r
+ newds=true;\r
+ dsseqs=new Vector();\r
+ } else {\r
+ log.debug("Update dataset from vamsas dataset.");\r
+ }\r
+ // etc for annotations, alignments, trees, etc. \r
+ }\r
+ }\r
+ }\r
+ /**\r
+ * get real bounds of a RangeType's specification. start and end are an\r
+ * inclusive range within which all segments and positions lie.\r
+ * TODO: refactor to vamsas utils\r
+ * @param dseta\r
+ * @return int[] { start, end}\r
+ */\r
+ private int[] getBounds(RangeType dseta) {\r
+ if (dseta != null)\r
+ {\r
+ int[] se = null;\r
+ if (dseta.getSegCount()>0 && dseta.getPosCount()>0)\r
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+ if (dseta.getSegCount() > 0)\r
+ {\r
+ se = getSegRange(dseta.getSeg(0),true);\r
+ for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)\r
+ {\r
+ int nse[] = getSegRange(dseta.getSeg(s), true);\r
+ if (se[0] > nse[0])\r
+ se[0] = nse[0];\r
+ if (se[1] < nse[1])\r
+ se[1] = nse[1];\r
+ }\r
+ }\r
+ if (dseta.getPosCount() > 0)\r
+ {\r
+ // could do a polarity for pos range too. and pass back indication of discontinuities.\r
+ int pos = dseta.getPos(0).getI();\r
+ se = new int[] { pos, pos };\r
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+ {\r
+ pos = dseta.getPos(p).getI();\r
+ if (se[0] > pos)\r
+ se[0] = pos;\r
+ if (se[1] < pos)\r
+ se[1] = pos;\r
+ }\r
+ }\r
+ return se;\r
+ }\r
+ return null;\r
+ }\r
+ /**\r
+ * map from a rangeType's internal frame to the referenced object's coordinate frame.\r
+ * @param dseta\r
+ * @return int [] { ref(pos)...} for all pos in rangeType's frame.\r
+ */\r
+ private int[] getMapping(RangeType dseta) {\r
+ Vector posList=new Vector();\r
+ if (dseta != null)\r
+ {\r
+ int[] se = null;\r
+ if (dseta.getSegCount()>0 && dseta.getPosCount()>0)\r
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+ if (dseta.getSegCount() > 0)\r
+ {\r
+ for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)\r
+ {\r
+ se = getSegRange(dseta.getSeg(s), false);\r
+ int se_end=se[1-se[2]]+(se[2]==0 ? 1 : -1);\r
+ for (int p=se[se[2]]; p!=se_end; p+=se[2]==0 ? 1 : -1 ) {\r
+ posList.add(Integer.valueOf(p));\r
+ }\r
+ }\r
+ } \r
+ else if (dseta.getPosCount() > 0)\r
+ {\r
+ int pos = dseta.getPos(0).getI();\r
+\r
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+ {\r
+ pos = dseta.getPos(p).getI();\r
+ posList.add(Integer.valueOf(pos));\r
+ }\r
+ }\r
+ }\r
+ if (posList!=null && posList.size()>0) {\r
+ int[] range=new int[posList.size()];\r
+ for (int i=0; i<range.length; i++)\r
+ range[i] = ((Integer)posList.elementAt(i)).intValue();\r
+ posList.clear();\r
+ return range;\r
+ }\r
+ return null;\r
+ }\r
+ /**\r
+ * \r
+ * @return default initial provenance list for a VamsasDatastore created vamsas\r
+ * object.\r
+ */\r
+ Provenance dummyProvenance() {\r
+ return dummyProvenance(null);\r
+ }\r
+\r
+ Entry dummyPEntry(String action) {\r
+ Entry entry = new Entry();\r
+ entry.setApp(this.provEntry.getApp());\r
+ if (action != null)\r
+ entry.setAction(action);\r
+ else\r
+ entry.setAction("created.");\r
+ entry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));\r
+ entry.setUser(this.provEntry.getUser());\r
+ return entry;\r
+ }\r
+\r
+ Provenance dummyProvenance(String action) {\r
+ Provenance prov = new Provenance();\r
+ prov.addEntry(dummyPEntry(action));\r
+ return prov;\r
+ }\r
+\r
+ void addProvenance(Provenance p, String action) {\r
+ p.addEntry(dummyPEntry(action));\r
+ }\r
+\r
+}\r