All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.kiota.MultipartBody Maven / Gradle / Ivy

package com.microsoft.kiota;

import com.microsoft.kiota.serialization.Parsable;
import com.microsoft.kiota.serialization.ParseNode;
import com.microsoft.kiota.serialization.SerializationWriter;
import com.microsoft.kiota.serialization.SerializationWriterFactory;

import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Consumer;

/**
 * Represents a multipart body for a request or a response.
 */
public class MultipartBody implements Parsable {
    /**
     * Creates a new instance of the MultipartBody class.
     */
    public MultipartBody() {
        // default empty constructor
    }

    @Nonnull private final String boundary = UUID.randomUUID().toString().replace("-", "");

    /**
     * Gets the boundary string for the multipart body.
     * @return the boundary string for the multipart body.
     */
    @Nonnull public String getBoundary() {
        return boundary;
    }

    /**
     * The request adapter to use for the multipart body serialization.
     */
    @Nullable public RequestAdapter requestAdapter;

    /**
     * Adds or replaces a part in the multipart body.
     * @param  the type of the part to add or replace.
     * @param name the name of the part to add or replace.
     * @param contentType the content type of the part to add or replace.
     * @param value the value of the part to add or replace.
     */
    public  void addOrReplacePart(
            @Nonnull final String name, @Nonnull final String contentType, @Nonnull final T value) {
        addOrReplacePart(name, contentType, value, null);
    }

    /**
     * Adds or replaces a part in the multipart body.
     *
     * @param  the type of the part to add or replace.
     * @param name the name of the part to add or replace.
     * @param contentType the content type of the part to add or replace.
     * @param value the value of the part to add or replace.
     * @param filename the value of the filename directive.
     */
    public  void addOrReplacePart(
            @Nonnull final String name,
            @Nonnull final String contentType,
            @Nonnull final T value,
            @Nullable String filename) {
        Objects.requireNonNull(value);
        if (Compatibility.isBlank(contentType))
            throw new IllegalArgumentException("contentType cannot be blank or empty");
        if (Compatibility.isBlank(name))
            throw new IllegalArgumentException("name cannot be blank or empty");

        final String normalizedName = normalizePartName(name);
        Part part = new Part(name, value, contentType, filename);
        parts.put(normalizedName, part);
    }

    private final Map parts = new HashMap<>();

    private String normalizePartName(@Nonnull final String original) {
        return original.toLowerCase(Locale.ROOT);
    }

    /**
     * Gets the content type of the part with the specified name.
     * @param partName the name of the part to get.
     * @return the content type of the part with the specified name.
     */
    @Nullable public Object getPartValue(@Nonnull final String partName) {
        if (Compatibility.isBlank(partName))
            throw new IllegalArgumentException("partName cannot be blank or empty");
        final String normalizedName = normalizePartName(partName);
        final Part candidate = parts.get(normalizedName);
        if (candidate == null) return null;
        return candidate.getValue();
    }

    /**
     * Gets the content type of the part with the specified name.
     * @param partName the name of the part to get.
     * @return the content type of the part with the specified name.
     */
    public boolean removePart(@Nonnull final String partName) {
        if (Compatibility.isBlank(partName))
            throw new IllegalArgumentException("partName cannot be blank or empty");
        final String normalizedName = normalizePartName(partName);
        final Object candidate = parts.remove(normalizedName);
        return candidate != null;
    }

    /** {@inheritDoc} */
    @Override
    @Nonnull public Map> getFieldDeserializers() {
        throw new UnsupportedOperationException("Unimplemented method 'getFieldDeserializers'");
    }

    /** {@inheritDoc} */
    @Override
    public void serialize(@Nonnull final SerializationWriter writer) {
        Objects.requireNonNull(writer);
        final RequestAdapter ra = requestAdapter;
        if (ra == null) throw new IllegalStateException("requestAdapter cannot be null");
        if (parts.isEmpty()) throw new IllegalStateException("multipart body cannot be empty");
        final SerializationWriterFactory serializationFactory = ra.getSerializationWriterFactory();
        boolean isFirst = true;
        for (final Map.Entry partEntry : parts.entrySet()) {
            try {
                Part part = partEntry.getValue();
                if (isFirst) isFirst = false;
                else writer.writeStringValue("", "");
                writer.writeStringValue("", "--" + getBoundary());
                final String partContentType = part.getContentType();
                writer.writeStringValue("Content-Type", partContentType);

                String contentDisposition = "form-data; name=\"" + part.getName() + "\"";
                if (part.getFilename() != null && !part.getFilename().trim().isEmpty()) {
                    contentDisposition += "; filename=\"" + part.getFilename() + "\"";
                }
                writer.writeStringValue("Content-Disposition", contentDisposition);

                writer.writeStringValue("", "");
                final Object objectValue = part.getValue();
                if (objectValue instanceof Parsable) {
                    try (final SerializationWriter partWriter =
                            serializationFactory.getSerializationWriter(partContentType)) {
                        partWriter.writeObjectValue("", ((Parsable) objectValue));
                        try (final InputStream partContent = partWriter.getSerializedContent()) {
                            if (partContent.markSupported()) partContent.reset();
                            writer.writeByteArrayValue("", Compatibility.readAllBytes(partContent));
                        }
                    }
                } else if (objectValue instanceof String) {
                    writer.writeStringValue("", (String) objectValue);
                } else if (objectValue instanceof InputStream) {
                    final InputStream inputStream = (InputStream) objectValue;
                    if (inputStream.markSupported()) inputStream.reset();
                    writer.writeByteArrayValue("", Compatibility.readAllBytes(inputStream));
                } else if (objectValue instanceof byte[]) {
                    writer.writeByteArrayValue("", (byte[]) objectValue);
                } else {
                    throw new IllegalStateException(
                            "Unsupported part type" + objectValue.getClass().getName());
                }
            } catch (final IOException ex) {
                throw new RuntimeException(ex);
            }
        }
        writer.writeStringValue("", "");
        writer.writeStringValue("", "--" + boundary + "--");
    }

    private class Part {
        private final String name;
        private final Object value;
        private final String contentType;
        private final String filename;

        Part(String name, Object value, String contentType, String filename) {
            this.name = name;
            this.value = value;
            this.contentType = contentType;
            this.filename = filename;
        }

        public String getName() {
            return name;
        }

        public Object getValue() {
            return value;
        }

        public String getContentType() {
            return contentType;
        }

        public String getFilename() {
            return filename;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy