/*
 * 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 javax.xml.soap;

import javax.activation.DataHandler;
import java.util.Iterator;

/**
 * <P>A single attachment to a <CODE>SOAPMessage</CODE> object. A <CODE>SOAPMessage</CODE> object
 * may contain zero, one, or many <CODE>AttachmentPart</CODE> objects. Each <CODE>
 * AttachmentPart</CODE> object consists of two parts, application-specific content and associated
 * MIME headers. The MIME headers consists of name/value pairs that can be used to identify and
 * describe the content.</P>
 * <p/>
 * <P>An <CODE>AttachmentPart</CODE> object must conform to certain standards.</P>
 * <p/>
 * <OL> <LI>It must conform to <A href= "http://www.ietf.org/rfc/rfc2045.txt">MIME [RFC2045]
 * standards</A></LI>
 * <p/>
 * <LI>It MUST contain content</LI>
 * <p/>
 * <LI> The header portion MUST include the following header:
 * <p/>
 * <UL> <LI> <CODE>Content-Type</CODE><BR> This header identifies the type of data in the content of
 * an <CODE>AttachmentPart</CODE> object and MUST conform to [RFC2045]. The following is an example
 * of a Content-Type header: <PRE> Content-Type:  application/xml
 * <p/>
 * </PRE> The following line of code, in which <CODE>ap</CODE> is an <CODE>AttachmentPart</CODE>
 * object, sets the header shown in the previous example. <PRE> ap.setMimeHeader("Content-Type",
 * "application/xml");
 * <p/>
 * </PRE>
 * <p/>
 * <P></P> </LI> </UL> </LI> </OL>
 * <p/>
 * <P>There are no restrictions on the content portion of an <CODE>AttachmentPart</CODE> object. The
 * content may be anything from a simple plain text object to a complex XML document or image
 * file.</P>
 * <p/>
 * <P>An <CODE>AttachmentPart</CODE> object is created with the method
 * <CODE>SOAPMessage.createAttachmentPart</CODE>. After setting its MIME headers, the
 * <CODE>AttachmentPart</CODE> object is added to the message that created it with the method
 * <CODE>SOAPMessage.addAttachmentPart</CODE>.</P>
 * <p/>
 * <P>The following code fragment, in which <CODE>m</CODE> is a <CODE>SOAPMessage</CODE> object and
 * <CODE>contentStringl</CODE> is a <CODE>String</CODE>, creates an instance of <CODE>
 * AttachmentPart</CODE>, sets the <CODE>AttachmentPart</CODE> object with some content and header
 * information, and adds the <CODE>AttachmentPart</CODE> object to the <CODE> SOAPMessage</CODE>
 * object.</P> <PRE> AttachmentPart ap1 = m.createAttachmentPart(); ap1.setContent(contentString1,
 * "text/plain"); m.addAttachmentPart(ap1); </PRE>
 * <p/>
 * <P>The following code fragment creates and adds a second <CODE> AttachmentPart</CODE> instance to
 * the same message. <CODE> jpegData</CODE> is a binary byte buffer representing the jpeg file.</P>
 * <PRE> AttachmentPart ap2 = m.createAttachmentPart(); byte[] jpegData =  ...; ap2.setContent(new
 * ByteArrayInputStream(jpegData), "image/jpeg"); m.addAttachmentPart(ap2); </PRE>
 * <p/>
 * <P>The <CODE>getContent</CODE> method retrieves the contents and header from an
 * <CODE>AttachmentPart</CODE> object. Depending on the <CODE>DataContentHandler</CODE> objects
 * present, the returned <CODE>Object</CODE> can either be a typed Java object corresponding to the
 * MIME type or an <CODE> InputStream</CODE> object that contains the content as bytes.</P> <PRE>
 * String content1 = ap1.getContent(); java.io.InputStream content2 = ap2.getContent(); </PRE> The
 * method <CODE>clearContent</CODE> removes all the content from an <CODE>AttachmentPart</CODE>
 * object but does not affect its header information. <PRE> ap1.clearContent(); </PRE>
 */
public abstract class AttachmentPart {

    // fixme: should this constructor be protected?

    /** Create a new AttachmentPart. */
    public AttachmentPart() {
    }

    /**
     * Returns the number of bytes in this <CODE> AttachmentPart</CODE> object.
     *
     * @return the size of this <CODE>AttachmentPart</CODE> object in bytes or -1 if the size cannot
     *         be determined
     * @throws SOAPException if the content of this attachment is corrupted of if there was an
     *                       exception while trying to determine the size.
     */
    public abstract int getSize() throws SOAPException;

    /**
     * Clears out the content of this <CODE> AttachmentPart</CODE> object. The MIME header portion
     * is left untouched.
     */
    public abstract void clearContent();

