protected ArrayList<Tag> coalesceTags() {
    ArrayList<Tag> result = new ArrayList<Tag>();

    // close all open tags
    for (ArrayList<BeginTag> tagList : openTags.values()) {
      for (BeginTag tag : tagList) {
        for (Pattern p : whitelist) {
          if (p.matcher(tag.name).matches()) {
            result.add(new Tag(tag.name, tag.attributes, tag.termPosition, tag.termPosition, tag.bytePosition, tag.bytePosition));
            break;
          }
        }
      }
    }

    for (ClosedTag tag : closedTags) {
      for (Pattern p : whitelist) {
        if (p.matcher(tag.name).matches()) {
          result.add(new Tag(tag.name, tag.attributes, tag.termStart, tag.termEnd, tag.byteStart, tag.byteEnd));
          break;
        }
      }
    }

    Collections.sort(result);
    return result;
  }