+ synchronized (sequences)
+ {
+ SeqCigar alseqs[] = new SeqCigar[sequences.size()];
+ int i = 0;
+ for (SequenceI seq : sequences)
+ {
+ alseqs[i++] = new SeqCigar(seq);
+ }
+ CigarArray cal = new CigarArray(alseqs);
+ cal.addOperation(CigarArray.M, getWidth());
+ return cal;
+ }
+ }
+
+ @Override
+ public void setProperty(Object key, Object value)
+ {
+ if (alignmentProperties == null)
+ {
+ alignmentProperties = new Hashtable();
+ }
+
+ alignmentProperties.put(key, value);
+ }
+
+ @Override
+ public Object getProperty(Object key)
+ {
+ if (alignmentProperties != null)
+ {
+ return alignmentProperties.get(key);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public Hashtable getProperties()
+ {
+ return alignmentProperties;
+ }
+
+ /**
+ * Adds the given mapping to the stored set. Note this may be held on the
+ * dataset alignment.
+ */
+ @Override
+ public void addCodonFrame(AlignedCodonFrame codons)
+ {
+ List<AlignedCodonFrame> acfs = getCodonFrames();
+ if (codons != null && acfs != null && !acfs.contains(codons))
+ {
+ acfs.add(codons);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.datamodel.AlignmentI#getCodonFrame(jalview.datamodel.SequenceI)
+ */
+ @Override
+ public List<AlignedCodonFrame> getCodonFrame(SequenceI seq)
+ {
+ if (seq == null)
+ {
+ return null;
+ }
+ List<AlignedCodonFrame> cframes = new ArrayList<AlignedCodonFrame>();
+ for (AlignedCodonFrame acf : getCodonFrames())
+ {
+ if (acf.involvesSequence(seq))
+ {
+ cframes.add(acf);
+ }
+ }
+ return cframes;
+ }
+
+ /**
+ * Sets the codon frame mappings (replacing any existing mappings). Note the
+ * mappings are set on the dataset alignment instead if there is one.
+ *
+ * @see jalview.datamodel.AlignmentI#setCodonFrames()
+ */
+ @Override
+ public void setCodonFrames(List<AlignedCodonFrame> acfs)
+ {
+ if (dataset != null)
+ {
+ dataset.setCodonFrames(acfs);
+ }
+ else
+ {
+ this.codonFrameList = acfs;
+ }
+ }
+
+ /**
+ * Returns the set of codon frame mappings. Any changes to the returned set
+ * will affect the alignment. The mappings are held on (and read from) the
+ * dataset alignment if there is one.
+ *
+ * @see jalview.datamodel.AlignmentI#getCodonFrames()
+ */
+ @Override
+ public List<AlignedCodonFrame> getCodonFrames()
+ {
+ // TODO: Fix this method to fix failing AlignedCodonFrame tests
+ // this behaviour is currently incorrect. method should return codon frames
+ // for just the alignment,
+ // selected from dataset
+ return dataset != null ? dataset.getCodonFrames() : codonFrameList;
+ }
+
+ /**
+ * Removes the given mapping from the stored set. Note that the mappings are
+ * held on the dataset alignment if there is one.
+ */
+ @Override
+ public boolean removeCodonFrame(AlignedCodonFrame codons)
+ {
+ List<AlignedCodonFrame> acfs = getCodonFrames();
+ if (codons == null || acfs == null)
+ {
+ return false;
+ }
+ return acfs.remove(codons);
+ }
+
+ @Override
+ public void append(AlignmentI toappend)
+ {
+ if (toappend == this)
+ {
+ System.err.println("Self append may cause a deadlock.");
+ }
+ // TODO JAL-1270 needs test coverage
+ // currently tested for use in jalview.gui.SequenceFetcher
+ boolean samegap = toappend.getGapCharacter() == getGapCharacter();
+ char oldc = toappend.getGapCharacter();
+ boolean hashidden = toappend.getHiddenSequences() != null
+ && toappend.getHiddenSequences().hiddenSequences != null;
+ // get all sequences including any hidden ones
+ List<SequenceI> sqs = (hashidden) ? toappend.getHiddenSequences()
+ .getFullAlignment().getSequences() : toappend.getSequences();
+ if (sqs != null)
+ {
+ synchronized (sqs)
+ {
+ for (SequenceI addedsq : sqs)
+ {
+ if (!samegap)
+ {
+ char[] oldseq = addedsq.getSequence();
+ for (int c = 0; c < oldseq.length; c++)
+ {
+ if (oldseq[c] == oldc)
+ {
+ oldseq[c] = gapCharacter;
+ }
+ }
+ }
+ addSequence(addedsq);
+ }
+ }
+ }
+ AlignmentAnnotation[] alan = toappend.getAlignmentAnnotation();
+ for (int a = 0; alan != null && a < alan.length; a++)
+ {
+ addAnnotation(alan[a]);
+ }
+
+ // use add method
+ getCodonFrames().addAll(toappend.getCodonFrames());
+
+ List<SequenceGroup> sg = toappend.getGroups();
+ if (sg != null)
+ {
+ for (SequenceGroup _sg : sg)
+ {
+ addGroup(_sg);
+ }
+ }
+ if (toappend.getHiddenSequences() != null)
+ {
+ HiddenSequences hs = toappend.getHiddenSequences();
+ if (hiddenSequences == null)
+ {
+ hiddenSequences = new HiddenSequences(this);
+ }
+ if (hs.hiddenSequences != null)
+ {
+ for (int s = 0; s < hs.hiddenSequences.length; s++)
+ {
+ // hide the newly appended sequence in the alignment
+ if (hs.hiddenSequences[s] != null)
+ {
+ hiddenSequences.hideSequence(hs.hiddenSequences[s]);
+ }
+ }
+ }
+ }
+ if (toappend.getProperties() != null)
+ {
+ // we really can't do very much here - just try to concatenate strings
+ // where property collisions occur.
+ Enumeration key = toappend.getProperties().keys();
+ while (key.hasMoreElements())
+ {
+ Object k = key.nextElement();
+ Object ourval = this.getProperty(k);
+ Object toapprop = toappend.getProperty(k);
+ if (ourval != null)
+ {
+ if (ourval.getClass().equals(toapprop.getClass())
+ && !ourval.equals(toapprop))
+ {
+ if (ourval instanceof String)
+ {
+ // append strings
+ this.setProperty(k, ((String) ourval) + "; "
+ + ((String) toapprop));
+ }
+ else
+ {
+ if (ourval instanceof Vector)
+ {
+ // append vectors
+ Enumeration theirv = ((Vector) toapprop).elements();
+ while (theirv.hasMoreElements())
+ {
+ ((Vector) ourval).addElement(theirv);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // just add new property directly
+ setProperty(k, toapprop);
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public AlignmentAnnotation findOrCreateAnnotation(String name,
+ String calcId, boolean autoCalc, SequenceI seqRef,
+ SequenceGroup groupRef)
+ {
+ assert (name != null);
+ if (annotations != null)
+ {
+ for (AlignmentAnnotation annot : getAlignmentAnnotation())
+ {
+ if (annot.autoCalculated == autoCalc && (name.equals(annot.label))
+ && (calcId == null || annot.getCalcId().equals(calcId))
+ && annot.sequenceRef == seqRef
+ && annot.groupRef == groupRef)
+ {
+ return annot;
+ }
+ }
+ }
+ AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
+ new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
+ annot.hasText = false;
+ annot.setCalcId(new String(calcId));
+ annot.autoCalculated = autoCalc;
+ if (seqRef != null)
+ {
+ annot.setSequenceRef(seqRef);
+ }
+ annot.groupRef = groupRef;
+ addAnnotation(annot);
+
+ return annot;
+ }
+
+ @Override
+ public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
+ {
+ ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
+ for (AlignmentAnnotation a : getAlignmentAnnotation())
+ {
+ if (a.getCalcId() == calcId
+ || (a.getCalcId() != null && calcId != null && a.getCalcId()
+ .equals(calcId)))
+ {
+ aa.add(a);
+ }
+ }
+ return aa;
+ }
+
+ /**
+ * Returns an iterable collection of any annotations that match on given
+ * sequence ref, calcId and label (ignoring null values).
+ */
+ @Override
+ public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
+ String calcId, String label)
+ {
+ ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
+ for (AlignmentAnnotation ann : getAlignmentAnnotation())