class Id {

    private static final Function<List<String>, String> RANDOM_ID = ignored -> UUIDs.base64UUID();

    private static final Function<List<String>, String> ONLY_ITEM_NULL_VALIDATION = keyValues -> {
        return ensureNonNull(getOnlyElement(keyValues));
    };

    private static final Function<List<String>, String> ONLY_ITEM = Lists::getOnlyElement;


    /**
     * generates a function which can be used to generate an id and apply null validation.
     * <p>
     * This variant doesn't handle the pk = _id case.
     */
    private static Function<List<String>, String> compileWithNullValidation(final int numPks,
                                                                            final int clusteredByPosition) {
        switch (numPks) {
            case 0:
                return RANDOM_ID;
            case 1:
                return ONLY_ITEM_NULL_VALIDATION;
            default:
                return keyValues -> {
                    if (keyValues.size() != numPks) {
                        throw new IllegalArgumentException("Missing primary key values");
                    }
                    return encode(keyValues, clusteredByPosition);
                };
        }
    }

    /**
     * generates a function which can be used to generate an id.
     * <p>
     * This variant doesn't handle the pk = _id case.
     */
    public static Function<List<String>, String> compile(final int numPks, final int clusteredByPosition) {
        if (numPks == 1) {
            return ONLY_ITEM;
        }
        return compileWithNullValidation(numPks, clusteredByPosition);
    }

    /**
     * returns a function which can be used to generate an id with null validation.
     */
    public static Function<List<String>, String> compileWithNullValidation(final List<ColumnIdent> pkColumns, final ColumnIdent clusteredBy) {<FILL_FUNCTION_BODY>}

    @NotNull
    private static <T> T ensureNonNull(@Nullable T pkValue) throws IllegalArgumentException {
        if (pkValue == null) {
            throw new IllegalArgumentException("A primary key value must not be NULL");
        }
        return pkValue;
    }

    public static List<String> decode(List<ColumnIdent> primaryKeys, String id) {
        if (primaryKeys.isEmpty() || primaryKeys.size() == 1) {
            return List.of(id);
        }
        List<String> pkValues = new ArrayList<>();
        byte[] inputBytes = Base64.getDecoder().decode(id);
        try (var in = StreamInput.wrap(inputBytes)) {
            int size = in.readVInt();
            assert size == primaryKeys.size()
                : "Encoded primary key values must match size of primaryKey column list";
            for (int i = 0; i < size; i++) {
                BytesRef bytesRef = in.readBytesRef();
                pkValues.add(bytesRef.utf8ToString());
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        return pkValues;
    }

    public static String encode(List<String> values, int clusteredByPosition) {
        try (BytesStreamOutput out = new BytesStreamOutput(estimateSize(values))) {
            int size = values.size();
            out.writeVInt(size);
            if (clusteredByPosition >= 0) {
                out.writeBytesRef(new BytesRef(ensureNonNull(values.get(clusteredByPosition))));
            }
            for (int i = 0; i < size; i++) {
                if (i != clusteredByPosition) {
                    out.writeBytesRef(new BytesRef(ensureNonNull(values.get(i))));
                }
            }
            return Base64.getEncoder().encodeToString(BytesReference.toBytes(out.bytes()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * estimates the size the bytesRef values will take if written onto a StreamOutput using the String streamer
     */
    private static int estimateSize(Iterable<String> values) {
        int expectedEncodedSize = 0;
        for (String value : values) {
            // 5 bytes for the value of the length itself using vInt
            expectedEncodedSize += 5 + (value != null ? value.length() : 0);
        }
        return expectedEncodedSize;
    }
}

        final int numPks = pkColumns.size();
        if (numPks == 1 && getOnlyElement(pkColumns).equals(DocSysColumns.ID)) {
            return RANDOM_ID;
        }
        int idx = -1;
        if (clusteredBy != null) {
            idx = pkColumns.indexOf(clusteredBy);
        }
        return compileWithNullValidation(numPks, idx);
    
<no_super_class>