    /**
     * Gets the content of this <code>AttachmentPart</code> object as a Java object. The type of the
     * returned Java object depends on (1) the <code>DataContentHandler</code> object that is used
     * to interpret the bytes and (2) the <code>Content-Type</code> given in the header.
     * <p/>
     * For the MIME content types "text/plain", "text/html" and "text/xml", the
     * <code>DataContentHandler</code> object does the conversions to and from the Java types
     * corresponding to the MIME types. For other MIME types,the <code>DataContentHandler</code>
     * object can return an <code>InputStream</code> object that contains the content data as raw
     * bytes.
     * <p/>
     * A JAXM-compliant implementation must, as a minimum, return a <code>java.lang.String</code>
     * object corresponding to any content stream with a <code>Content-Type</code> value of
     * <code>text/plain</code>, a <code>javax.xml.transform.StreamSource</code> object corresponding
     * to a content stream with a <code>Content-Type</code> value of <code>text/xml</code>, a
     * <code>java.awt.Image</code> object corresponding to a content stream with a
     * <code>Content-Type</code> value of <code>image/gif</code> or <code>image/jpeg</code>.  For
     * those content types that an installed <code>DataContentHandler</code> object does not
     * understand, the <code>DataContentHandler</code> object is required to return a
     * <code>java.io.InputStream</code> object with the raw bytes.
     *
     * @return a Java object with the content of this <CODE> AttachmentPart</CODE> object
     * @throws SOAPException if there is no content set into this <CODE>AttachmentPart</CODE> object
     *                       or if there was a data transformation error
     */
    public abstract Object getContent() throws SOAPException;

    /**
     * Sets the content of this attachment part to that of the given <CODE>Object</CODE> and sets
     * the value of the <CODE> Content-Type</CODE> header to the given type. The type of the
     * <CODE>Object</CODE> should correspond to the value given for the <CODE>Content-Type</CODE>.
     * This depends on the particular set of <CODE>DataContentHandler</CODE> objects in use.
     *
     * @param object      the Java object that makes up the content for this attachment part
     * @param contentType the MIME string that specifies the type of the content
     * @throws IllegalArgumentException
     *          if the contentType does not match the type of the content object, or if there was no
     *          <CODE> DataContentHandler</CODE> object for this content object
     * @see #getContent() getContent()
     */
    public abstract void setContent(Object object, String contentType);

    /**
     * Gets the <CODE>DataHandler</CODE> object for this <CODE> AttachmentPart</CODE> object.
     *
     * @return the <CODE>DataHandler</CODE> object associated with this <CODE>AttachmentPart</CODE>
     *         object
     * @throws SOAPException if there is no data in this <CODE>AttachmentPart</CODE> object
     */
    public abstract DataHandler getDataHandler() throws SOAPException;

    /**
     * Sets the given <CODE>DataHandler</CODE> object as the data handler for this
     * <CODE>AttachmentPart</CODE> object. Typically, on an incoming message, the data handler is
     * automatically set. When a message is being created and populated with content, the
     * <CODE>setDataHandler</CODE> method can be used to get data from various data sources into the
     * message.
     *
     * @param datahandler <CODE>DataHandler</CODE> object to be set
     * @throws IllegalArgumentException
     *          if there was a problem with the specified <CODE> DataHandler</CODE> object
     */
    public abstract void setDataHandler(DataHandler datahandler);

    /**
     * Gets the value of the MIME header whose name is "Content-Id".
     *
     * @return a <CODE>String</CODE> giving the value of the "Content-Id" header or
     *         <CODE>null</CODE> if there is none
     * @see #setContentId(String) setContentId(java.lang.String)
     */
    public String getContentId() {

        String as[] = getMimeHeader("Content-Id");

        if (as != null && as.length > 0) {
            return as[0];
        } else {
            return null;
        }
    }

    /**
     * Gets the value of the MIME header "Content-Location".
     *
     * @return a <CODE>String</CODE> giving the value of the "Content-Location" header or
     *         <CODE>null</CODE> if there is none
     */
    public String getContentLocation() {

        String as[] = getMimeHeader("Content-Location");

        if (as != null && as.length > 0) {
            return as[0];
        } else {
            return null;
        }
    }

    /**
     * Gets the value of the MIME header "Content-Type".
     *
     * @return a <CODE>String</CODE> giving the value of the "Content-Type" header or
     *         <CODE>null</CODE> if there is none
     */
    public String getContentType() {

        String as[] = getMimeHeader("Content-Type");

        if (as != null && as.length > 0) {
            return as[0];
        } else {
            return null;
        }
    }

