/*
 * JBoss, the OpenSource J2EE webOS
 * 
 * Distributable under LGPL license. See terms of license at gnu.org.
 */

package javax.emb;

import java.io.Serializable;

/**
 * This basic interface is used throughout Enterprise Media Beans to define the
 * most common behavior for media objects. It defines the services common to
 * all kinds of media objects, regardless of them being persistent or
 * transient.
 * 
 * <p>There are basically two major ways to implement this interface. Media
 * Entity Beans deal with media content modeled as EJB entity beans, i.e. media
 * that is persistent and mutable. The class {@link MediaBean} models media
 * content that is local, possibly transient and immutable.
 * 
 * <p>In order to allow a common view on all kinds of media objects, the Media
 * interface extends {@link java.io.Serializable}, regardless of media being
 * persistent or transient. Having the Media interface extend Serializable
 * ensures that instances can be transferred over remote boundaries, for
 * example using facade stateless session beans.
 * 
 * @version <tt>$Revision: 1.4 $</tt>
 * @author <a href="mailto:ricardoarguello@users.sourceforge.net">Ricardo
 *         Argüello</a>
 */
public interface Media extends Serializable
{
   static final String MIME_TYPE_UNKNOWN = "www/unknown";

   /**
    * Returns the complete media content as a byte array. This method is
    * intended for convenient access to media content up to a few MB in size.
    * Streaming I/O access as defined in readContent() should be used instead
    * to access large content.
    * 
    * @return the media content.
    * @throws javax.emb.ContentTooLargeException if the resulting byte array
    *         size exceeds the theoretical maximum Java array size of 2 GB.
    * @throws javax.emb.ContentAccessException if the content cannot be
    *         accessed.
    */
   byte[] getContent() throws MediaException;

   /**
    * Queries a suitable media format instance from the MediaFormatRegistry
    * singleton and returns it. The file extension contained in the name
    * property is used as a key for this query.
    * 
    * @return the media format.
    * @throws javax.emb.FormatNotFoundException if the file extension is not
    *         registered with the media format registry.
    */
   MediaFormat getFormat() throws MediaException;

   /**
    * Returns the receiver's header information. Queries a suitable media
    * format instance from the MediaFormatRegistry singleton and determines the
    * header information based on it.
    * 
    * @return the media header.
    * @throws javax.emb.FormatNotFoundException if the file extension is not
    *         registered with the media format registry.
    * @throws javax.emb.FormatSyntaxException if the receiver's content does
    *         not match the syntax defined for the receiver's media format.
    * @throws javax.emb.FormatFeatureException if the header cannot be
    *         extracted because a vital feature of the media format involved is
    *         not supported by the implementation.
    * @throws javax.emb.ContentAccessException if the actual content access
    *         fails.
    */
   MediaHeader getHeader() throws MediaException;

   /**
    * Returns a mime type for the receiver's content as a string. This allows
    * media content to be written directly to a Servlet output stream, as this
    * technique requires a mime type to be specified in case the output is
    * different from HTML. If no mime type has been set explicitly a default
    * mime type is returned, possibly based on the receiver's format.
    * 
    * @return the mime type.
    * @throws javax.emb.FormatNotFoundException if the receiver's media format
    *         cannot be determined.
    */
   String getMimeType() throws MediaException;

   /**
    * Returns the receiver's non-unique name as a String. The name is used as a
    * file name hint in case the media content is to be stored in a file system
    * and therefore may only contain characters that are valid in file names.
    * It contains a file extension that represents the receiver's media format.
    * 
    * @return the media name.
    */
   String getName() throws MediaException;

   /**
    * Returns a media object that can be used as a proxy for the receiver, e.g.
    * a thumbnail, an icon, a short video/audio clip. Servlets can use this
    * operation whenever a thumbnail or sound bite is required to represent a
    * given media and give users an up front impression of the content. The
    * value returned may have any format and is never null.
    * 
    * @return the media proxy
    */
   Media getProxy() throws MediaException;

   /**
    * This operation returns the receiver's content size in number of bytes as
    * a long value.
    * 
    * @return the media size.
    * @throws javax.emb.ContentAccessException if there's a problem accessing
    *         the receiver's content.
    */
   long getSize() throws MediaException;

   /**
    * Similarly to input streams, this method fills the given buffer with
    * content read from the media object. The media content is copied from the
    * given position, and the buffer is filled beginning with offset 0. In case
    * the buffer is larger than the amount of bytes available, it is only
    * partially filled. The buffer may also be filled partially if the
    * implementation uses non-blocking I/O. The method returns the number of
    * bytes copied into the buffer, or -1 in case the given position equals the
    * content size.
    * 
    * @param position the position in media to copy from.
    * @param buffer the byte array to store content.
    * @return the number of bytes copied into the buffer.
    * @throws java.lang.IndexOutOfBoundsException if the given position is
    *         negative or exceeding the content size.
    * @throws java.lang.NullPointerException if the given buffer is null.
    * @throws javax.emb.ContentAccessException if the actual content access
    *         fails.
    */
   int readContent(long position, byte[] buffer) throws MediaException;

   /**
    * Similar to input streams, this method fills the given buffer with content
    * read from the media object. The media content is copied from the given
    * position, and the buffer is filled beginning from the given offset with a
    * maximum amount of bytes defined by the given length. In case the buffer
    * is larger than the amount of bytes available, it is only partially
    * filled. The buffer may also be filled partially if the implementation
    * uses non-blocking I/O. The method returns the number of bytes copied into
    * the buffer, or -1 in case the given position equals the content size.
    * 
    * @param position the position in media to copy from.
    * @param buffer the byte array to store content.
    * @param offset the offset in the buffer to begin storing content.
    * @param length the number of bytes to copy from the content.
    * @return number of bytes copied into the buffer.
    * @throws java.lang.IndexOutOfBoundsException if the given position is
    *         negative or exceeding the content size, or in case the given
    *         offset is negative or exceeding the buffer size.
    * @throws java.lang.NegativeArraySizeException if the given length is
    *         negative.
    * @throws java.lang.NullPointerExcetion if the given buffer is null.
    * @throws javax.emb.ContentAccessException if the actual content access
    *         fails.
    */
   int readContent(long position, byte[] buffer, int offset, int length)
      throws MediaException;
}