X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FHiddenColumns.java;h=c0a43eea64ba09df70ed8e5686e58334ecb772f0;hb=3d0101179759ef157b088ea135423cd909512d9f;hp=be107211b95853ec93fb338956585ff94bff9fe9;hpb=ab67e99fb7336d0f4411488d9f843c720ab6b418;p=jalview.git diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index be10721..c0a43ee 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -33,19 +33,51 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class HiddenColumns { private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock(); - + /* * list of hidden column [start, end] ranges; the list is maintained in * ascending start column order */ - private Vector hiddenColumns; + private ArrayList hiddenColumns; + + /** + * Constructor + */ + public HiddenColumns() + { + } /** - * This Method is used to return all the HiddenColumn regions + * Copy constructor + * + * @param copy + */ + public HiddenColumns(HiddenColumns copy) + { + try + { + LOCK.writeLock().lock(); + if (copy != null) + { + if (copy.hiddenColumns != null) + { + hiddenColumns = copy.copyHiddenRegionsToArrayList(); + } + } + } finally + { + LOCK.writeLock().unlock(); + } + } + + /** + * This method is used to return all the HiddenColumn regions and is intended + * to remain private. External callers which need a copy of the regions can + * call getHiddenColumnsCopyAsList. * * @return empty list or List of hidden column intervals */ - public List getHiddenRegions() + private List getHiddenRegions() { return hiddenColumns == null ? Collections. emptyList() : hiddenColumns; @@ -67,13 +99,16 @@ public class HiddenColumns { LOCK.readLock().lock(); StringBuilder regionBuilder = new StringBuilder(); - for (int[] range : hiddenColumns) + if (hiddenColumns != null) { - regionBuilder.append(delimiter).append(range[0]).append(between) - .append(range[1]); - } + for (int[] range : hiddenColumns) + { + regionBuilder.append(delimiter).append(range[0]).append(between) + .append(range[1]); + } - regionBuilder.deleteCharAt(0); + regionBuilder.deleteCharAt(0); + } return regionBuilder.toString(); } finally { @@ -92,7 +127,7 @@ public class HiddenColumns { LOCK.readLock().lock(); int size = 0; - if (hasHidden()) + if (hasHiddenColumns()) { for (int[] range : hiddenColumns) { @@ -100,29 +135,10 @@ public class HiddenColumns } } return size; - } - finally - { - LOCK.readLock().unlock(); - } - } - - /** - * Answers if there are any hidden columns - * - * @return true if there are hidden columns - */ - public boolean hasHidden() - { - try - { - LOCK.readLock().lock(); - return (hiddenColumns != null) && (!hiddenColumns.isEmpty()); } finally { LOCK.readLock().unlock(); } - } @Override @@ -183,7 +199,7 @@ public class HiddenColumns { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); if (result >= region[0]) { result += region[1] - region[0] + 1; @@ -218,7 +234,7 @@ public class HiddenColumns int[] region; do { - region = hiddenColumns.elementAt(index++); + region = hiddenColumns.get(index++); if (hiddenColumn > region[1]) { result -= region[1] + 1 - region[0]; @@ -273,47 +289,47 @@ public class HiddenColumns { LOCK.readLock().lock(); - int distance = visibleDistance; + int distance = visibleDistance; - // in case startColumn is in a hidden region, move it to the left - int start = adjustForHiddenColumns(findColumnPosition(startColumn)); + // in case startColumn is in a hidden region, move it to the left + int start = adjustForHiddenColumns(findColumnPosition(startColumn)); - // get index of hidden region to left of start - int index = getHiddenIndexLeft(start); - if (index == -1) - { - // no hidden regions to left of startColumn - return start - distance; - } + // get index of hidden region to left of start + int index = getHiddenIndexLeft(start); + if (index == -1) + { + // no hidden regions to left of startColumn + return start - distance; + } - // walk backwards through the alignment subtracting the counts of visible - // columns from distance - int[] region; - int gap = 0; - int nextstart = start; + // walk backwards through the alignment subtracting the counts of visible + // columns from distance + int[] region; + int gap = 0; + int nextstart = start; - while ((index > -1) && (distance - gap > 0)) - { - // subtract the gap to right of region from distance - distance -= gap; - start = nextstart; + while ((index > -1) && (distance - gap > 0)) + { + // subtract the gap to right of region from distance + distance -= gap; + start = nextstart; - // calculate the next gap - region = hiddenColumns.get(index); - gap = start - region[1]; + // calculate the next gap + region = hiddenColumns.get(index); + gap = start - region[1]; - // set start to just to left of current region - nextstart = region[0] - 1; - index--; - } + // set start to just to left of current region + nextstart = region[0] - 1; + index--; + } - if (distance - gap > 0) - { - // fell out of loop because there are no more hidden regions - distance -= gap; - return nextstart - distance; - } - return start - distance; + if (distance - gap > 0) + { + // fell out of loop because there are no more hidden regions + distance -= gap; + return nextstart - distance; + } + return start - distance; } finally { LOCK.readLock().unlock(); @@ -331,34 +347,41 @@ public class HiddenColumns try { LOCK.readLock().lock(); - List positions = new ArrayList<>( - hiddenColumns.size()); + List positions = null; - positions.add(hiddenColumns.elementAt(0)[0]); - for (int i = 1; i < hiddenColumns.size(); ++i) + if (hiddenColumns != null) { + positions = new ArrayList<>(hiddenColumns.size()); - int result = 0; - if (hiddenColumns != null) + positions.add(hiddenColumns.get(0)[0]); + for (int i = 1; i < hiddenColumns.size(); ++i) { - int index = 0; - int gaps = 0; - do + + int result = 0; + if (hiddenColumns != null) { - int[] region = hiddenColumns.elementAt(index); - gaps += region[1] + 1 - region[0]; - result = region[1] + 1; - index++; - } while (index <= i); + int index = 0; + int gaps = 0; + do + { + int[] region = hiddenColumns.get(index); + gaps += region[1] + 1 - region[0]; + result = region[1] + 1; + index++; + } while (index <= i); - result -= gaps; + result -= gaps; + } + positions.add(result); } - positions.add(result); + } + else + { + positions = new ArrayList<>(); } return positions; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -381,7 +404,7 @@ public class HiddenColumns int index = 0; do { - int[] region = hiddenColumns.elementAt(index); + int[] region = hiddenColumns.get(index); if (alPos < region[0]) { return region[0]; @@ -412,22 +435,22 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - int index = hiddenColumns.size() - 1; - do + if (hiddenColumns != null) { - int[] region = hiddenColumns.elementAt(index); - if (alPos > region[1]) + int index = hiddenColumns.size() - 1; + do { - return region[1]; - } + int[] region = hiddenColumns.get(index); + if (alPos > region[1]) + { + return region[1]; + } - index--; - } while (index > -1); - } + index--; + } while (index > -1); + } - return alPos; + return alPos; } finally { LOCK.readLock().unlock(); @@ -448,22 +471,22 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - int index = hiddenColumns.size() - 1; - do + if (hiddenColumns != null) { - int[] region = hiddenColumns.elementAt(index); - if (pos > region[1]) + int index = hiddenColumns.size() - 1; + do { - return index; - } + int[] region = hiddenColumns.get(index); + if (pos > region[1]) + { + return index; + } - index--; - } while (index > -1); - } + index--; + } while (index > -1); + } - return -1; + return -1; } finally { LOCK.readLock().unlock(); @@ -479,28 +502,23 @@ public class HiddenColumns */ public void hideColumns(int start, int end) { - hideColumns(start, end, false); - } - - /** - * Adds the specified column range to the hidden columns - * - * @param start - * @param end - */ - private void hideColumns(int start, int end, boolean alreadyLocked) - { + boolean wasAlreadyLocked = false; try { - - if (!alreadyLocked) + // check if the write lock was already locked by this thread, + // as this method can be called internally in loops within HiddenColumns + if (!LOCK.isWriteLockedByCurrentThread()) { LOCK.writeLock().lock(); } + else + { + wasAlreadyLocked = true; + } if (hiddenColumns == null) { - hiddenColumns = new Vector<>(); + hiddenColumns = new ArrayList<>(); } /* @@ -509,14 +527,14 @@ public class HiddenColumns */ for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); if (end < region[0] - 1) { /* * insert discontiguous preceding range */ - hiddenColumns.insertElementAt(new int[] { start, end }, i); + hiddenColumns.add(i, new int[] { start, end }); return; } @@ -558,15 +576,15 @@ public class HiddenColumns } return; } - } + } - /* - * remaining case is that the new range follows everything else - */ - hiddenColumns.addElement(new int[] { start, end }); + /* + * remaining case is that the new range follows everything else + */ + hiddenColumns.add(new int[] { start, end }); } finally { - if (!alreadyLocked) + if (!wasAlreadyLocked) { LOCK.writeLock().unlock(); } @@ -579,82 +597,38 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - for (int[] region : hiddenColumns) + if (hiddenColumns != null) { - if (column >= region[0] && column <= region[1]) + for (int[] region : hiddenColumns) { - return false; + if (column >= region[0] && column <= region[1]) + { + return false; + } } } - } - return true; + return true; } finally { LOCK.readLock().unlock(); } } - /** - * ColumnSelection - */ - public HiddenColumns() - { - } - - /** - * Copy constructor - * - * @param copy - */ - public HiddenColumns(HiddenColumns copy) - { - try - { - - LOCK.readLock().lock(); - if (copy != null) - { - if (copy.hiddenColumns != null) - { - hiddenColumns = copy.copyHiddenRegions(); - } - } - } - finally - { - LOCK.readLock().unlock(); - } - } - - private Vector copyHiddenRegions() + private ArrayList copyHiddenRegionsToArrayList() { - Vector copy = new Vector<>(hiddenColumns.size()); - for (int i = 0, j = hiddenColumns.size(); i < j; i++) + int size = 0; + if (hiddenColumns != null) { - int[] rh; - int[] cp; - rh = hiddenColumns.elementAt(i); - if (rh != null) - { - cp = new int[rh.length]; - System.arraycopy(rh, 0, cp, 0, rh.length); - copy.addElement(cp); - } + size = hiddenColumns.size(); } - return copy; - } + ArrayList copy = new ArrayList<>(size); - private ArrayList copyHiddenRegionsToArrayList() - { - ArrayList copy = new ArrayList<>(hiddenColumns.size()); - for (int i = 0, j = hiddenColumns.size(); i < j; i++) + for (int i = 0, j = size; i < j; i++) { int[] rh; int[] cp; - rh = hiddenColumns.elementAt(i); + rh = hiddenColumns.get(i); if (rh != null) { cp = new int[rh.length]; @@ -662,22 +636,19 @@ public class HiddenColumns copy.add(cp); } } - return copy; - } - public Vector getHiddenColumnsCopy() - { - try - { - LOCK.readLock().lock(); - return copyHiddenRegions(); - } finally - { - LOCK.readLock().unlock(); - } + return copy; } - public ArrayList getHiddenColumnsCopyAsList() + /** + * Returns a copy of the vector of hidden regions, as an ArrayList. Before + * using this method please consider if you really need access to the hidden + * regions - a new (or existing!) method on HiddenColumns might be more + * appropriate. + * + * @return hidden regions as an ArrayList of [start,end] pairs + */ + public ArrayList getHiddenColumnsCopy() { try { @@ -711,12 +682,12 @@ public class HiddenColumns int hSize = hiddenColumns.size(); for (int i = 0; i < hSize; i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); if (region[0] > start && start + change > region[1]) { deletedHiddenColumns.add(region); - hiddenColumns.removeElementAt(i); + hiddenColumns.remove(i); i--; hSize--; continue; @@ -763,7 +734,7 @@ public class HiddenColumns { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); if (region[0] >= start) { region[0] -= change; @@ -774,7 +745,7 @@ public class HiddenColumns } if (region[1] < region[0]) { - hiddenColumns.removeElementAt(i--); + hiddenColumns.remove(i--); } if (region[0] < 0) @@ -787,8 +758,7 @@ public class HiddenColumns } } } - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -855,8 +825,7 @@ public class HiddenColumns { return new int[] { start, end - 1 }; } - } - finally + } finally { LOCK.readLock().unlock(); } @@ -869,7 +838,7 @@ public class HiddenColumns { LOCK.readLock().lock(); int iSize = seqs.length; - String selections[] = new String[iSize]; + String[] selections = new String[iSize]; if (hiddenColumns != null && hiddenColumns.size() > 0) { for (int i = 0; i < iSize; i++) @@ -925,8 +894,7 @@ public class HiddenColumns } return selections; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1019,8 +987,7 @@ public class HiddenColumns } // otherwise, sequence was completely hidden return new int[] { visPrev, visNext, 0, 0, firstP, lastP }; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1141,8 +1108,7 @@ public class HiddenColumns { alignmentAnnotation.restrict(start, end); } - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1194,7 +1160,7 @@ public class HiddenColumns List inserts = sr.getInsertions(); for (int[] r : inserts) { - hideColumns(r[0], r[1], true); + hideColumns(r[0], r[1]); } } finally { @@ -1214,7 +1180,7 @@ public class HiddenColumns { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); for (int j = region[0]; j < region[1] + 1; j++) { sel.addElement(j); @@ -1223,8 +1189,7 @@ public class HiddenColumns } hiddenColumns = null; - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -1243,7 +1208,7 @@ public class HiddenColumns LOCK.writeLock().lock(); for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = hiddenColumns.elementAt(i); + int[] region = hiddenColumns.get(i); if (start == region[0]) { for (int j = region[0]; j < region[1] + 1; j++) @@ -1251,7 +1216,7 @@ public class HiddenColumns sel.addElement(j); } - hiddenColumns.removeElement(region); + hiddenColumns.remove(region); break; } } @@ -1259,8 +1224,7 @@ public class HiddenColumns { hiddenColumns = null; } - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -1274,16 +1238,16 @@ public class HiddenColumns * @param intervals * @return */ - private boolean pruneIntervalVector(final List shifts, - Vector intervals) + private boolean pruneIntervalList(final List shifts, + ArrayList intervals) { boolean pruned = false; int i = 0; int j = intervals.size() - 1; int s = 0; int t = shifts.size() - 1; - int hr[] = intervals.elementAt(i); - int sr[] = shifts.get(s); + int[] hr = intervals.get(i); + int[] sr = shifts.get(s); while (i <= j && s <= t) { boolean trailinghn = hr[1] >= sr[0]; @@ -1291,7 +1255,7 @@ public class HiddenColumns { if (i < j) { - hr = intervals.elementAt(++i); + hr = intervals.get(++i); } else { @@ -1319,12 +1283,12 @@ public class HiddenColumns { if (trailinghc) { // deleted hidden region. - intervals.removeElementAt(i); + intervals.remove(i); pruned = true; j--; if (i <= j) { - hr = intervals.elementAt(i); + hr = intervals.get(i); } continue; } @@ -1378,14 +1342,13 @@ public class HiddenColumns // delete any intervals intersecting. if (hiddenColumns != null) { - pruneIntervalVector(shifts, hiddenColumns); + pruneIntervalList(shifts, hiddenColumns); if (hiddenColumns != null && hiddenColumns.size() == 0) { hiddenColumns = null; } } - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -1434,8 +1397,7 @@ public class HiddenColumns // recover mapping between sequence's non-gap positions and positions // mapping to view. pruneDeletions(ShiftList.parseMap(origseq.gapMap())); - int[] viscontigs = al.getHiddenColumns().getVisibleContigs(0, - profileseq.getLength()); + int[] viscontigs = getVisibleContigs(0, profileseq.getLength()); int spos = 0; int offset = 0; @@ -1484,9 +1446,8 @@ public class HiddenColumns } else { - al.getSequenceAt(s).setSequence( - sq.substring(0, spos + offset) + sb.toString() - + sq.substring(spos + offset)); + al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset) + + sb.toString() + sq.substring(spos + offset)); } } } @@ -1498,7 +1459,8 @@ public class HiddenColumns { // pad the final region with gaps. StringBuffer sb = new StringBuffer(); - for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++) + for (int s = 0, ns = profileseq.getLength() - spos + - offset; s < ns; s++) { sb.append(gc); } @@ -1600,8 +1562,7 @@ public class HiddenColumns } } return hashCode; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1623,7 +1584,7 @@ public class HiddenColumns .nextSetBit(lastSet)) { lastSet = inserts.nextClearBit(firstSet); - hideColumns(firstSet, lastSet - 1, true); + hideColumns(firstSet, lastSet - 1); } } finally { @@ -1649,8 +1610,7 @@ public class HiddenColumns { inserts.set(range[0], range[1] + 1); } - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1711,4 +1671,37 @@ public class HiddenColumns } + /** + * Finds the hidden region (if any) which starts or ends at res + * + * @param res + * visible residue position, unadjusted for hidden columns + * @return region as [start,end] or null if no matching region is found + */ + public int[] getRegionWithEdgeAtRes(int res) + { + try + { + LOCK.readLock().lock(); + int adjres = adjustForHiddenColumns(res); + + int[] reveal = null; + if (hiddenColumns != null) + { + for (int[] region : hiddenColumns) + { + if (adjres + 1 == region[0] || adjres - 1 == region[1]) + { + reveal = region; + break; + } + } + } + return reveal; + } finally + { + LOCK.readLock().unlock(); + } + } + }