2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.io.vamsas;
23 import java.util.Enumeration;
24 import java.util.Hashtable;
25 import java.util.IdentityHashMap;
26 import java.util.Vector;
28 import jalview.bin.Cache;
29 import jalview.io.VamsasAppDatastore;
30 import jalview.log.JLoggerLog4j;
31 import jalview.util.MessageManager;
32 import uk.ac.vamsas.client.IClientDocument;
33 import uk.ac.vamsas.client.Vobject;
34 import uk.ac.vamsas.client.VorbaId;
35 import uk.ac.vamsas.objects.core.Entry;
36 import uk.ac.vamsas.objects.core.Provenance;
37 import uk.ac.vamsas.objects.core.Seg;
40 * Holds all the common machinery for binding objects to vamsas objects
45 public abstract class DatastoreItem
50 Entry provEntry = null;
56 IdentityHashMap jv2vobj;
58 boolean tojalview = false;
63 protected static JLoggerLog4j log = JLoggerLog4j
64 .getLogger(DatastoreItem.class.getCanonicalName());
67 * note: this is taken verbatim from jalview.io.VamsasAppDatastore
69 * @return the Vobject bound to Jalview datamodel object
71 protected Vobject getjv2vObj(Object jvobj)
73 if (jv2vobj.containsKey(jvobj))
75 return cdoc.getObject((VorbaId) jv2vobj.get(jvobj));
77 if (Cache.isDebugEnabled())
80 "Returning null VorbaID binding for jalview object " + jvobj);
88 * @return Jalview datamodel object bound to the vamsas document object
90 protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj)
94 VorbaId id = vobj.getVorbaId();
97 id = cdoc.registerObject(vobj);
99 "Registering new object and returning null for getvObj2jv");
102 if (vobj2jv.containsKey(vobj.getVorbaId()))
104 return vobj2jv.get(vobj.getVorbaId());
110 * note: this is taken verbatim from jalview.io.VamsasAppDatastore with added
111 * call to updateRegistryEntry
116 protected void bindjvvobj(Object jvobj, uk.ac.vamsas.client.Vobject vobj)
118 VorbaId id = vobj.getVorbaId();
121 id = cdoc.registerObject(vobj);
122 if (id == null || vobj.getVorbaId() == null
123 || cdoc.getObject(id) != vobj)
125 Cache.error("Failed to get id for "
126 + (vobj.isRegisterable() ? "registerable"
128 + " object " + vobj);
131 if (vobj2jv.containsKey(vobj.getVorbaId())
132 && !(vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
135 "Warning? Overwriting existing vamsas id binding for "
137 new Exception(MessageManager.getString(
138 "exception.overwriting_vamsas_id_binding")));
140 else if (jv2vobj.containsKey(jvobj)
141 && !((VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
144 "Warning? Overwriting existing jalview object binding for "
146 new Exception(MessageManager.getString(
147 "exception.overwriting_jalview_id_binding")));
150 * Cache.error("Attempt to make conflicting object binding! "+vobj+" id "
151 * +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+"
152 * already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to
155 // we just update the hash's regardless!
156 Cache.debug("Binding " + vobj.getVorbaId() + " to " + jvobj);
157 vobj2jv.put(vobj.getVorbaId(), jvobj);
158 // JBPNote - better implementing a hybrid invertible hash.
159 jv2vobj.put(jvobj, vobj.getVorbaId());
160 if (jvobj == this.jvobj || vobj == this.vobj)
162 updateRegistryEntry(jvobj, vobj);
167 * update the vobj and jvobj references and the registry entry for this
168 * datastore object called by bindjvvobj and replacejvobjmapping
170 private void updateRegistryEntry(Object jvobj, Vobject vobj)
172 if (this.jvobj != null && this.vobj != null)
174 Cache.debug("updating dsobj registry. (" + this.getClass().getName()
179 dsReg.registerDsObj(this);
183 * replaces oldjvobject with newjvobject in the Jalview Object <> VorbaID
184 * binding tables note: originally taken verbatim from
185 * jalview.io.VamsasAppDatastore with added call to updateRegistryEntry
189 * (may be null to forget the oldjvobject's document mapping)
192 protected void replaceJvObjMapping(Object oldjvobject, Object newjvobject)
194 Object vobject = jv2vobj.remove(oldjvobject);
197 throw new Error(MessageManager.formatMessage(
198 "error.implementation_error_old_jalview_object_not_bound",
200 { oldjvobject.toString() }));
202 if (newjvobject != null)
204 jv2vobj.put(newjvobject, vobject);
205 vobj2jv.put(vobject, newjvobject);
206 updateRegistryEntry(newjvobject, vobj);
210 public DatastoreItem()
215 public DatastoreItem(VamsasAppDatastore datastore)
218 initDatastoreItem(datastore);
219 // TODO Auto-generated constructor stub
223 * construct and initialise datastore object and retrieve object bound to
224 * vobj2 and validate it against boundType
230 public DatastoreItem(VamsasAppDatastore datastore2, Vobject vobj2,
235 jvobj = getvObj2jv(vobj2);
237 if (jvobj != null && !(boundType.isAssignableFrom(jvobj.getClass())))
239 throw new Error(MessageManager.formatMessage(
240 "error.implementation_error_vamsas_doc_class_should_bind_to_type",
242 { vobj.getClass().toString(), boundType.toString(),
243 jvobj.getClass().toString() }));
245 dsReg.registerDsObj(this);
249 * construct and initialise datastore object and retrieve document object
250 * bound to Jalview object jvobj2 and validate it against boundType
257 * - the document object class that the bound object should be
260 public DatastoreItem(VamsasAppDatastore datastore2, Object jvobj2,
266 vobj = getjv2vObj(jvobj);
267 if (vobj != null && !(boundToType.isAssignableFrom(vobj.getClass())))
269 throw new Error(MessageManager.formatMessage(
270 "error.implementation_error_vamsas_doc_class_should_bind_to_type",
272 { jvobj2.getClass().toString(), boundToType.toString(),
273 vobj.getClass().toString() }));
275 dsReg.registerDsObj(this);
279 * create a new vobj to be added to the document for the jalview object jvobj
280 * (jvobj!=null, vobj==null)
282 public abstract void addToDocument();
285 * handle a conflict where both an existing vobj has been updated and a local
286 * jalview object has been updated. This method is only called from doSync,
287 * when an incoming update from the vamsas session conflicts with local
288 * modifications made by the Jalview user. (jvobj!=null, vobj!=null)
290 public abstract void conflict();
293 * update an existing vobj in the document with the data and settings from
294 * jvobj (jvobj!=null, vobj!=null)
296 public abstract void updateToDoc();
299 * update the local jalview object with the data from an existing vobj in the
300 * document (jvobj!=null, vobj!=null)
302 public abstract void updateFromDoc();
305 * create a new local jvobj bound to the vobj in the document. (jvobj==null,
308 public abstract void addFromDocument();
310 boolean addtodoc = false, conflicted = false, updated = false,
311 addfromdoc = false, success = false;
313 private boolean updatedtodoc;
315 private boolean updatedfromdoc;
318 * Sync jalview to document. Enact addToDocument, conflict or update dependent
319 * on existence of a vobj bound to the local jvobj.
321 protected void doSync()
323 dsReg.registerDsObj(this);
326 log.debug("adding new vobject to document.");
332 if (vobj.isUpdated())
334 log.debug("Handling update conflict for existing bound vobject.");
340 log.debug("updating existing vobject in document.");
345 // no exceptions were encountered...
350 * Update jalview from document. enact addFromDocument if no local jvobj
351 * exists, or update iff jvobj exists and the vobj.isUpdated() flag is set.
353 protected void doJvUpdate()
355 dsReg.registerDsObj(this);
358 log.debug("adding new vobject to Jalview from Document");
364 if (vobj.isUpdated())
366 log.debug("updating Jalview from existing bound vObject");
367 updatedfromdoc = true;
373 VamsasAppDatastore datastore = null;
376 * object in vamsas document
378 protected Vobject vobj = null;
381 * local jalview object
383 protected Object jvobj = null;
385 protected DatastoreRegistry dsReg;
387 public void initDatastoreItem(VamsasAppDatastore ds)
390 dsReg = ds.getDatastoreRegisty();
391 initDatastoreItem(ds.getProvEntry(), ds.getClientDocument(),
392 ds.getVamsasObjectBinding(), ds.getJvObjectBinding());
395 private void initDatastoreItem(Entry provEntry, IClientDocument cdoc,
396 Hashtable vobj2jv, IdentityHashMap jv2vobj)
398 this.provEntry = provEntry;
400 this.vobj2jv = vobj2jv;
401 this.jv2vobj = jv2vobj;
404 protected boolean isModifiable(String modifiable)
406 return modifiable == null; // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS)
409 protected Vector getjv2vObjs(Vector alsq)
411 Vector vObjs = new Vector();
412 Enumeration elm = alsq.elements();
413 while (elm.hasMoreElements())
415 vObjs.addElement(getjv2vObj(elm.nextElement()));
422 * get start<end range of segment, adjusting for inclusivity flag and
426 * @param ensureDirection
427 * when true - always ensure start is less than end.
428 * @return int[] { start, end, direction} where direction==1 for range running
431 public int[] getSegRange(Seg visSeg, boolean ensureDirection)
433 boolean incl = visSeg.getInclusive();
434 // adjust for inclusive flag.
435 int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of
437 int start = visSeg.getStart() + (incl ? 0 : pol);
438 int end = visSeg.getEnd() + (incl ? 0 : -pol);
439 if (ensureDirection && pol == -1)
441 // jalview doesn't deal with inverted ranges, yet.
446 return new int[] { start, end, pol < 0 ? 1 : 0 };
452 protected jalview.datamodel.Provenance getJalviewProvenance(
455 // TODO: fix App and Action entries and check use of provenance in jalview.
456 jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
457 for (int i = 0; i < prov.getEntryCount(); i++)
459 jprov.addEntry(prov.getEntry(i).getUser(),
460 prov.getEntry(i).getAction(), prov.getEntry(i).getDate(),
461 prov.getEntry(i).getId());
469 * @return default initial provenance list for a Jalview created vamsas
472 Provenance dummyProvenance()
474 return dummyProvenance(null);
477 protected Entry dummyPEntry(String action)
479 Entry entry = new Entry();
480 entry.setApp(this.provEntry.getApp());
483 entry.setAction(action);
487 entry.setAction("created.");
489 entry.setDate(new java.util.Date());
490 entry.setUser(this.provEntry.getUser());
494 protected Provenance dummyProvenance(String action)
496 Provenance prov = new Provenance();
497 prov.addEntry(dummyPEntry(action));
501 protected void addProvenance(Provenance p, String action)
503 p.addEntry(dummyPEntry(action));
507 * @return true if jalview was being updated from the vamsas document
509 public boolean isTojalview()
515 * @return true if addToDocument() was called.
517 public boolean isAddtodoc()
523 * @return true if conflict() was called
525 public boolean isConflicted()
531 * @return true if updateFromDoc() was called
533 public boolean isUpdatedFromDoc()
535 return updatedfromdoc;
539 * @return true if updateToDoc() was called
541 public boolean isUpdatedToDoc()
547 * @return true if addFromDocument() was called.
549 public boolean isAddfromdoc()
555 * @return true if object sync logic completed normally.
557 public boolean isSuccess()
565 public Vobject getVobj()
573 public Object getJvobj()
578 public boolean docWasUpdated()
580 return (this.addtodoc || this.updated) && this.success;
583 public boolean jvWasUpdated()
585 return (success); // TODO : Implement this properly!