public static StructTreeReader createRootTreeReader(TypeDescription[] batchSchemas,
      List<OrcProto.ColumnEncoding> encodings, OrcEncodedColumnBatch batch, CompressionCodec codec, Context context,
      final boolean useDecimal64ColumnVectors) throws IOException {
    // Note: we only look at the schema here to deal with complex types. Somebody has set up the
    //       reader with whatever ideas they had to the schema and we just trust the reader to
    //       produce the CVBs that was asked for. However, we only need to look at top level columns.
    int includedCount = batch.getColumnsWithDataCount();
    if (batchSchemas.length > includedCount) {
      throw new AssertionError(
          "For " + Arrays.toString(batchSchemas) + ", only received " + includedCount + " columns");
    }
    TreeReader[] childReaders = new TreeReader[batchSchemas.length];
    for (int i = 0; i < batchSchemas.length; ++i) {
      int batchColIx = batchSchemas[i].getId();
      if (!batch.hasData(batchColIx) && !batch.hasVectors(batchColIx)) {
        throw new AssertionError("No data for column " + batchColIx + ": " + batchSchemas[i]);
      }
      childReaders[i] = createEncodedTreeReader(batchSchemas[i], encodings, batch, codec, context,
          useDecimal64ColumnVectors);
    }

    // TODO: do we actually need this reader? the caller just extracts child readers.
    return StructStreamReader.builder().setColumnIndex(0).setCompressionCodec(codec).setColumnEncoding(encodings.get(0))
        .setChildReaders(childReaders).setContext(context).build();
  }
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