class DocKey {

        private final List<Symbol> key;

        private DocKey(int pos) {
            key = docKeys.get(pos);
        }

        public String getId(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {
            return idFunction.apply(
                Lists.mapLazy(
                    key.subList(0, width),
                    s -> StringUtils.nullOrString(SymbolEvaluator.evaluate(txnCtx, nodeCtx, s, params, subQueryResults))
                )
            );
        }

        public Optional<Long> version(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {
            if (withVersions && key.get(width) != null) {
                Object val = SymbolEvaluator.evaluate(txnCtx, nodeCtx, key.get(width), params, subQueryResults);
                return Optional.of(DataTypes.LONG.sanitizeValue(val));
            }
            return Optional.empty();
        }

        public Optional<Long> sequenceNo(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {
            if (withSequenceVersioning && key.get(width) != null) {
                Object val = SymbolEvaluator.evaluate(txnCtx, nodeCtx, key.get(width), params, subQueryResults);
                return Optional.of(LongType.INSTANCE.sanitizeValue(val));
            }
            return Optional.empty();
        }

        public Optional<Long> primaryTerm(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {<FILL_FUNCTION_BODY>}

        public List<Symbol> values() {
            return key;
        }

        public List<String> getPartitionValues(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {
            if (partitionIdx == null || partitionIdx.isEmpty()) {
                return Collections.emptyList();
            }
            return Lists.map(
                partitionIdx,
                pIdx -> DataTypes.STRING.implicitCast(SymbolEvaluator.evaluate(txnCtx, nodeCtx, key.get(pIdx), params, subQueryResults)));

        }

        public String getRouting(TransactionContext txnCtx, NodeContext nodeCtx, Row params, SubQueryResults subQueryResults) {
            if (clusteredByIdx >= 0) {
                return SymbolEvaluator.evaluate(txnCtx, nodeCtx, key.get(clusteredByIdx), params, subQueryResults).toString();
            }
            return getId(txnCtx, nodeCtx, params, subQueryResults);
        }
    }

            if (withSequenceVersioning && key.get(width + 1) != null) {
                Object val = SymbolEvaluator.evaluate(txnCtx, nodeCtx, key.get(width + 1), params, subQueryResults);
                return Optional.of(LongType.INSTANCE.sanitizeValue(val));
            }
            return Optional.empty();
        
<no_super_class>