@VisibleForTesting
  static Row renameRow(
      Row row,
      Schema schema,
      @Nullable BitSet nestedRenames,
      Map<UUID, Schema> renamedSubSchemasMap,
      Map<UUID, BitSet> nestedFieldRenamedMap) {
    if (nestedRenames == null || nestedRenames.isEmpty()) {
      // Fast path, short circuit subschems.
      return Row.withSchema(schema).attachValues(row.getValues());
    } else {
      List<Object> values = Lists.newArrayListWithCapacity(row.getValues().size());
      for (int i = 0; i < schema.getFieldCount(); ++i) {
        if (nestedRenames.get(i)) {
          values.add(
              renameFieldValue(
                  row.getValue(i),
                  schema.getField(i).getType(),
                  renamedSubSchemasMap,
                  nestedFieldRenamedMap));
        } else {
          values.add(row.getValue(i));
        }
      }
      return Row.withSchema(schema).attachValues(values);
    }
  }
@Test
  public void testRenameRow() {
    Schema nestedSchema = Schema.builder().addStringField("field1").addInt32Field("field2").build();
    Schema schema =
        Schema.builder().addStringField("field1").addRowField("nested", nestedSchema).build();

    Schema expectedNestedSchema =
        Schema.builder().addStringField("bottom1").addInt32Field("bottom2").build();
    Schema expectedSchema =
        Schema.builder()
            .addStringField("top1")
            .addRowField("top_nested", expectedNestedSchema)
            .build();

    List<RenamePair> renames =
        ImmutableList.of(
                RenamePair.of(FieldAccessDescriptor.withFieldNames("field1"), "top1"),
                RenamePair.of(FieldAccessDescriptor.withFieldNames("nested"), "top_nested"),
                RenamePair.of(FieldAccessDescriptor.withFieldNames("nested.field1"), "bottom1"),
                RenamePair.of(FieldAccessDescriptor.withFieldNames("nested.field2"), "bottom2"))
            .stream()
            .map(r -> r.resolve(schema))
            .collect(Collectors.toList());

    final Map<UUID, Schema> renamedSchemasMap = Maps.newHashMap();
    final Map<UUID, BitSet> nestedFieldRenamedMap = Maps.newHashMap();
    RenameFields.renameSchema(schema, renames, renamedSchemasMap, nestedFieldRenamedMap);

    assertEquals(expectedSchema, renamedSchemasMap.get(schema.getUUID()));

    Row row =
        Row.withSchema(schema)
            .withFieldValue("field1", "one")
            .withFieldValue(
                "nested",
                Row.withSchema(nestedSchema)
                    .withFieldValue("field1", "one")
                    .withFieldValue("field2", 1)
                    .build())
            .build();
    Row expectedRow =
        Row.withSchema(expectedSchema)
            .withFieldValue("top1", "one")
            .withFieldValue(
                "top_nested",
                Row.withSchema(expectedNestedSchema)
                    .withFieldValue("bottom1", "one")
                    .withFieldValue("bottom2", 1)
                    .build())
            .build();

    Row renamedRow =
        RenameFields.renameRow(
            row,
            renamedSchemasMap.get(schema.getUUID()),
            nestedFieldRenamedMap.get(schema.getUUID()),
            renamedSchemasMap,
            nestedFieldRenamedMap);
    assertEquals(expectedRow, renamedRow);
  }