private String rangesAsString() {
   assert !ranges.isEmpty();
   StringBuilder sb = new StringBuilder();
   AbstractType at = (AbstractType) ranges.comparator();
   assert at != null;
   for (RangeTombstone i : ranges) {
     sb.append("[");
     sb.append(at.getString(i.min)).append("-");
     sb.append(at.getString(i.max)).append(", ");
     sb.append(i.data);
     sb.append("]");
   }
   return sb.toString();
 }
 /**
  * Return a new DeletionInfo correspond to purging every tombstones that are older than {@code
  * gcbefore}.
  *
  * @param gcBefore timestamp (in seconds) before which tombstones should be purged
  * @return a new DeletionInfo with the purged info remove. Should return DeletionInfo.LIVE if no
  *     tombstones remain.
  */
 public DeletionInfo purge(int gcBefore) {
   if (ranges.isEmpty()) {
     return topLevel.localDeletionTime < gcBefore ? LIVE : this;
   } else {
     // We rebuild a new intervalTree that contains only non expired range tombstones
     List<RangeTombstone> nonExpired = new ArrayList<RangeTombstone>();
     for (RangeTombstone range : ranges) {
       if (range.data.localDeletionTime >= gcBefore) nonExpired.add(range);
     }
     IntervalTree<ByteBuffer, DeletionTime, RangeTombstone> newRanges =
         nonExpired.size() == ranges.intervalCount()
             ? ranges
             : IntervalTree.build(nonExpired, ranges.comparator());
     return topLevel.localDeletionTime < gcBefore
         ? new DeletionInfo(DeletionTime.LIVE, newRanges)
         : new DeletionInfo(topLevel, newRanges);
   }
 }
 /** Returns a new DeletionInfo containing of this plus the provided {@code newInfo}. */
 public DeletionInfo add(DeletionInfo newInfo) {
   if (ranges.isEmpty()) {
     return topLevel.markedForDeleteAt < newInfo.topLevel.markedForDeleteAt
         ? newInfo
         : newInfo.ranges.isEmpty() ? this : new DeletionInfo(topLevel, newInfo.ranges);
   } else {
     if (newInfo.ranges.isEmpty()) {
       return topLevel.markedForDeleteAt < newInfo.topLevel.markedForDeleteAt
           ? new DeletionInfo(newInfo.topLevel, ranges)
           : this;
     } else {
       // Need to merge both ranges
       Set<RangeTombstone> merged = new HashSet<RangeTombstone>();
       Iterables.addAll(merged, Iterables.concat(ranges, newInfo.ranges));
       return new DeletionInfo(
           topLevel.markedForDeleteAt < newInfo.topLevel.markedForDeleteAt
               ? newInfo.topLevel
               : topLevel,
           IntervalTree.build(merged, ranges.comparator()));
     }
   }
 }