/****************************************************************
 * 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 org.apache.james.mime4j.parser;

import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.stream.BodyDescriptor;
import org.apache.james.mime4j.stream.Field;

import java.io.IOException;
import java.io.InputStream;

/**
 * <p>
 * Receives notifications of the content of a plain RFC822 or MIME message.
 * Implement this interface and register an instance of that implementation
 * with a <code>MimeStreamParser</code> instance using its
 * {@link org.apache.james.mime4j.parser.MimeStreamParser#setContentHandler(ContentHandler)}
 * method. The parser uses the <code>ContentHandler</code> instance to report
 * basic message-related events like the start and end of the body of a
 * part in a multipart MIME entity.
 * </p>
 * <p>
 * Throwing an exception from an event method will terminate the message
 * processing, i.e. no new events will be generated for that message.
 * <p>
 * Events will be generated in the order the corresponding elements occur in
 * the message stream parsed by the parser. E.g.:
 * </p>
 * <pre>
 *      startMessage()
 *          startHeader()
 *              field(...)
 *              field(...)
 *              ...
 *          endHeader()
 *          startMultipart()
 *              preamble(...)
 *              startBodyPart()
 *                  startHeader()
 *                      field(...)
 *                      field(...)
 *                      ...
 *                  endHeader()
 *                  body()
 *              endBodyPart()
 *              startBodyPart()
 *                  startHeader()
 *                      field(...)
 *                      field(...)
 *                      ...
 *                  endHeader()
 *                  body()
 *              endBodyPart()
 *              epilogue(...)
 *          endMultipart()
 *      endMessage()
 * </pre>
 * <p>
 * The above shows an example of a MIME message consisting of a multipart
 * body containing two body parts.
 * </p>
 * <p>
 * See MIME RFCs 2045-2049 for more information on the structure of MIME
 * messages and RFC 822 and 2822 for the general structure of Internet mail
 * messages.
 * </p>
 */
public interface ContentHandler {

    /**
     * Called when a new message starts (a top level message or an embedded
     * rfc822 message).
     *
     * @throws MimeException on processing errors
     */
    void startMessage() throws MimeException;

    /**
     * Called when a message ends.
     *
     * @throws MimeException on processing errors
     */
    void endMessage() throws MimeException;

    /**
     * Called when a new body part starts inside a
     * <code>multipart/*</code> entity.
     *
     * @throws MimeException on processing errors
     */
    void startBodyPart() throws MimeException;

    /**
     * Called when a body part ends.
     *
     * @throws MimeException on processing errors
     */
    void endBodyPart() throws MimeException;

    /**
     * Called when a header (of a message or body part) is about to be parsed.
     *
     * @throws MimeException on processing errors
     */
    void startHeader() throws MimeException;

    /**
     * Called for each field of a header.
     *
     * @param rawField the MIME field.
     * @throws MimeException on processing errors
     */
    void field(Field rawField) throws MimeException;

    /**
     * Called when there are no more header fields in a message or body part.
     *
     * @throws MimeException on processing errors
     */
    void endHeader() throws MimeException;

    /**
     * Called for the preamble (whatever comes before the first body part)
     * of a <code>multipart/*</code> entity.
     *
     * @param is used to get the contents of the preamble.
     * @throws MimeException on processing errors
     * @throws IOException should be thrown on I/O errors.
     */
    void preamble(InputStream is) throws MimeException, IOException;

    /**
     * Called for the epilogue (whatever comes after the final body part)
     * of a <code>multipart/*</code> entity.
     *
     * @param is used to get the contents of the epilogue.
     * @throws MimeException on processing errors
     * @throws IOException should be thrown on I/O errors.
     */
    void epilogue(InputStream is) throws MimeException, IOException;

    /**
     * Called when the body of a multipart entity is about to be parsed.
     *
     * @param bd encapsulates the values (either read from the
     *        message stream or, if not present, determined implictly
     *        as described in the
     *        MIME rfc:s) of the <code>Content-Type</code> and
     *        <code>Content-Transfer-Encoding</code> header fields.
     * @throws MimeException on processing errors
     */
    void startMultipart(BodyDescriptor bd) throws MimeException;

    /**
     * Called when the body of an entity has been parsed.
     *
     * @throws MimeException on processing errors
     */
    void endMultipart() throws MimeException;

    /**
     * Called when the body of a discrete (non-multipart) entity is about to
     * be parsed.
     *
     * @param bd see {@link #startMultipart(BodyDescriptor)}
     * @param is the contents of the body. NOTE: this is the raw body contents
     *           - it will not be decoded if encoded. The <code>bd</code>
     *           parameter should be used to determine how the stream data
     *           should be decoded.
     * @throws MimeException on processing errors
     * @throws IOException should be thrown on I/O errors.
     */
    void body(BodyDescriptor bd, InputStream is)
        throws MimeException, IOException;

    /**
     * Called when a new entity (message or body part) starts and the
     * parser is in <code>raw</code> mode.
     *
     * @param is the raw contents of the entity.
     * @throws MimeException on processing errors
     * @throws IOException should be thrown on I/O errors.
     * @see org.apache.james.mime4j.parser.MimeStreamParser#setRaw()
     */
    void raw(InputStream is) throws MimeException, IOException;

}
