private static TreeReader getPrimitiveTreeReader(final int columnIndex, TypeDescription columnType,
      CompressionCodec codec, OrcProto.ColumnEncoding columnEncoding, ColumnStreamData present, ColumnStreamData data,
      ColumnStreamData dictionary, ColumnStreamData lengths, ColumnStreamData secondary, Context context,
      List<ColumnVector> vectors, final boolean useDecimal64ColumnVectors) throws IOException {
    switch (columnType.getCategory()) {
    case BINARY:
      return BinaryStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setLengthStream(lengths).setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors)
          .setContext(context).build();
    case BOOLEAN:
      return BooleanStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setVectors(vectors).setContext(context).build();
    case BYTE:
      return ByteStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setVectors(vectors).setContext(context).build();
    case SHORT:
      return ShortStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case INT:
      return IntStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case LONG:
      return LongStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case FLOAT:
      return FloatStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setVectors(vectors).setContext(context).build();
    case DOUBLE:
      return DoubleStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setVectors(vectors).setContext(context).build();
    case CHAR:
      return CharStreamReader.builder().setColumnIndex(columnIndex).setMaxLength(columnType.getMaxLength())
          .setPresentStream(present).setDataStream(data).setLengthStream(lengths).setDictionaryStream(dictionary)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case VARCHAR:
      return VarcharStreamReader.builder().setColumnIndex(columnIndex).setMaxLength(columnType.getMaxLength())
          .setPresentStream(present).setDataStream(data).setLengthStream(lengths).setDictionaryStream(dictionary)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case STRING:
      return StringStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setLengthStream(lengths).setDictionaryStream(dictionary).setCompressionCodec(codec)
          .setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    case DECIMAL:
      // special handling for serde reader (text) in llap IO.
      // if file format version is null, then we are processing text IF in LLAP IO, in which case
      // we get vectors instead of streams. If vectors contain instance of Decimal64ColumnVector we
      // should use Decimal64StreamReader (which acts as a wrapper around vectors)
      boolean useDecimal64Reader = context.getFileFormat() == null && vectors != null && useDecimal64ColumnVectors;
      if (useDecimal64Reader) {
        boolean containDecimal64CV = false;
        for (ColumnVector vector : vectors) {
          if (vector instanceof Decimal64ColumnVector) {
            containDecimal64CV = true;
            break;
          }
        }
        useDecimal64Reader &= containDecimal64CV;
      }
      if ((context.getFileFormat() == OrcFile.Version.UNSTABLE_PRE_2_0 || useDecimal64Reader) && columnType.getPrecision() <= TypeDescription.MAX_DECIMAL64_PRECISION) {
        return Decimal64StreamReader.builder().setColumnIndex(columnIndex).setPrecision(columnType.getPrecision())
            .setScale(columnType.getScale()).setPresentStream(present).setValueStream(data).setCompressionCodec(codec)
            .setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
      } else {
        return DecimalStreamReader.builder().setColumnIndex(columnIndex).setPrecision(columnType.getPrecision())
            .setScale(columnType.getScale()).setPresentStream(present).setValueStream(data).setScaleStream(secondary)
            .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context)
            .build();
      }
    case TIMESTAMP:
      return TimestampStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present)
          .setSecondsStream(data).setNanosStream(secondary).setCompressionCodec(codec).setColumnEncoding(columnEncoding)
          .setVectors(vectors).setContext(context).setIsInstant(false).build();
    case DATE:
      return DateStreamReader.builder().setColumnIndex(columnIndex).setPresentStream(present).setDataStream(data)
          .setCompressionCodec(codec).setColumnEncoding(columnEncoding).setVectors(vectors).setContext(context).build();
    default:
      throw new AssertionError("Not a primitive category: " + columnType.getCategory());
    }
  }
We choose to use a toy programming language, so we cannot use multiple inheritance.
If we could, we could have this inherit TreeReader to contain the common impl, and then
have e.g. SettableIntTreeReader inherit both Settable... and Int.. TreeReader-s.
Instead, we have a settable interface that the caller will cast to and call setBuffers.
ql/src/java/org/apache/hadoop/hive/ql/io/orc/encoded/EncodedTreeReaderFactory.java