/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jakarta.servlet.http;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

/**
 * This class represents a part as uploaded to the server as part of a <code>multipart/form-data</code> request body.
 * The part may represent either an uploaded file or form data.
 *
 * @since Servlet 3.0
 */
public interface Part {

    /**
     * Obtain an <code>InputStream</code> that can be used to retrieve the contents of the file.
     *
     * @return An InputStream for the contents of the file
     *
     * @throws IOException if an I/O occurs while obtaining the stream
     */
    InputStream getInputStream() throws IOException;

    /**
     * Obtain the content type passed by the browser.
     *
     * @return The content type passed by the browser or <code>null</code> if not defined.
     */
    String getContentType();

    /**
     * Obtain the name of the field in the multipart form corresponding to this part.
     *
     * @return The name of the field in the multipart form corresponding to this part.
     */
    String getName();

    /**
     * If this part represents an uploaded file, gets the file name submitted in the upload. Returns {@code null} if no
     * file name is available or if this part is not a file upload.
     *
     * @return the submitted file name or {@code null}.
     *
     * @since Servlet 3.1
     */
    String getSubmittedFileName();

    /**
     * Obtain the size of this part.
     *
     * @return The size of the part if bytes
     */
    long getSize();

    /**
     * A convenience method to write an uploaded part to disk. The client code is not concerned with whether the
     * part is stored in memory, or on disk in a temporary location. They just want to write the uploaded part to a
     * file. This method is not guaranteed to succeed if called more than once for the same part. This allows a
     * particular implementation to use, for example, file renaming, where possible, rather than copying all of the
     * underlying data, thus gaining a significant performance benefit.
     *
     * @param fileName The location into which the uploaded part should be stored. Relative locations are relative to
     *                     {@link jakarta.servlet.MultipartConfigElement#getLocation()}
     *
     * @throws IOException if an I/O occurs while attempting to write the part
     */
    void write(String fileName) throws IOException;

    /**
     * Deletes the underlying storage for a part, including deleting any associated temporary disk file. Although the
     * container will delete this storage automatically this method can be used to ensure that this is done at an
     * earlier time, thus preserving system resources.
     * <p>
     * Containers are only required to delete the associated storage when the Part instance is garbage collected. Apache
     * Tomcat will delete the associated storage when the associated request has finished processing. Behaviour of other
     * containers may be different.
     *
     * @throws IOException if an I/O occurs while attempting to delete the part
     */
    void delete() throws IOException;

    /**
     * Obtains the value of the specified part header as a String. If there are multiple headers with the same name,
     * this method returns the first header in the part. The header name is case-insensitive.
     *
     * @param name Header name
     *
     * @return The header value or <code>null</code> if the header is not present
     */
    String getHeader(String name);

    /**
     * Obtain all the values of the specified part header.
     *
     * @param name The name of the header of interest. The header name is case-insensitive.
     *
     * @return All the values of the specified part header. If the part did not include any headers of the specified
     *             name, this method returns an empty Collection.
     */
    Collection<String> getHeaders(String name);

    /**
     * Get the header names provided for this part.
     *
     * @return a Collection of all the header names provided for this part.
     */
    Collection<String> getHeaderNames();
}
