diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/Adapters.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/Adapters.java
index 217762d341..a936cf4c54 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/Adapters.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/Adapters.java
@@ -15,6 +15,7 @@
*/
package com.google.cloud.bigtable.hbase.adapters;
+import com.google.cloud.bigtable.hbase.adapters.read.ModelRowAdapter;
import com.google.cloud.bigtable.hbase.adapters.read.RowRangeAdapter;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Append;
@@ -38,6 +39,8 @@
public final class Adapters {
/** Constant ROW_ADAPTER */
public static final RowAdapter ROW_ADAPTER = new RowAdapter();
+ /** Constant MODEL_ROW_ADAPTER */
+ public static final ModelRowAdapter MODEL_ROW_ADAPTER = new ModelRowAdapter();
/** Constant FLAT_ROW_ADAPTER */
public static final FlatRowAdapter FLAT_ROW_ADAPTER = new FlatRowAdapter();
/** Constant APPEND_ADAPTER */
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/ModelRowAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/ModelRowAdapter.java
new file mode 100644
index 0000000000..9d4d07260b
--- /dev/null
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/ModelRowAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Google LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.cloud.bigtable.hbase.adapters.read;
+
+import com.google.cloud.bigtable.data.v2.models.Row;
+import com.google.cloud.bigtable.hbase.adapters.ResponseAdapter;
+import com.google.cloud.bigtable.hbase.util.ByteStringer;
+import com.google.cloud.bigtable.hbase.util.TimestampConverter;
+import com.google.common.collect.ImmutableList;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * Adapt between a {@link Row} and an hbase client {@link Result}.
+ */
+public class ModelRowAdapter implements ResponseAdapter {
+
+ @Override
+ public Result adaptResponse(Row response) {
+ if (response == null) {
+ return new Result();
+ }
+
+ ImmutableList.Builder hbaseCellBuilder = ImmutableList.builder();
+ byte[] rowKey = ByteStringer.extract(response.getKey());
+ for (com.google.cloud.bigtable.data.v2.models.RowCell rowCell : response.getCells()) {
+ // Cells with labels are for internal use, do not return them.
+ // TODO(kevinsi4508): Filter out targeted {@link WhileMatchFilter} labels.
+ if (rowCell.getLabels().size() > 0) {
+ continue;
+ }
+ byte[] familyNameBytes = Bytes.toBytes(rowCell.getFamily());
+ byte[] columnQualifier = ByteStringer.extract(rowCell.getQualifier());
+ long hbaseTimestamp = TimestampConverter.bigtable2hbase(rowCell.getTimestamp());
+ RowCell keyValue = new RowCell(
+ rowKey,
+ familyNameBytes,
+ columnQualifier,
+ hbaseTimestamp,
+ ByteStringer.extract(rowCell.getValue()));
+
+ hbaseCellBuilder.add(keyValue);
+ }
+
+ ImmutableList| hbaseCells = hbaseCellBuilder.build();
+ return Result.create(hbaseCells.toArray(new Cell[hbaseCells.size()]));
+ }
+}
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestModelRowAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestModelRowAdapter.java
new file mode 100644
index 0000000000..cb3459ec02
--- /dev/null
+++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestModelRowAdapter.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019 Google LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.cloud.bigtable.hbase.adapters.read;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.google.cloud.bigtable.data.v2.models.Row;
+import com.google.cloud.bigtable.data.v2.models.RowCell;
+import com.google.cloud.bigtable.hbase.util.ByteStringer;
+import com.google.common.collect.ImmutableList;
+import com.google.protobuf.ByteString;
+import java.util.Collections;
+import java.util.List;
+import org.apache.hadoop.hbase.client.Result;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for the {@link ModelRowAdapter}.
+ */
+@RunWith(JUnit4.class)
+public class TestModelRowAdapter {
+
+ private static final String FAMILY_1 = "firstFamily";
+ private static final String FAMILY_2 = "secondFamily";
+ private static final ByteString QUALIFIER_1 = ByteString.copyFromUtf8("qualifier1");
+ private static final ByteString QUALIFIER_2 = ByteString.copyFromUtf8("qualifier2");
+ private static final long TIMESTAMP_MS_1 = 12345600;
+ private static final long TIMESTAMP_MS_2 = 65432100;
+ private static final long TIMESTAMP_MS_3 = 92929292;
+ private static final long TIMESTAMP_MILLS_1 = TIMESTAMP_MS_1/1000;
+ private static final long TIMESTAMP_MILLS_2 = TIMESTAMP_MS_2/1000;
+ private static final String LABEL = "label";
+ private static final List LABEL_LIST = Collections.emptyList();
+ private static final ByteString VALUE_1 = ByteString.copyFromUtf8("test-value-1");
+ private static final ByteString VALUE_2 = ByteString.copyFromUtf8("test-value-2");
+ private static final ByteString VALUE_3 = ByteString.copyFromUtf8("test-value-3");
+ private static final ByteString VALUE_4 = ByteString.copyFromUtf8("test-value-4");
+ private static final ByteString ROW_KEY = ByteString.copyFromUtf8("test-key");
+
+ private ModelRowAdapter adapter = new ModelRowAdapter();
+
+ @Test
+ public void testAdaptResponseWhenNull(){
+ Result result = adapter.adaptResponse(null);
+ assertNull(result.rawCells());
+ }
+
+ @Test
+ public void testAdaptResWithEmptyRow(){
+ Row row = Row.create(ROW_KEY, Collections.emptyList());
+ Result result = adapter.adaptResponse(row);
+ assertEquals(0, result.rawCells().length);
+ }
+
+ @Test
+ public void testAdaptResWithMultipleRow(){
+ ImmutableList.Builder rowCells = ImmutableList.builder();
+ rowCells.add(RowCell.create(FAMILY_1, QUALIFIER_1, TIMESTAMP_MS_1, LABEL_LIST, VALUE_1));
+ rowCells.add(RowCell.create(FAMILY_1, QUALIFIER_2, TIMESTAMP_MS_2, LABEL_LIST, VALUE_2));
+ rowCells.add(RowCell.create(FAMILY_2, QUALIFIER_2, TIMESTAMP_MS_2, LABEL_LIST, VALUE_3));
+ rowCells.add(RowCell.create(FAMILY_2, QUALIFIER_1, TIMESTAMP_MS_1, LABEL_LIST, VALUE_4));
+
+ //Row containing Label, Should be ignored
+ rowCells.add(RowCell.create(FAMILY_1, QUALIFIER_2, TIMESTAMP_MS_3,
+ Collections.singletonList(LABEL), VALUE_1));
+ Row inputRow = Row.create(ROW_KEY, rowCells.build());
+
+ Result result = adapter.adaptResponse(inputRow);
+ assertEquals(4, result.rawCells().length);
+
+ // Duplicate row and row with label cells should be removed. The timestamp micros gets
+ // converted to millisecond accuracy.
+ byte[] keyArray = ByteStringer.extract(ROW_KEY);
+ org.apache.hadoop.hbase.Cell[] expectedCells = new org.apache.hadoop.hbase.Cell[] {
+ new com.google.cloud.bigtable.hbase.adapters.read.RowCell(keyArray, FAMILY_1.getBytes(),
+ QUALIFIER_1.toByteArray(), TIMESTAMP_MILLS_1, VALUE_1.toByteArray()),
+ new com.google.cloud.bigtable.hbase.adapters.read.RowCell(keyArray, FAMILY_1.getBytes(),
+ QUALIFIER_2.toByteArray(), TIMESTAMP_MILLS_2, VALUE_2.toByteArray()),
+ new com.google.cloud.bigtable.hbase.adapters.read.RowCell(keyArray, FAMILY_2.getBytes(),
+ QUALIFIER_2.toByteArray(), TIMESTAMP_MILLS_2, VALUE_3.toByteArray()),
+ new com.google.cloud.bigtable.hbase.adapters.read.RowCell(keyArray, FAMILY_2.getBytes(),
+ QUALIFIER_1.toByteArray(), TIMESTAMP_MILLS_1, VALUE_4.toByteArray()),
+ };
+ assertArrayEquals(expectedCells, result.rawCells());
+ }
+}
| |