class MultipartUtils {

    private MultipartUtils() {
        // Prevent outside initialization
    }

    /**
     * Creates a new multipart entity containing the given parts.
     *
     * @param parts          the parts to include.
     * @param requestHeaders the request headers
     * @return a MultipartBody
     */
    public static MultipartBody newMultipartBody(List<Part> parts, HttpHeaders requestHeaders) {<FILL_FUNCTION_BODY>}

    public static List<MultipartPart<? extends Part>> generateMultipartParts(List<Part> parts, byte[] boundary) {
        List<MultipartPart<? extends Part>> multipartParts = new ArrayList<>(parts.size());
        for (Part part : parts) {
            if (part instanceof FilePart) {
                multipartParts.add(new FileMultipartPart((FilePart) part, boundary));

            } else if (part instanceof ByteArrayPart) {
                multipartParts.add(new ByteArrayMultipartPart((ByteArrayPart) part, boundary));

            } else if (part instanceof StringPart) {
                multipartParts.add(new StringMultipartPart((StringPart) part, boundary));

            } else if (part instanceof InputStreamPart) {
                multipartParts.add(new InputStreamMultipartPart((InputStreamPart) part, boundary));

            } else {
                throw new IllegalArgumentException("Unknown part type: " + part);
            }
        }
        // add an extra fake part for terminating the message
        multipartParts.add(new MessageEndMultipartPart(boundary));
        return multipartParts;
    }
}

        requireNonNull(parts, "parts");

        byte[] boundary;
        String contentType;

        String contentTypeHeader = requestHeaders.get(CONTENT_TYPE);
        if (isNonEmpty(contentTypeHeader)) {
            int boundaryLocation = contentTypeHeader.indexOf("boundary=");
            if (boundaryLocation != -1) {
                // boundary defined in existing Content-Type
                contentType = contentTypeHeader;
                boundary = contentTypeHeader.substring(boundaryLocation + "boundary=".length()).trim().getBytes(US_ASCII);
            } else {
                // generate boundary and append it to existing Content-Type
                boundary = computeMultipartBoundary();
                contentType = patchContentTypeWithBoundaryAttribute(contentTypeHeader, boundary);
            }
        } else {
            boundary = computeMultipartBoundary();
            contentType = patchContentTypeWithBoundaryAttribute(HttpHeaderValues.MULTIPART_FORM_DATA.toString(), boundary);
        }

        List<MultipartPart<? extends Part>> multipartParts = generateMultipartParts(parts, boundary);
        return new MultipartBody(multipartParts, contentType, boundary);
    
<no_super_class>