    /**
     * Sets the MIME header "Content-Id" with the given value.
     *
     * @param contentId a <CODE>String</CODE> giving the value of the "Content-Id" header
     * @throws IllegalArgumentException
     *          if there was a problem with the specified <CODE> contentId</CODE> value
     * @see #getContentId() getContentId()
     */
    public void setContentId(String contentId) {
        setMimeHeader("Content-Id", contentId);
    }

    /**
     * Sets the MIME header "Content-Location" with the given value.
     *
     * @param contentLocation a <CODE>String</CODE> giving the value of the "Content-Location"
     *                        header
     * @throws IllegalArgumentException
     *          if there was a problem with the specified content location
     */
    public void setContentLocation(String contentLocation) {
        setMimeHeader("Content-Location", contentLocation);
    }

    /**
     * Sets the MIME header "Content-Type" with the given value.
     *
     * @param contentType a <CODE>String</CODE> giving the value of the "Content-Type" header
     * @throws IllegalArgumentException
     *          if there was a problem with the specified content type
     */
    public void setContentType(String contentType) {
        setMimeHeader("Content-Type", contentType);
    }

    /**
     * Removes all MIME headers that match the given name.
     *
     * @param header - the string name of the MIME header/s to be removed
     */
    public abstract void removeMimeHeader(String header);

    /** Removes all the MIME header entries. */
    public abstract void removeAllMimeHeaders();

    /**
     * Gets all the values of the header identified by the given <CODE>String</CODE>.
     *
     * @param name the name of the header; example: "Content-Type"
     * @return a <CODE>String</CODE> array giving the value for the specified header
     * @see #setMimeHeader(String, String) setMimeHeader(java.lang.String,
     *      java.lang.String)
     */
    public abstract String[] getMimeHeader(String name);

    /**
     * Changes the first header entry that matches the given name to the given value, adding a new
     * header if no existing header matches. This method also removes all matching headers but the
     * first.
     * <p/>
     * <P>Note that RFC822 headers can only contain US-ASCII characters.</P>
     *
     * @param name  a <CODE>String</CODE> giving the name of the header for which to search
     * @param value a <CODE>String</CODE> giving the value to be set for the header whose name
     *              matches the given name
     * @throws IllegalArgumentException
     *          if there was a problem with the specified mime header name or value
     */
    public abstract void setMimeHeader(String name, String value);

    /**
     * Adds a MIME header with the specified name and value to this <CODE>AttachmentPart</CODE>
     * object.
     * <p/>
     * <P>Note that RFC822 headers can contain only US-ASCII characters.</P>
     *
     * @param name  a <CODE>String</CODE> giving the name of the header to be added
     * @param value a <CODE>String</CODE> giving the value of the header to be added
     * @throws IllegalArgumentException
     *          if there was a problem with the specified mime header name or value
     */
    public abstract void addMimeHeader(String name, String value);

    /**
     * Retrieves all the headers for this <CODE> AttachmentPart</CODE> object as an iterator over
     * the <CODE> MimeHeader</CODE> objects.
     *
     * @return an <CODE>Iterator</CODE> object with all of the Mime headers for this
     *         <CODE>AttachmentPart</CODE> object
     */
    public abstract Iterator getAllMimeHeaders();

    /**
     * Retrieves all <CODE>MimeHeader</CODE> objects that match a name in the given array.
     *
     * @param names a <CODE>String</CODE> array with the name(s) of the MIME headers to be returned
     * @return all of the MIME headers that match one of the names in the given array as an
     *         <CODE>Iterator</CODE> object
     */
    public abstract Iterator getMatchingMimeHeaders(String names[]);

    /**
     * Retrieves all <CODE>MimeHeader</CODE> objects whose name does not match a name in the given
     * array.
     *
     * @param names a <CODE>String</CODE> array with the name(s) of the MIME headers not to be
     *              returned
     * @return all of the MIME headers in this <CODE> AttachmentPart</CODE> object except those that
     *         match one of the names in the given array. The nonmatching MIME headers are returned
     *         as an <CODE>Iterator</CODE> object.
     */
    public abstract Iterator getNonMatchingMimeHeaders(String names[]);

    public abstract java.io.InputStream getBase64Content()
            throws SOAPException;

    public abstract java.io.InputStream getRawContent()
            throws SOAPException;

    public abstract byte[] getRawContentBytes()
            throws SOAPException;

    public abstract void setBase64Content(java.io.InputStream inputstream,
                                          java.lang.String s)
            throws SOAPException;

    public abstract void setRawContent(java.io.InputStream inputstream,
                                       java.lang.String s)
            throws SOAPException;

    public abstract void setRawContentBytes(byte[] abyte0,
                                            int i,
                                            int j,
                                            java.lang.String s)
            throws SOAPException;
}
