+ return annotation == null ? null
+ : annotation
+ .toArray(new AlignmentAnnotation[annotation.size()]);
+ }
+
+ @Override
+ public boolean hasAnnotation(AlignmentAnnotation ann)
+ {
+ return annotation == null ? false : annotation.contains(ann);
+ }
+
+ @Override
+ public void addAlignmentAnnotation(AlignmentAnnotation annotation)
+ {
+ if (this.annotation == null)
+ {
+ this.annotation = new Vector<>();
+ }
+ if (!this.annotation.contains(annotation))
+ {
+ this.annotation.addElement(annotation);
+ }
+ annotation.setSequenceRef(this);
+ }
+
+ @Override
+ public void removeAlignmentAnnotation(AlignmentAnnotation annotation)
+ {
+ if (this.annotation != null)
+ {
+ this.annotation.removeElement(annotation);
+ if (this.annotation.size() == 0)
+ {
+ this.annotation = null;
+ }
+ }
+ }
+
+ /**
+ * test if this is a valid candidate for another sequence's dataset sequence.
+ *
+ */
+ private boolean isValidDatasetSequence()
+ {
+ if (datasetSequence != null)
+ {
+ return false;
+ }
+ for (int i = 0; i < sequence.length; i++)
+ {
+ if (jalview.util.Comparison.isGap(sequence[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public SequenceI deriveSequence()
+ {
+ Sequence seq = null;
+ if (datasetSequence == null)
+ {
+ if (isValidDatasetSequence())
+ {
+ // Use this as dataset sequence
+ seq = new Sequence(getName(), "", 1, -1);
+ seq.setDatasetSequence(this);
+ seq.initSeqFrom(this, getAnnotation());
+ return seq;
+ }
+ else
+ {
+ // Create a new, valid dataset sequence
+ createDatasetSequence();
+ }
+ }
+ return new Sequence(this);
+ }
+
+ private boolean _isNa;
+
+ private long _seqhash = 0;
+
+ /**
+ * Answers false if the sequence is more than 85% nucleotide (ACGTU), else
+ * true
+ */
+ @Override
+ public boolean isProtein()
+ {
+ if (datasetSequence != null)
+ {
+ return datasetSequence.isProtein();
+ }
+ if (_seqhash != sequence.hashCode())
+ {
+ _seqhash = sequence.hashCode();
+ _isNa = Comparison.isNucleotide(this);
+ }
+ return !_isNa;
+ };
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.SequenceI#createDatasetSequence()
+ */
+ @Override
+ public SequenceI createDatasetSequence()
+ {
+ if (datasetSequence == null)
+ {
+ Sequence dsseq = new Sequence(getName(),
+ AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
+ getSequenceAsString()),
+ getStart(), getEnd());
+
+ datasetSequence = dsseq;
+
+ dsseq.setDescription(description);
+ // move features and database references onto dataset sequence
+ dsseq.sequenceFeatures = sequenceFeatures;
+ sequenceFeatures = null;
+ dsseq.dbrefs = dbrefs;
+ dbrefs = null;
+ // TODO: search and replace any references to this sequence with
+ // references to the dataset sequence in Mappings on dbref
+ dsseq.pdbIds = pdbIds;
+ pdbIds = null;
+ datasetSequence.updatePDBIds();
+ if (annotation != null)
+ {
+ // annotation is cloned rather than moved, to preserve what's currently
+ // on the alignment
+ for (AlignmentAnnotation aa : annotation)
+ {
+ AlignmentAnnotation _aa = new AlignmentAnnotation(aa);
+ _aa.sequenceRef = datasetSequence;
+ _aa.adjustForAlignment(); // uses annotation's own record of
+ // sequence-column mapping
+ datasetSequence.addAlignmentAnnotation(_aa);
+ }
+ }
+ }
+ return datasetSequence;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.datamodel.SequenceI#setAlignmentAnnotation(AlignmmentAnnotation[]
+ * annotations)
+ */
+ @Override
+ public void setAlignmentAnnotation(AlignmentAnnotation[] annotations)
+ {
+ if (annotation != null)
+ {
+ annotation.removeAllElements();
+ }
+ if (annotations != null)
+ {
+ for (int i = 0; i < annotations.length; i++)
+ {
+ if (annotations[i] != null)
+ {
+ addAlignmentAnnotation(annotations[i]);
+ }
+ }
+ }
+ }
+
+ @Override
+ public AlignmentAnnotation[] getAnnotation(String label)
+ {
+ if (annotation == null || annotation.size() == 0)