+ {
+ // derive new sequence
+ SequenceI adding = snew.deriveSequence();
+ getDataset().addSequence(adding.getDatasetSequence());
+ snew = adding;
+ }
+ }
+ if (sequences == null)
+ {
+ initAlignment(new SequenceI[]
+ { snew });
+ }
+ else
+ {
+ synchronized (sequences)
+ {
+ sequences.add(snew);
+ }
+ }
+ if (hiddenSequences != null)
+ {
+ hiddenSequences.adjustHeightSequenceAdded();
+ }
+ }
+
+ /**
+ * Adds a sequence to the alignment. Recalculates maxLength and size.
+ *
+ * @param snew
+ */
+ @Override
+ public void setSequenceAt(int i, SequenceI snew)
+ {
+ SequenceI oldseq = getSequenceAt(i);
+ deleteSequence(i);
+ synchronized (sequences)
+ {
+ sequences.set(i, snew);
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ @Override
+ public List<SequenceGroup> getGroups()
+ {
+ return groups;
+ }
+
+ @Override
+ public void finalize()
+ {
+ if (getDataset() != null)
+ {
+ getDataset().removeAlignmentRef();
+ }
+
+ dataset = null;
+ sequences = null;
+ groups = null;
+ annotations = null;
+ hiddenSequences = null;
+ }
+
+ /**
+ * decrement the alignmentRefs counter by one and call finalize if it goes to
+ * zero.
+ */
+ private void removeAlignmentRef()
+ {
+ if (--alignmentRefs == 0)
+ {
+ finalize();
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param s
+ * DOCUMENT ME!
+ */
+ @Override
+ public void deleteSequence(SequenceI s)
+ {
+ deleteSequence(findIndex(s));
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param i
+ * DOCUMENT ME!
+ */
+ @Override
+ public void deleteSequence(int i)
+ {
+ if (i > -1 && i < getHeight())
+ {
+ synchronized (sequences)
+ {
+ sequences.remove(i);
+ }
+ hiddenSequences.adjustHeightSequenceDeleted(i);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#findGroup(jalview.datamodel.SequenceI)
+ */
+ @Override
+ public SequenceGroup findGroup(SequenceI s)
+ {
+ synchronized (groups)
+ {
+ for (int i = 0; i < this.groups.size(); i++)
+ {
+ SequenceGroup sg = groups.get(i);
+
+ if (sg.getSequences(null).contains(s))
+ {
+ return sg;
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.datamodel.AlignmentI#findAllGroups(jalview.datamodel.SequenceI)
+ */
+ @Override
+ public SequenceGroup[] findAllGroups(SequenceI s)
+ {
+ ArrayList<SequenceGroup> temp = new ArrayList<SequenceGroup>();
+
+ synchronized (groups)
+ {
+ int gSize = groups.size();
+ for (int i = 0; i < gSize; i++)
+ {
+ SequenceGroup sg = groups.get(i);
+ if (sg == null || sg.getSequences(null) == null)
+ {
+ this.deleteGroup(sg);
+ gSize--;
+ continue;
+ }
+
+ if (sg.getSequences(null).contains(s))
+ {
+ temp.add(sg);
+ }
+ }
+ }
+ SequenceGroup[] ret = new SequenceGroup[temp.size()];
+ return temp.toArray(ret);
+ }
+
+ /** */
+ @Override
+ public void addGroup(SequenceGroup sg)
+ {
+ synchronized (groups)
+ {
+ if (!groups.contains(sg))
+ {
+ if (hiddenSequences.getSize() > 0)
+ {
+ int i, iSize = sg.getSize();
+ for (i = 0; i < iSize; i++)
+ {
+ if (!sequences.contains(sg.getSequenceAt(i)))
+ {
+ sg.deleteSequence(sg.getSequenceAt(i), false);
+ iSize--;
+ i--;
+ }
+ }
+
+ if (sg.getSize() < 1)
+ {
+ return;
+ }
+ }
+ sg.setContext(this);
+ groups.add(sg);
+ }
+ }
+ }
+
+ /**
+ * remove any annotation that references gp
+ *
+ * @param gp
+ * (if null, removes all group associated annotation)
+ */
+ private void removeAnnotationForGroup(SequenceGroup gp)
+ {
+ if (annotations == null || annotations.length == 0)
+ {
+ return;
+ }
+ // remove annotation very quickly
+ AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length];
+ int i, p, k;
+ if (gp == null)
+ {
+ for (i = 0, p = 0, k = 0; i < annotations.length; i++)
+ {
+ if (annotations[i].groupRef != null)
+ {
+ todelete[p++] = annotations[i];
+ }
+ else
+ {
+ tokeep[k++] = annotations[i];
+ }
+ }
+ }
+ else
+ {
+ for (i = 0, p = 0, k = 0; i < annotations.length; i++)
+ {
+ if (annotations[i].groupRef == gp)
+ {
+ todelete[p++] = annotations[i];
+ }
+ else
+ {
+ tokeep[k++] = annotations[i];
+ }
+ }
+ }
+ if (p > 0)
+ {
+ // clear out the group associated annotation.
+ for (i = 0; i < p; i++)
+ {
+ unhookAnnotation(todelete[i]);
+ todelete[i] = null;
+ }
+ t = new AlignmentAnnotation[k];
+ for (i = 0; i < k; i++)
+ {
+ t[i] = tokeep[i];
+ }
+ annotations = t;
+ }
+ }
+
+ @Override
+ public void deleteAllGroups()
+ {
+ synchronized (groups)
+ {
+ if (annotations != null)
+ {
+ removeAnnotationForGroup(null);
+ }
+ for (SequenceGroup sg : groups)
+ {
+ sg.setContext(null);
+ }
+ groups.clear();
+ }
+ }
+
+ /** */
+ @Override
+ public void deleteGroup(SequenceGroup g)
+ {
+ synchronized (groups)
+ {
+ if (groups.contains(g))
+ {
+ removeAnnotationForGroup(g);
+ groups.remove(g);
+ g.setContext(null);
+ }
+ }
+ }
+
+ /** */
+ @Override
+ public SequenceI findName(String name)
+ {
+ return findName(name, false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#findName(java.lang.String, boolean)
+ */
+ @Override
+ public SequenceI findName(String token, boolean b)
+ {
+ return findName(null, token, b);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#findName(SequenceI, java.lang.String,
+ * boolean)
+ */
+ @Override
+ public SequenceI findName(SequenceI startAfter, String token, boolean b)
+ {
+
+ int i = 0;
+ SequenceI sq = null;
+ String sqname = null;
+ if (startAfter != null)
+ {
+ // try to find the sequence in the alignment
+ boolean matched = false;
+ while (i < sequences.size())
+ {
+ if (getSequenceAt(i++) == startAfter)
+ {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched)
+ {
+ i = 0;
+ }
+ }
+ while (i < sequences.size())
+ {
+ sq = getSequenceAt(i);
+ sqname = sq.getName();
+ if (sqname.equals(token) // exact match
+ || (b && // allow imperfect matches - case varies
+ (sqname.equalsIgnoreCase(token))))
+ {
+ return getSequenceAt(i);
+ }
+
+ i++;
+ }
+
+ return null;
+ }
+
+ @Override
+ public SequenceI[] findSequenceMatch(String name)
+ {
+ Vector matches = new Vector();
+ int i = 0;
+
+ while (i < sequences.size())
+ {
+ if (getSequenceAt(i).getName().equals(name))
+ {
+ matches.addElement(getSequenceAt(i));
+ }
+ i++;
+ }
+
+ SequenceI[] result = new SequenceI[matches.size()];
+ for (i = 0; i < result.length; i++)
+ {
+ result[i] = (SequenceI) matches.elementAt(i);
+ }
+
+ return result;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#findIndex(jalview.datamodel.SequenceI)
+ */
+ @Override
+ public int findIndex(SequenceI s)
+ {
+ int i = 0;
+
+ while (i < sequences.size())
+ {
+ if (s == getSequenceAt(i))
+ {
+ return i;
+ }
+
+ i++;
+ }
+
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.datamodel.AlignmentI#findIndex(jalview.datamodel.SearchResults)
+ */
+ @Override
+ public int findIndex(SearchResults results)
+ {
+ int i = 0;
+
+ while (i < sequences.size())
+ {
+ if (results.involvesSequence(getSequenceAt(i)))
+ {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ @Override
+ public int getHeight()
+ {
+ return sequences.size();
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ @Override
+ public int getWidth()
+ {
+ int maxLength = -1;
+
+ for (int i = 0; i < sequences.size(); i++)
+ {
+ if (getSequenceAt(i).getLength() > maxLength)
+ {
+ maxLength = getSequenceAt(i).getLength();
+ }
+ }
+
+ return maxLength;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param gc
+ * DOCUMENT ME!
+ */
+ @Override
+ public void setGapCharacter(char gc)
+ {
+ gapCharacter = gc;
+ synchronized (sequences)
+ {
+ for (SequenceI seq : sequences)
+ {
+ seq.setSequence(seq.getSequenceAsString().replace('.', gc)
+ .replace('-', gc).replace(' ', gc));
+ }
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ @Override
+ public char getGapCharacter()
+ {
+ return gapCharacter;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#isAligned()
+ */
+ @Override
+ public boolean isAligned()
+ {
+ return isAligned(false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AlignmentI#isAligned(boolean)
+ */
+ @Override
+ public boolean isAligned(boolean includeHidden)
+ {
+ int width = getWidth();
+ if (hiddenSequences == null || hiddenSequences.getSize() == 0)
+ {
+ includeHidden = true; // no hidden sequences to check against.
+ }
+ for (int i = 0; i < sequences.size(); i++)
+ {
+ if (includeHidden || !hiddenSequences.isHidden(getSequenceAt(i)))
+ {
+ if (getSequenceAt(i).getLength() != width)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seejalview.datamodel.AlignmentI#deleteAnnotation(jalview.datamodel.
+ * AlignmentAnnotation)
+ */
+ @Override
+ public boolean deleteAnnotation(AlignmentAnnotation aa)
+ {
+ return deleteAnnotation(aa, true);
+ }
+
+ @Override
+ public boolean deleteAnnotation(AlignmentAnnotation aa, boolean unhook)
+ {
+ int aSize = 1;