@Override
 public RowFilter adapt(FilterAdapterContext context, TimestampsFilter filter) {
   Interleave.Builder interleaveBuilder = RowFilter.Interleave.newBuilder();
   for (long timestamp : filter.getTimestamps()) {
     // HBase TimestampsFilters are of the form: [N, M], however; bigtable
     // uses [N, M) to express timestamp ranges. In order to express an HBase
     // single point timestamp [M, M], we need to specify [M, M+1) to bigtable.
     long bigtableStartTimestamp =
         BigtableConstants.BIGTABLE_TIMEUNIT.convert(timestamp, BigtableConstants.HBASE_TIMEUNIT);
     long bigtableEndTimestamp =
         BigtableConstants.BIGTABLE_TIMEUNIT.convert(
             timestamp + 1, BigtableConstants.HBASE_TIMEUNIT);
     interleaveBuilder.addFilters(
         RowFilter.newBuilder()
             .setTimestampRangeFilter(
                 TimestampRange.newBuilder()
                     .setStartTimestampMicros(bigtableStartTimestamp)
                     .setEndTimestampMicros(bigtableEndTimestamp)));
   }
   return RowFilter.newBuilder().setInterleave(interleaveBuilder).build();
 }
  private RowFilter createColumnFamilyFilter(Scan scan) {
    // Build a filter of the form:
    // (fam1 | (qual1 + qual2 + qual3)) + (fam2 | qual1) + (fam3)
    RowFilter.Interleave.Builder interleaveBuilder = RowFilter.Interleave.newBuilder();
    Map<byte[], NavigableSet<byte[]>> familyMap = scan.getFamilyMap();
    if (!scan.getFamilyMap().isEmpty()) {
      for (Map.Entry<byte[], NavigableSet<byte[]>> entry : familyMap.entrySet()) {
        if (entry.getValue() == null) {
          // No qualifier, add the entire family:
          interleaveBuilder.addFilters(createFamilyFilter(entry.getKey()));
        } else if (entry.getValue().size() == 1) {
          // Build filter of the form "family | qual"
          Chain.Builder familyBuilder = interleaveBuilder.addFiltersBuilder().getChainBuilder();
          familyBuilder.addFilters(createFamilyFilter(entry.getKey()));
          familyBuilder.addFilters(createColumnQualifierFilter(entry.getValue().first()));
        } else {
          // Build filter of the form "family | (qual1 + qual2 + qual3)"
          Chain.Builder familyBuilder = interleaveBuilder.addFiltersBuilder().getChainBuilder();
          familyBuilder.addFilters(createFamilyFilter(entry.getKey()));
          // Add a qualifier filter for each specified qualifier:
          Interleave.Builder columnFilters =
              familyBuilder.addFiltersBuilder().getInterleaveBuilder();
          for (byte[] qualifier : entry.getValue()) {
            columnFilters.addFilters(createColumnQualifierFilter(qualifier));
          }
        }
      }
    } else {
      // Simplify processing a bit and add an explicit inclusion of all families:
      interleaveBuilder.addFiltersBuilder().setFamilyNameRegexFilter(".*");
    }

    if (interleaveBuilder.getFiltersCount() > 1) {
      return RowFilter.newBuilder().setInterleave(interleaveBuilder).build();
    } else {
      return interleaveBuilder.getFilters(0);
    }
  }