001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.io.ByteArrayOutputStream;
026import java.io.IOException;
027import java.math.BigDecimal;
028import java.nio.ByteBuffer;
029import java.util.ArrayList;
030import java.util.List;
031import java.util.NavigableMap;
032import java.util.TreeMap;
033import org.apache.hadoop.hbase.testclassification.MiscTests;
034import org.apache.hadoop.hbase.testclassification.SmallTests;
035import org.apache.hadoop.hbase.util.Bytes;
036import org.junit.Assert;
037import org.junit.ClassRule;
038import org.junit.Test;
039import org.junit.experimental.categories.Category;
040import org.mockito.Mockito;
041
042@Category({MiscTests.class, SmallTests.class})
043public class TestCellUtil {
044
045  @ClassRule
046  public static final HBaseClassTestRule CLASS_RULE =
047      HBaseClassTestRule.forClass(TestCellUtil.class);
048
049  /**
050   * CellScannable used in test. Returns a {@link TestCellScanner}
051   */
052  private static class TestCellScannable implements CellScannable {
053    private final int cellsCount;
054    TestCellScannable(final int cellsCount) {
055      this.cellsCount = cellsCount;
056    }
057    @Override
058    public CellScanner cellScanner() {
059      return new TestCellScanner(this.cellsCount);
060    }
061  }
062
063  /**
064   * CellScanner used in test.
065   */
066  private static class TestCellScanner implements CellScanner {
067    private int count = 0;
068    private Cell current = null;
069    private final int cellsCount;
070
071    TestCellScanner(final int cellsCount) {
072      this.cellsCount = cellsCount;
073    }
074
075    @Override
076    public Cell current() {
077      return this.current;
078    }
079
080    @Override
081    public boolean advance() throws IOException {
082      if (this.count < cellsCount) {
083        this.current = new TestCell(this.count);
084        this.count++;
085        return true;
086      }
087      return false;
088    }
089  }
090
091  /**
092   * Cell used in test. Has row only.
093   */
094  private static class TestCell implements Cell {
095    private final byte [] row;
096
097    TestCell(final int i) {
098      this.row = Bytes.toBytes(i);
099    }
100
101    @Override
102    public byte[] getRowArray() {
103      return this.row;
104    }
105
106    @Override
107    public int getRowOffset() {
108      return 0;
109    }
110
111    @Override
112    public short getRowLength() {
113      return (short)this.row.length;
114    }
115
116    @Override
117    public byte[] getFamilyArray() {
118      // TODO Auto-generated method stub
119      return null;
120    }
121
122    @Override
123    public int getFamilyOffset() {
124      // TODO Auto-generated method stub
125      return 0;
126    }
127
128    @Override
129    public byte getFamilyLength() {
130      // TODO Auto-generated method stub
131      return 0;
132    }
133
134    @Override
135    public byte[] getQualifierArray() {
136      // TODO Auto-generated method stub
137      return null;
138    }
139
140    @Override
141    public int getQualifierOffset() {
142      // TODO Auto-generated method stub
143      return 0;
144    }
145
146    @Override
147    public int getQualifierLength() {
148      // TODO Auto-generated method stub
149      return 0;
150    }
151
152    @Override
153    public long getTimestamp() {
154      // TODO Auto-generated method stub
155      return 0;
156    }
157
158    @Override
159    public byte getTypeByte() {
160      // TODO Auto-generated method stub
161      return 0;
162    }
163
164    @Override
165    public byte[] getValueArray() {
166      // TODO Auto-generated method stub
167      return null;
168    }
169
170    @Override
171    public int getValueOffset() {
172      // TODO Auto-generated method stub
173      return 0;
174    }
175
176    @Override
177    public int getValueLength() {
178      // TODO Auto-generated method stub
179      return 0;
180    }
181
182    @Override
183    public byte[] getTagsArray() {
184      // TODO Auto-generated method stub
185      return null;
186    }
187
188    @Override
189    public int getTagsOffset() {
190      // TODO Auto-generated method stub
191      return 0;
192    }
193
194    @Override
195    public long getSequenceId() {
196      // TODO Auto-generated method stub
197      return 0;
198    }
199
200    @Override
201    public int getTagsLength() {
202      // TODO Auto-generated method stub
203      return 0;
204    }
205  }
206
207  /**
208   * Was overflowing if 100k or so lists of cellscanners to return.
209   */
210  @Test
211  public void testCreateCellScannerOverflow() throws IOException {
212    consume(doCreateCellScanner(1, 1), 1 * 1);
213    consume(doCreateCellScanner(3, 0), 3 * 0);
214    consume(doCreateCellScanner(3, 3), 3 * 3);
215    consume(doCreateCellScanner(0, 1), 0 * 1);
216    // Do big number. See HBASE-11813 for why.
217    final int hundredK = 100000;
218    consume(doCreateCellScanner(hundredK, 0), hundredK * 0);
219    consume(doCreateCellArray(1), 1);
220    consume(doCreateCellArray(0), 0);
221    consume(doCreateCellArray(3), 3);
222    List<CellScannable> cells = new ArrayList<>(hundredK);
223    for (int i = 0; i < hundredK; i++) {
224      cells.add(new TestCellScannable(1));
225    }
226    consume(CellUtil.createCellScanner(cells), hundredK * 1);
227    NavigableMap<byte [], List<Cell>> m = new TreeMap<>(Bytes.BYTES_COMPARATOR);
228    List<Cell> cellArray = new ArrayList<>(hundredK);
229    for (int i = 0; i < hundredK; i++) {
230      cellArray.add(new TestCell(i));
231    }
232    m.put(new byte [] {'f'}, cellArray);
233    consume(CellUtil.createCellScanner(m), hundredK * 1);
234  }
235
236  private CellScanner doCreateCellArray(final int itemsPerList) {
237    Cell [] cells = new Cell [itemsPerList];
238    for (int i = 0; i < itemsPerList; i++) {
239      cells[i] = new TestCell(i);
240    }
241    return CellUtil.createCellScanner(cells);
242  }
243
244  private CellScanner doCreateCellScanner(final int listsCount, final int itemsPerList)
245  throws IOException {
246    List<CellScannable> cells = new ArrayList<>(listsCount);
247    for (int i = 0; i < listsCount; i++) {
248      CellScannable cs = new CellScannable() {
249        @Override
250        public CellScanner cellScanner() {
251          return new TestCellScanner(itemsPerList);
252        }
253      };
254      cells.add(cs);
255    }
256    return CellUtil.createCellScanner(cells);
257  }
258
259  private void consume(final CellScanner scanner, final int expected) throws IOException {
260    int count = 0;
261    while (scanner.advance()) {
262      count++;
263    }
264    Assert.assertEquals(expected, count);
265  }
266
267  @Test
268  public void testOverlappingKeys() {
269    byte[] empty = HConstants.EMPTY_BYTE_ARRAY;
270    byte[] a = Bytes.toBytes("a");
271    byte[] b = Bytes.toBytes("b");
272    byte[] c = Bytes.toBytes("c");
273    byte[] d = Bytes.toBytes("d");
274
275    // overlaps
276    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, a, b));
277    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, c, a, b));
278    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, a, c));
279    Assert.assertTrue(PrivateCellUtil.overlappingKeys(b, c, a, c));
280    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, c, b, c));
281    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, d, b, c));
282    Assert.assertTrue(PrivateCellUtil.overlappingKeys(b, c, a, d));
283
284    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, b, a, b));
285    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, b, a, c));
286
287    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, b));
288    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, c));
289
290    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, empty, a, b));
291    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, empty, a, c));
292
293    Assert.assertTrue(PrivateCellUtil.overlappingKeys(a, b, empty, empty));
294    Assert.assertTrue(PrivateCellUtil.overlappingKeys(empty, empty, a, b));
295
296    // non overlaps
297    Assert.assertFalse(PrivateCellUtil.overlappingKeys(a, b, c, d));
298    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, d, a, b));
299
300    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, c, d));
301    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, c, empty));
302    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, d, empty));
303    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, d, b, c));
304    Assert.assertFalse(PrivateCellUtil.overlappingKeys(c, empty, b, c));
305    Assert.assertFalse(PrivateCellUtil.overlappingKeys(d, empty, b, c));
306
307    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, a, b));
308    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, empty, b));
309    Assert.assertFalse(PrivateCellUtil.overlappingKeys(b, c, empty, a));
310    Assert.assertFalse(PrivateCellUtil.overlappingKeys(a,b, b, c));
311    Assert.assertFalse(PrivateCellUtil.overlappingKeys(empty, b, b, c));
312    Assert.assertFalse(PrivateCellUtil.overlappingKeys(empty, a, b, c));
313  }
314
315  @Test
316  public void testFindCommonPrefixInFlatKey() {
317    // The whole key matching case
318    KeyValue kv1 = new KeyValue(Bytes.toBytes("r1"), Bytes.toBytes("f1"),
319        Bytes.toBytes("q1"), null);
320    Assert.assertEquals(kv1.getKeyLength(),
321      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, true, true));
322    Assert.assertEquals(kv1.getKeyLength(),
323      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, false, true));
324    Assert.assertEquals(kv1.getKeyLength() - KeyValue.TIMESTAMP_TYPE_SIZE,
325      PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv1, true, false));
326    // The rk length itself mismatch
327    KeyValue kv2 = new KeyValue(Bytes.toBytes("r12"), Bytes.toBytes("f1"),
328        Bytes.toBytes("q1"), null);
329    Assert.assertEquals(1, PrivateCellUtil.findCommonPrefixInFlatKey(kv1, kv2, true, true));
330    // part of rk is same
331    KeyValue kv3 = new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f1"),
332        Bytes.toBytes("q1"), null);
333    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + Bytes.toBytes("r1").length,
334      PrivateCellUtil.findCommonPrefixInFlatKey(kv2, kv3, true, true));
335    // entire rk is same but different cf name
336    KeyValue kv4 = new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f2"),
337        Bytes.toBytes("q1"), null);
338    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + kv3.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
339        + Bytes.toBytes("f").length,
340        PrivateCellUtil.findCommonPrefixInFlatKey(kv3, kv4, false, true));
341    // rk and family are same and part of qualifier
342    KeyValue kv5 = new KeyValue(Bytes.toBytes("r14"), Bytes.toBytes("f2"),
343        Bytes.toBytes("q123"), null);
344    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + kv3.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
345        + kv4.getFamilyLength() + kv4.getQualifierLength(),
346        PrivateCellUtil.findCommonPrefixInFlatKey(kv4, kv5, true, true));
347    // rk, cf and q are same. ts differs
348    KeyValue kv6 = new KeyValue(Bytes.toBytes("rk"), 1234L);
349    KeyValue kv7 = new KeyValue(Bytes.toBytes("rk"), 1235L);
350    // only last byte out of 8 ts bytes in ts part differs
351    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
352        + kv6.getFamilyLength() + kv6.getQualifierLength() + 7,
353        PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv7, true, true));
354    // rk, cf, q and ts are same. Only type differs
355    KeyValue kv8 = new KeyValue(Bytes.toBytes("rk"), 1234L, KeyValue.Type.Delete);
356    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
357        + kv6.getFamilyLength() + kv6.getQualifierLength() + KeyValue.TIMESTAMP_SIZE,
358        PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv8, true, true));
359    // With out TS_TYPE check
360    Assert.assertEquals(KeyValue.ROW_LENGTH_SIZE + kv6.getRowLength() + KeyValue.FAMILY_LENGTH_SIZE
361        + kv6.getFamilyLength() + kv6.getQualifierLength(),
362        PrivateCellUtil.findCommonPrefixInFlatKey(kv6, kv8, true, false));
363  }
364
365  /**
366   * Assert CellUtil makes Cell toStrings same way we do KeyValue toStrings.
367   */
368  @Test
369  public void testToString() {
370    byte [] row = Bytes.toBytes("row");
371    long ts = 123L;
372    // Make a KeyValue and a Cell and see if same toString result.
373    KeyValue kv = new KeyValue(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
374        ts, KeyValue.Type.Minimum, HConstants.EMPTY_BYTE_ARRAY);
375    Cell cell = CellUtil.createCell(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
376        ts, KeyValue.Type.Minimum.getCode(), HConstants.EMPTY_BYTE_ARRAY);
377    String cellToString = CellUtil.getCellKeyAsString(cell);
378    assertEquals(kv.toString(), cellToString);
379    // Do another w/ non-null family.
380    byte [] f = new byte [] {'f'};
381    byte [] q = new byte [] {'q'};
382    kv = new KeyValue(row, f, q, ts, KeyValue.Type.Minimum, HConstants.EMPTY_BYTE_ARRAY);
383    cell = CellUtil.createCell(row, f, q, ts, KeyValue.Type.Minimum.getCode(),
384        HConstants.EMPTY_BYTE_ARRAY);
385    cellToString = CellUtil.getCellKeyAsString(cell);
386    assertEquals(kv.toString(), cellToString);
387
388  }
389
390  @Test
391  public void testToString1() {
392    String row = "test.row";
393    String family = "test.family";
394    String qualifier = "test.qualifier";
395    long timestamp = 42;
396    KeyValue.Type type = KeyValue.Type.Put;
397    String value = "test.value";
398    long seqId = 1042;
399
400    Cell cell = CellUtil.createCell(Bytes.toBytes(row), Bytes.toBytes(family),
401      Bytes.toBytes(qualifier), timestamp, type.getCode(), Bytes.toBytes(value), seqId);
402
403    String nonVerbose = CellUtil.toString(cell, false);
404    String verbose = CellUtil.toString(cell, true);
405
406    System.out.println("nonVerbose=" + nonVerbose);
407    System.out.println("verbose=" + verbose);
408
409    Assert.assertEquals(
410        String.format("%s/%s:%s/%d/%s/vlen=%s/seqid=%s",
411          row, family, qualifier, timestamp, type.toString(),
412          Bytes.toBytes(value).length, seqId),
413        nonVerbose);
414
415    Assert.assertEquals(
416      String.format("%s/%s:%s/%d/%s/vlen=%s/seqid=%s/%s",
417        row, family, qualifier, timestamp, type.toString(), Bytes.toBytes(value).length,
418        seqId, value),
419      verbose);
420
421    // TODO: test with tags
422  }
423
424  @Test
425  public void testCloneCellFieldsFromByteBufferedCell() {
426    byte[] r = Bytes.toBytes("row1");
427    byte[] f = Bytes.toBytes("cf1");
428    byte[] q = Bytes.toBytes("qual1");
429    byte[] v = Bytes.toBytes("val1");
430    byte[] tags = Bytes.toBytes("tag1");
431    KeyValue kv =
432        new KeyValue(r, f, q, 0, q.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
433    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
434    Cell bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
435    byte[] rDest = CellUtil.cloneRow(bbCell);
436    assertTrue(Bytes.equals(r, rDest));
437    byte[] fDest = CellUtil.cloneFamily(bbCell);
438    assertTrue(Bytes.equals(f, fDest));
439    byte[] qDest = CellUtil.cloneQualifier(bbCell);
440    assertTrue(Bytes.equals(q, qDest));
441    byte[] vDest = CellUtil.cloneValue(bbCell);
442    assertTrue(Bytes.equals(v, vDest));
443    byte[] tDest = new byte[tags.length];
444    PrivateCellUtil.copyTagsTo(bbCell, tDest, 0);
445    assertTrue(Bytes.equals(tags, tDest));
446  }
447
448  @Test
449  public void testMatchingCellFieldsFromByteBufferedCell() {
450    byte[] r = Bytes.toBytes("row1");
451    byte[] f = Bytes.toBytes("cf1");
452    byte[] q1 = Bytes.toBytes("qual1");
453    byte[] q2 = Bytes.toBytes("qual2");
454    byte[] v = Bytes.toBytes("val1");
455    byte[] tags = Bytes.toBytes("tag1");
456    KeyValue kv =
457        new KeyValue(r, f, q1, 0, q1.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
458    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
459    Cell bbCell1 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
460    kv = new KeyValue(r, f, q2, 0, q2.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
461    buffer = ByteBuffer.wrap(kv.getBuffer());
462    Cell bbCell2 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
463    assertTrue(CellUtil.matchingRows(bbCell1, bbCell2));
464    assertTrue(CellUtil.matchingRows(kv, bbCell2));
465    assertTrue(CellUtil.matchingRows(bbCell1, r));
466    assertTrue(CellUtil.matchingFamily(bbCell1, bbCell2));
467    assertTrue(CellUtil.matchingFamily(kv, bbCell2));
468    assertTrue(CellUtil.matchingFamily(bbCell1, f));
469    assertFalse(CellUtil.matchingQualifier(bbCell1, bbCell2));
470    assertTrue(CellUtil.matchingQualifier(kv, bbCell2));
471    assertTrue(CellUtil.matchingQualifier(bbCell1, q1));
472    assertTrue(CellUtil.matchingQualifier(bbCell2, q2));
473    assertTrue(CellUtil.matchingValue(bbCell1, bbCell2));
474    assertTrue(CellUtil.matchingValue(kv, bbCell2));
475    assertTrue(CellUtil.matchingValue(bbCell1, v));
476    assertFalse(CellUtil.matchingColumn(bbCell1, bbCell2));
477    assertTrue(CellUtil.matchingColumn(kv, bbCell2));
478    assertTrue(CellUtil.matchingColumn(bbCell1, f, q1));
479    assertTrue(CellUtil.matchingColumn(bbCell2, f, q2));
480  }
481
482  @Test
483  public void testCellFieldsAsPrimitiveTypesFromByteBufferedCell() {
484    int ri = 123;
485    byte[] r = Bytes.toBytes(ri);
486    byte[] f = Bytes.toBytes("cf1");
487    byte[] q = Bytes.toBytes("qual1");
488    long vl = 10981L;
489    byte[] v = Bytes.toBytes(vl);
490    KeyValue kv = new KeyValue(r, f, q, v);
491    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
492    Cell bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
493    assertEquals(ri, PrivateCellUtil.getRowAsInt(bbCell));
494    assertEquals(vl, PrivateCellUtil.getValueAsLong(bbCell));
495    double vd = 3005.5;
496    v = Bytes.toBytes(vd);
497    kv = new KeyValue(r, f, q, v);
498    buffer = ByteBuffer.wrap(kv.getBuffer());
499    bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
500    assertEquals(vd, PrivateCellUtil.getValueAsDouble(bbCell), 0.0);
501    BigDecimal bd = new BigDecimal(9999);
502    v = Bytes.toBytes(bd);
503    kv = new KeyValue(r, f, q, v);
504    buffer = ByteBuffer.wrap(kv.getBuffer());
505    bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
506    assertEquals(bd, PrivateCellUtil.getValueAsBigDecimal(bbCell));
507  }
508
509  @Test
510  public void testWriteCell() throws IOException {
511    byte[] r = Bytes.toBytes("row1");
512    byte[] f = Bytes.toBytes("cf1");
513    byte[] q1 = Bytes.toBytes("qual1");
514    byte[] q2 = Bytes.toBytes("qual2");
515    byte[] v = Bytes.toBytes("val1");
516    byte[] tags = Bytes.toBytes("tag1");
517    KeyValue kv =
518        new KeyValue(r, f, q1, 0, q1.length, 1234L, KeyValue.Type.Put, v, 0, v.length, tags);
519    NonExtendedCell nonExtCell = new NonExtendedCell(kv);
520    ByteArrayOutputStream os = new ByteArrayOutputStream();
521    int writeCell = PrivateCellUtil.writeCell(nonExtCell, os, true);
522    byte[] byteArray = os.toByteArray();
523    KeyValue res = new KeyValue(byteArray);
524    assertTrue(CellUtil.equals(kv, res));
525  }
526
527  @Test
528  public void testGetType() throws IOException {
529    Cell c = Mockito.mock(Cell.class);
530    Mockito.when(c.getType()).thenCallRealMethod();
531    for (Cell.Type type : Cell.Type.values()) {
532      Mockito.when(c.getTypeByte()).thenReturn(type.getCode());
533      assertEquals(type, c.getType());
534    }
535
536    try {
537      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Maximum.getCode());
538      c.getType();
539      fail("The code of Maximum can't be handled by Cell.Type");
540    } catch(UnsupportedOperationException e) {
541    }
542
543    try {
544      Mockito.when(c.getTypeByte()).thenReturn(KeyValue.Type.Minimum.getCode());
545      c.getType();
546      fail("The code of Maximum can't be handled by Cell.Type");
547    } catch(UnsupportedOperationException e) {
548    }
549  }
550
551  private static class NonExtendedCell implements Cell {
552    private KeyValue kv;
553
554    public NonExtendedCell(KeyValue kv) {
555      this.kv = kv;
556    }
557
558    @Override
559    public byte[] getRowArray() {
560      return this.kv.getRowArray();
561    }
562
563    @Override
564    public int getRowOffset() {
565      return this.kv.getRowOffset();
566    }
567
568    @Override
569    public short getRowLength() {
570      return this.kv.getRowLength();
571    }
572
573    @Override
574    public byte[] getFamilyArray() {
575      return this.kv.getFamilyArray();
576    }
577
578    @Override
579    public int getFamilyOffset() {
580      return this.kv.getFamilyOffset();
581    }
582
583    @Override
584    public byte getFamilyLength() {
585      return this.kv.getFamilyLength();
586    }
587
588    @Override
589    public byte[] getQualifierArray() {
590      return this.kv.getQualifierArray();
591    }
592
593    @Override
594    public int getQualifierOffset() {
595      return this.kv.getQualifierOffset();
596    }
597
598    @Override
599    public int getQualifierLength() {
600      return this.kv.getQualifierLength();
601    }
602
603    @Override
604    public long getTimestamp() {
605      return this.kv.getTimestamp();
606    }
607
608    @Override
609    public byte getTypeByte() {
610      return this.kv.getTypeByte();
611    }
612
613    @Override
614    public long getSequenceId() {
615      return this.kv.getSequenceId();
616    }
617
618    @Override
619    public byte[] getValueArray() {
620      return this.kv.getValueArray();
621    }
622
623    @Override
624    public int getValueOffset() {
625      return this.kv.getValueOffset();
626    }
627
628    @Override
629    public int getValueLength() {
630      return this.kv.getValueLength();
631    }
632
633    @Override
634    public byte[] getTagsArray() {
635      return this.kv.getTagsArray();
636    }
637
638    @Override
639    public int getTagsOffset() {
640      return this.kv.getTagsOffset();
641    }
642
643    @Override
644    public int getTagsLength() {
645      return this.kv.getTagsLength();
646    }
647  }
648}