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