+/**\r
+ * \r
+ */\r
+package jalview.io.vamsas;\r
+\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+import uk.ac.vamsas.objects.core.DataSet;\r
+import uk.ac.vamsas.objects.core.DataSetAnnotations;\r
+import uk.ac.vamsas.objects.core.Link;\r
+import uk.ac.vamsas.objects.core.Property;\r
+import uk.ac.vamsas.objects.core.Provenance;\r
+import uk.ac.vamsas.objects.core.RangeAnnotation;\r
+import uk.ac.vamsas.objects.core.Score;\r
+import uk.ac.vamsas.objects.core.Seg;\r
+import uk.ac.vamsas.objects.core.Sequence;\r
+import uk.ac.vamsas.objects.utils.Properties;\r
+import jalview.bin.Cache;\r
+import jalview.datamodel.SequenceFeature;\r
+import jalview.datamodel.SequenceI;\r
+import jalview.io.VamsasAppDatastore;\r
+import jalview.util.UrlLink;\r
+\r
+/**\r
+ * @author JimP\r
+ * \r
+ */\r
+public class Sequencefeature extends Rangetype\r
+{\r
+\r
+ uk.ac.vamsas.objects.core.DataSet dataset;\r
+\r
+ uk.ac.vamsas.objects.core.Sequence sequence;\r
+\r
+ private SequenceI dsSeq;\r
+\r
+ public Sequencefeature(VamsasAppDatastore vamsasAppDatastore,\r
+ SequenceFeature sequenceFeature,\r
+ uk.ac.vamsas.objects.core.DataSet dataset,\r
+ uk.ac.vamsas.objects.core.Sequence sequence)\r
+ {\r
+ super(vamsasAppDatastore, sequenceFeature, DataSetAnnotations.class);\r
+ this.dataset = dataset;\r
+ this.sequence = sequence;\r
+ doSync();\r
+ }\r
+\r
+ public Sequencefeature(VamsasAppDatastore vamsasAppDatastore,\r
+ DataSetAnnotations dseta, SequenceI dsSeq)\r
+ {\r
+ super(vamsasAppDatastore, dseta, jalview.datamodel.SequenceFeature.class);\r
+ this.dsSeq = dsSeq;\r
+ doJvUpdate();\r
+ }\r
+\r
+ public void addToDocument()\r
+ {\r
+ DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
+ jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
+ dsa = (DataSetAnnotations) getDSAnnotationFromJalview(\r
+ new DataSetAnnotations(), feature);\r
+ if (dsa.getProvenance() == null)\r
+ {\r
+ dsa.setProvenance(new Provenance());\r
+ }\r
+ addProvenance(dsa.getProvenance(), "created"); // JBPNote - need\r
+ // to update\r
+ dsa.addSeqRef(sequence); // we have just created this annotation\r
+ // - so safe to use this\r
+ bindjvvobj(feature, dsa);\r
+ dataset.addDataSetAnnotations(dsa);\r
+ }\r
+\r
+ public void addFromDocument()\r
+ {\r
+ DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
+ if (dsa.getSeqRefCount()!=1)\r
+ {\r
+ Cache.log.warn("Not binding "+dsa.getVorbaId()+" to Sequence Feature - has multiple dataset sequence references.");\r
+ return;\r
+ }\r
+ jalview.datamodel.SequenceFeature sf = (jalview.datamodel.SequenceFeature) jvobj;\r
+ dsSeq.addSequenceFeature(sf = getJalviewSeqFeature(dsa));\r
+ jvobj = sf;\r
+ bindjvvobj(sf, dsa);\r
+ }\r
+\r
+ public void conflict()\r
+ {\r
+ log.warn("Untested sequencefeature conflict code");\r
+ DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
+ jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
+ jalview.datamodel.SequenceFeature sf = getJalviewSeqFeature(dsa);\r
+ replaceJvObjMapping(feature, sf); // switch binding of dsa from old feature to newly created feature\r
+ dsSeq.addSequenceFeature(sf); // add new imported feature\r
+ addToDocument(); // and create a new feature in the document \r
+ }\r
+\r
+ public void updateToDoc()\r
+ {\r
+ DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
+ jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
+ if (dsa.getSeqRefCount() != 1)\r
+ {\r
+ replaceJvObjMapping(feature, null);\r
+ Cache.log\r
+ .warn("Binding of annotation to jalview feature has changed. Removing binding and recreating.");\r
+ doSync(); // re-verify bindings.\r
+ }\r
+ else\r
+ {\r
+ // Sync the features from Jalview\r
+ long oldref = dsa.get__last_hash();\r
+ getDSAnnotationFromJalview(dsa, feature);\r
+ if (oldref != dsa.hashCode())\r
+ {\r
+ Cache.log\r
+ .debug("Updated dataset sequence annotation from feature.");\r
+ addProvenance(dsa.getProvenance(), "modified");\r
+ }\r
+ }\r
+\r
+ }\r
+ public void updateFromDoc()\r
+ {\r
+ DataSetAnnotations dsa = (DataSetAnnotations) vobj;\r
+ jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) jvobj;\r
+ if (dsa.getSeqRefCount() != 1)\r
+ {\r
+ // conflicting update from document - we cannot map this feature anymore.\r
+ replaceJvObjMapping(feature, null);\r
+ Cache.log\r
+ .warn("annotation ("+dsa.getVorbaId()+" bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature.");\r
+ // - consider deleting the feature ?\r
+ dsSeq.deleteFeature(feature);\r
+ // doSync();\r
+ }\r
+ else\r
+ {\r
+ // Sync the features to Jalview - easiest to delete and add the feature again\r
+ jalview.datamodel.SequenceFeature newsf = getJalviewSeqFeature(dsa);\r
+ dsSeq.deleteFeature(feature);\r
+ replaceJvObjMapping(feature, newsf);\r
+ dsSeq.addSequenceFeature(newsf);\r
+ feature.otherDetails.clear();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * correctly create/update a RangeAnnotation from a jalview sequence feature\r
+ * TODO: refactor to a method in jalview.io.vamsas.RangeAnnotation class\r
+ * \r
+ * @param dsa\r
+ * (typically DataSetAnnotations or\r
+ * AlignmentSequenceAnnotation)\r
+ * @param feature\r
+ * (the feature to be mapped from)\r
+ * @return\r
+ */\r
+ private RangeAnnotation getDSAnnotationFromJalview(RangeAnnotation dsa,\r
+ jalview.datamodel.SequenceFeature feature)\r
+ {\r
+ dsa.setType(feature.getType());\r
+ Seg vSeg = new Seg();\r
+ vSeg.setStart(feature.getBegin());\r
+ vSeg.setEnd(feature.getEnd());\r
+ vSeg.setInclusive(true);\r
+ if (dsa.getSegCount() > 1)\r
+ {\r
+ Cache.log\r
+ .debug("About to destroy complex annotation in vamsas document mapped to sequence feature ("\r
+ + dsa.getVorbaId() + ")");\r
+ }\r
+ dsa.setSeg(new Seg[]\r
+ { vSeg });\r
+ dsa.setDescription(feature.getDescription());\r
+ dsa.setStatus(feature.getStatus());\r
+ if (feature.links != null && feature.links.size() > 0)\r
+ {\r
+ for (int i = 0, iSize = feature.links.size(); i < iSize; i++)\r
+ {\r
+ String link = (String) feature.links.elementAt(i);\r
+ UrlLink ulink = new UrlLink(link);\r
+ /*\r
+ * int sep = link.indexOf('|'); if (sep > -1) { Link vLink = new Link();\r
+ * if (sep > 0) { vLink.setContent(link.substring(0, sep - 1)); } else {\r
+ * vLink.setContent(""); } vLink.setHref(link.substring(sep + 1)); //\r
+ * TODO: validate href. dsa.addLink(vLink); }\r
+ */\r
+ Link vLink = new Link();\r
+ vLink.setContent(ulink.getLabel());\r
+ vLink.setHref(ulink.getUrl_prefix());\r
+ }\r
+ }\r
+ dsa.setGroup(feature.getFeatureGroup());\r
+ if (feature.getScore() != Float.NaN)\r
+ {\r
+ Score fscore = new Score();\r
+ dsa.setScore(new Score[]\r
+ { fscore });\r
+ fscore.setContent(feature.getScore());\r
+ fscore.setName(feature.getType());\r
+ }\r
+ if (feature.otherDetails != null)\r
+ {\r
+ Enumeration iter = feature.otherDetails.keys();\r
+ Vector props = dsa.getPropertyAsReference();\r
+ while (iter.hasMoreElements())\r
+ {\r
+ String key = (String) iter.nextElement();\r
+ if (!key.equalsIgnoreCase("score")\r
+ && !key.equalsIgnoreCase("status"))\r
+ {\r
+ Property nprop = new Property();\r
+ nprop.setName(key);\r
+ Object vlu = feature.getValue(key);\r
+ nprop.setContent(feature.getValue(key).toString());\r
+ boolean valid = false;\r
+ if (vlu instanceof String)\r
+ {\r
+ nprop.setType(uk.ac.vamsas.objects.utils.Properties.STRINGTYPE);\r
+ valid = true;\r
+ }\r
+ else if (vlu instanceof Integer)\r
+ {\r
+ valid = true;\r
+ nprop\r
+ .setType(uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE);\r
+ }\r
+ else if (vlu instanceof Float)\r
+ {\r
+ nprop.setType(uk.ac.vamsas.objects.utils.Properties.FLOATTYPE);\r
+ valid = true;\r
+ }\r
+ if (valid)\r
+ {\r
+ if (props != null)\r
+ {\r
+ uk.ac.vamsas.objects.utils.Properties.addOrReplace(props,\r
+ nprop);\r
+ }\r
+ else\r
+ {\r
+ dsa.addProperty(nprop);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return dsa;\r
+ }\r
+ private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)\r
+ {\r
+ int[] se = getBounds(dseta);\r
+ SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta\r
+ .getType(), dseta.getDescription(), dseta.getStatus(), se[0],\r
+ se[1], dseta.getGroup());\r
+ if (dseta.getLinkCount() > 0)\r
+ {\r
+ Link[] links = dseta.getLink();\r
+ for (int i = 0; i < links.length; i++)\r
+ {\r
+ sf.addLink(links[i].getContent() + "|" + links[i].getHref());\r
+ }\r
+ }\r
+ if (dseta.getScoreCount()>0)\r
+ {\r
+ Enumeration scr = dseta.enumerateScore();\r
+ while (scr.hasMoreElements())\r
+ {\r
+ Score score = (Score) scr.nextElement();\r
+ if (score.getName().equals(sf.getType()))\r
+ {\r
+ sf.setScore(score.getContent());\r
+ } else {\r
+ sf.setValue(score.getName(), ""+score.getContent());\r
+ }\r
+ }\r
+ }\r
+ // other details\r
+ Enumeration props = dseta.enumerateProperty();\r
+ while (props.hasMoreElements())\r
+ {\r
+ Property p = (Property) props.nextElement();\r
+ Object val = null;\r
+ if (Properties.isValid(p)) \r
+ {\r
+ if (Properties.isString(p))\r
+ {\r
+ val = p.getContent();\r
+ }\r
+ if (Properties.isBoolean(p))\r
+ {\r
+ try {\r
+ val = new Boolean(p.getContent());\r
+ } catch (Exception e) {}\r
+ }\r
+ if (Properties.isFloat(p))\r
+ {\r
+ try {\r
+ val = new Float(p.getContent());\r
+ \r
+ } catch (Exception e)\r
+ {\r
+ }\r
+ }\r
+ if(Properties.isInteger(p))\r
+ {\r
+ try {\r
+ val = new Integer(p.getContent());\r
+ } catch (Exception e)\r
+ {\r
+ } \r
+ }\r
+ if (val!=null)\r
+ {\r
+ sf.setValue(p.getName(), val);\r
+ }\r
+ }\r
+ }\r
+\r
+ return sf;\r
+ }\r
+\r
+}\r