@Override
    public SortedSetDocValues getSortedSetDocValues(String field) throws IOException {
        ensureOpen();
        OrdinalMap map = null;
        synchronized (cachedOrdMaps) {
            map = cachedOrdMaps.get(field);
            if (map == null) {
                // uncached, or not a multi dv
                SortedSetDocValues dv = MultiDocValues.getSortedSetValues(in, field);
                if (dv instanceof MultiDocValues.MultiSortedSetDocValues) {
                    map = ((MultiDocValues.MultiSortedSetDocValues) dv).mapping;
                    CacheHelper cacheHelper = getReaderCacheHelper();
                    if (cacheHelper != null && map.owner == cacheHelper.getKey()) {
                        cachedOrdMaps.put(field, map);
                    }
                }
                return dv;
            }
        }

        assert map != null;
        int size = in
                .leaves()
                .size();
        final SortedSetDocValues[] values = new SortedSetDocValues[size];
        final int[] starts = new int[size + 1];
        long cost = 0;
        for (int i = 0; i < size; i++) {
            LeafReaderContext context = in
                    .leaves()
                    .get(i);
            final LeafReader reader = context.reader();
            final FieldInfo fieldInfo = reader
                    .getFieldInfos()
                    .fieldInfo(field);
            if (fieldInfo != null && fieldInfo.getDocValuesType() != DocValuesType.SORTED_SET) {
                return null;
            }
            SortedSetDocValues v = reader.getSortedSetDocValues(field);
            if (v == null) {
                v = DocValues.emptySortedSet();
            }
            values[i] = v;
            starts[i] = context.docBase;
            cost += v.cost();
        }
        starts[size] = maxDoc();
        return new MultiDocValues.MultiSortedSetDocValues(values, starts, map, cost);
    }
This method is sugar for getting an {@link LeafReader} from
an {@link IndexReader} of any kind. If the reader is already atomic,
it is returned unchanged, otherwise wrapped by this class.
tika-eval/tika-eval-app/src/main/java/org/apache/tika/eval/app/tools/SlowCompositeReaderWrapper.java