2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 package jalview.io.vamsas;
21 import jalview.bin.Cache;
22 import jalview.datamodel.DBRefEntry;
23 import jalview.gui.TreePanel;
24 import jalview.io.VamsasAppDatastore;
26 import java.util.Enumeration;
27 import java.util.Hashtable;
28 import java.util.IdentityHashMap;
29 import java.util.Vector;
31 import org.apache.commons.logging.Log;
33 import uk.ac.vamsas.client.IClientDocument;
34 import uk.ac.vamsas.client.Vobject;
35 import uk.ac.vamsas.client.VorbaId;
36 import uk.ac.vamsas.objects.core.DbRef;
37 import uk.ac.vamsas.objects.core.Entry;
38 import uk.ac.vamsas.objects.core.Provenance;
39 import uk.ac.vamsas.objects.core.Seg;
42 * Holds all the common machinery for binding objects to vamsas objects
47 public abstract class DatastoreItem
52 Entry provEntry = null;
58 IdentityHashMap jv2vobj;
60 boolean tojalview=false;
64 protected static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(DatastoreItem.class);
66 * note: this is taken verbatim from jalview.io.VamsasAppDatastore
67 * @return the Vobject bound to Jalview datamodel object
69 protected Vobject getjv2vObj(Object jvobj)
71 if (jv2vobj.containsKey(jvobj))
73 return cdoc.getObject((VorbaId) jv2vobj.get(jvobj));
75 if (Cache.log.isDebugEnabled())
77 Cache.log.debug("Returning null VorbaID binding for jalview object "
86 * @return Jalview datamodel object bound to the vamsas document object
88 protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj)
92 VorbaId id = vobj.getVorbaId();
95 id = cdoc.registerObject(vobj);
97 .debug("Registering new object and returning null for getvObj2jv");
100 if (vobj2jv.containsKey(vobj.getVorbaId()))
102 return vobj2jv.get(vobj.getVorbaId());
108 * note: this is taken verbatim from jalview.io.VamsasAppDatastore
109 * with added call to updateRegistryEntry
113 protected void bindjvvobj(Object jvobj, uk.ac.vamsas.client.Vobject vobj)
115 VorbaId id = vobj.getVorbaId();
118 id = cdoc.registerObject(vobj);
119 if (id == null || vobj.getVorbaId() == null
120 || cdoc.getObject(id) != vobj)
122 Cache.log.error("Failed to get id for "
123 + (vobj.isRegisterable() ? "registerable"
124 : "unregisterable") + " object " + vobj);
127 if (vobj2jv.containsKey(vobj.getVorbaId())
128 && !(vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
131 "Warning? Overwriting existing vamsas id binding for "
132 + vobj.getVorbaId(), new Exception(
133 "Overwriting vamsas id binding."));
135 else if (jv2vobj.containsKey(jvobj)
136 && !((VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
139 "Warning? Overwriting existing jalview object binding for "
140 + jvobj, new Exception(
141 "Overwriting jalview object binding."));
144 * Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id "
145 * +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+"
146 * already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to
149 // we just update the hash's regardless!
150 Cache.log.debug("Binding " + vobj.getVorbaId() + " to " + jvobj);
151 vobj2jv.put(vobj.getVorbaId(), jvobj);
152 // JBPNote - better implementing a hybrid invertible hash.
153 jv2vobj.put(jvobj, vobj.getVorbaId());
154 if (jvobj==this.jvobj || vobj==this.vobj)
156 updateRegistryEntry(jvobj,vobj);
160 * update the vobj and jvobj references and the registry entry for this datastore object
161 * called by bindjvvobj and replacejvobjmapping
163 private void updateRegistryEntry(Object jvobj,Vobject vobj)
165 if (this.jvobj!=null && this.vobj!=null) {
166 Cache.log.debug("updating dsobj registry. ("+this.getClass().getName()+")");
170 dsReg.registerDsObj(this);
174 * replaces oldjvobject with newjvobject in the Jalview Object <> VorbaID
176 * note: originally taken verbatim from jalview.io.VamsasAppDatastore with added call to updateRegistryEntry
178 * @param newjvobject (may be null to forget the oldjvobject's document mapping)
181 protected void replaceJvObjMapping(Object oldjvobject, Object newjvobject)
183 Object vobject = jv2vobj.remove(oldjvobject);
187 "IMPLEMENTATION ERROR: old jalview object is not bound ! ("
188 + oldjvobject + ")");
190 if (newjvobject!=null)
192 jv2vobj.put(newjvobject, vobject);
193 vobj2jv.put(vobject, newjvobject);
194 updateRegistryEntry(newjvobject,(Vobject) vobject);
198 public DatastoreItem()
203 public DatastoreItem(VamsasAppDatastore datastore)
206 initDatastoreItem(datastore);
207 // TODO Auto-generated constructor stub
210 * construct and initialise datastore object and retrieve object bound to vobj2 and validate it against boundType
215 public DatastoreItem(VamsasAppDatastore datastore2, Vobject vobj2, Class boundType)
219 jvobj = getvObj2jv(vobj2);
221 if (jvobj!=null && !(boundType.isAssignableFrom(jvobj.getClass())))
223 throw new Error("Implementation Error: Vamsas Document Class "+vobj.getClass()+" should bind to a "+boundType+" (found a "+jvobj.getClass()+")");
225 dsReg.registerDsObj(this);
228 * construct and initialise datastore object and retrieve document object bound to Jalview object jvobj2 and validate it against boundType
229 * @param datastore2 the datastore
230 * @param jvobj2 the jalview object
231 * @param boundToType - the document object class that the bound object should be assignable from
233 public DatastoreItem(VamsasAppDatastore datastore2, Object jvobj2, Class boundToType)
238 vobj = getjv2vObj(jvobj);
239 if (vobj!=null && !(boundToType.isAssignableFrom(vobj.getClass())))
241 throw new Error("Implementation Error: Jalview Class "+jvobj2.getClass()+" should bind to a "+boundToType+" (found a "+vobj.getClass()+")");
243 dsReg.registerDsObj(this);
246 * create a new vobj to be added to the document
247 * for the jalview object jvobj
248 * (jvobj!=null, vobj==null)
250 public abstract void addToDocument();
252 * handle a conflict where both an existing vobj has been updated
253 * and a local jalview object has been updated. This method
254 * is only called from doSync, when an incoming update from the vamsas
255 * session conflicts with local modifications made by the Jalview user.
256 * (jvobj!=null, vobj!=null)
258 public abstract void conflict();
260 * update an existing vobj in the document with the data and settings from jvobj
261 * (jvobj!=null, vobj!=null)
263 public abstract void updateToDoc();
265 * update the local jalview object with the data from an existing vobj in the document
266 * (jvobj!=null, vobj!=null)
268 public abstract void updateFromDoc();
270 * create a new local jvobj bound to the vobj in the document.
271 * (jvobj==null, vobj!=null)
273 public abstract void addFromDocument();
274 boolean addtodoc=false, conflicted=false,updated=false,addfromdoc=false,success=false;
276 private boolean updatedtodoc;
278 private boolean updatedfromdoc;
280 * Sync jalview to document. Enact addToDocument, conflict or update dependent on
281 * existence of a vobj bound to the local jvobj.
283 protected void doSync()
285 dsReg.registerDsObj(this);
288 log.debug("adding new vobject to document.");
294 if (vobj.isUpdated())
296 log.debug("Handling update conflict for existing bound vobject.");
302 log.debug("updating existing vobject in document.");
307 // no exceptions were encountered...
311 * Update jalview from document. enact addFromDocument if no local jvobj exists, or update iff jvobj
312 * exists and the vobj.isUpdated() flag is set.
314 protected void doJvUpdate()
316 dsReg.registerDsObj(this);
319 log.debug("adding new vobject to Jalview from Document");
325 if (vobj.isUpdated())
327 log.debug("updating Jalview from existing bound vObject");
334 VamsasAppDatastore datastore = null;
336 * object in vamsas document
338 protected Vobject vobj = null;
340 * local jalview object
342 protected Object jvobj = null;
344 protected DatastoreRegistry dsReg;
346 public void initDatastoreItem(VamsasAppDatastore ds)
349 dsReg = ds.getDatastoreRegisty();
350 initDatastoreItem(ds.getProvEntry(), ds.getClientDocument(), ds
351 .getVamsasObjectBinding(), ds.getJvObjectBinding());
354 private void initDatastoreItem(Entry provEntry, IClientDocument cdoc,
355 Hashtable vobj2jv, IdentityHashMap jv2vobj)
357 this.provEntry = provEntry;
359 this.vobj2jv = vobj2jv;
360 this.jv2vobj = jv2vobj;
363 protected boolean isModifiable(String modifiable)
365 return modifiable == null; // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS)
368 protected Vector getjv2vObjs(Vector alsq)
370 Vector vObjs = new Vector();
371 Enumeration elm = alsq.elements();
372 while (elm.hasMoreElements())
374 vObjs.addElement(getjv2vObj(elm.nextElement()));
381 * get start<end range of segment, adjusting for inclusivity flag and
385 * @param ensureDirection
386 * when true - always ensure start is less than end.
387 * @return int[] { start, end, direction} where direction==1 for range running
390 public int[] getSegRange(Seg visSeg, boolean ensureDirection)
392 boolean incl = visSeg.getInclusive();
393 // adjust for inclusive flag.
394 int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of
396 int start = visSeg.getStart() + (incl ? 0 : pol);
397 int end = visSeg.getEnd() + (incl ? 0 : -pol);
398 if (ensureDirection && pol == -1)
400 // jalview doesn't deal with inverted ranges, yet.
406 { start, end, pol < 0 ? 1 : 0 };
412 protected jalview.datamodel.Provenance getJalviewProvenance(
415 // TODO: fix App and Action entries and check use of provenance in jalview.
416 jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
417 for (int i = 0; i < prov.getEntryCount(); i++)
419 jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i)
420 .getAction(), prov.getEntry(i).getDate(), prov.getEntry(i)
429 * @return default initial provenance list for a Jalview created vamsas
432 Provenance dummyProvenance()
434 return dummyProvenance(null);
437 protected Entry dummyPEntry(String action)
439 Entry entry = new Entry();
440 entry.setApp(this.provEntry.getApp());
443 entry.setAction(action);
447 entry.setAction("created.");
449 entry.setDate(new java.util.Date());
450 entry.setUser(this.provEntry.getUser());
454 protected Provenance dummyProvenance(String action)
456 Provenance prov = new Provenance();
457 prov.addEntry(dummyPEntry(action));
461 protected void addProvenance(Provenance p, String action)
463 p.addEntry(dummyPEntry(action));
468 * @return true if jalview was being updated from the vamsas document
470 public boolean isTojalview()
476 * @return true if addToDocument() was called.
478 public boolean isAddtodoc()
484 * @return true if conflict() was called
486 public boolean isConflicted()
492 * @return true if updateFromDoc() was called
494 public boolean isUpdatedFromDoc()
496 return updatedfromdoc;
499 * @return true if updateToDoc() was called
501 public boolean isUpdatedToDoc()
507 * @return true if addFromDocument() was called.
509 public boolean isAddfromdoc()
515 * @return true if object sync logic completed normally.
517 public boolean isSuccess()
525 public Vobject getVobj()
533 public Object getJvobj()
538 public boolean docWasUpdated()
540 return (this.addtodoc || this.updated) && this.success;
543 public boolean jvWasUpdated()
545 return (success); // TODO : Implement this properly!