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

package javax.emb;

import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;

/**
 * This interface is used throughout Enterprise Media Beans for operations that
 * require knowledge of the media format. Each specific supported media format
 * requires an implementation of this interface to handle format specifics
 * correctly. Applications should not create instances directly using a
 * constructor, but instead query them using the {@link MediaFormatRegistry}
 * class. As implementations of this interface may have to be transferred over
 * remote boundaries at times, the MediaFormat interface extends
 * {@link java.io.Serializable}.
 * 
 * @version <tt>$Revision: 1.3 $</tt>
 * @author <a href="mailto:ricardoarguello@users.sourceforge.net">Ricardo
 *         Argüello</a>
 */
public interface MediaFormat extends Serializable
{
   /**
    * Assembles the given media segments and returns the resulting media
    * content as a byte array. The optional media location describes where the
    * content itself is stored, and passing it allows links to child media to
    * be written as relative file paths. In case the given media location is
    * <code>null</code>, all links in the resulting media content will be
    * URLs. In case it is not <code>null</code>, those links that can be
    * expressed relative to the given URL will be relative file paths, and all
    * others will be URLs.
    * 
    * <p>This means a media object that has been disassembled into media
    * segments beforehand can be reassembled using this operation. The given
    * media location is used to handle relative links to external media
    * correctly. Media Entity Beans use this operation when maintaining
    * referential integrity between complex graphs of persistent, non-embedded,
    * media objects. The implicit limitation of media size to a theoretical
    * limit of 2GB should not impose a restriction in practice as this
    * operation is only of value for non-embedded media, which tends to be
    * relatively small in size.
    * 
    * @param mediaLocation the intended location of the media to be assembled.
    * @param mediaSegments the segments that are to be assembled.
    * @return the assembled content.
    * @throws javax.emb.ContentTooLargeException if the resulting byte array
    *         size exceeds the theoretical maximum Java array size of 2 GB,
    * @throws javax.emb.LinkTranslationException if there's a problem
    *         transforming one of the media segment child locations into a
    *         format specific link.
    * @throws javax.emb.FormatSyntaxException in case of embedded media
    *         formats, thrown if the given media segment array contains more
    *         than one element, or if an element is passed that contains a
    *         child link that is not <code>null</code>.
    * @throws java.lang.NullPointerException if the given segment array is
    *         <code>null</code>.
    */
   byte[] assembleContent(URL mediaLocation, MediaSegment[] mediaSegments)
      throws MediaException;

   /**
    * Disassembles the given media content into an array of media segments
    * preserving the order of the original content, and returns said array of
    * media segments. The optional media location describes where the content
    * itself is stored, and passing it allows relative links to child media to
    * be interpreted.
    * 
    * <p>In case of simple media formats, the resulting media segment array
    * contains exactly one element, which consists of <code>null</code> as
    * child location and the complete media content as content. Media Entity
    * Beans use this operation when maintaining referential integrity between
    * complex graphs of persistent, non embedded, media objects. Note that this
    * operation is only of value for non-embedded media formats. As the
    * reassembly is limited to media up to 2GB in size, the
    * {@link MediaFormat.isEmbedded()}operation should be used to determine if
    * disassembling a given media content is of value beforehand.
    * 
    * @param mediaLocation the location of the media to be disassembled.
    * @param mediaContent the content to be disassembled.
    * @return the segments.
    * @throws javax.emb.FormatSyntaxException if the content does not match the
    *         expected media format.
    * @throws javax.emb.LinkTranslationException if the given media location is
    *         <code>null</code> and the given content contains child links
    *         that are not URLs.
    * @throws java.lang.NullPointerException if the content passed is <code>null</code>.
    */
   MediaSegment[] disassembleContent(URL mediaLocation, byte[] mediaContent)
      throws MediaException;

   /**
    * Extracts a media header instance from the given media content and returns
    * it. The information presented by the header is up to the implementation
    * of the media format bean, and the information returned can therefore be
    * the complete header information as defined in the relevant media format
    * standard, no information at all, or something in between. However,
    * implementers are encouraged to return header information as complete as
    * possible, as such information can be highly useful for format specific
    * algorithms and optimizations.
    * 
    * <p>Please note that the given input stream is not closed once the
    * operation is successfully completed.
    * 
    * @param content the media content to extract the header from.
    * @return the header.
    * @throws javax.emb.FormatSyntaxException if the given media content does
    *         not match the syntax defined for the receiver.
    * @throws javax.emb.FormatFeatureException if the header cannot be
    *         extracted because a vital feature of the media format involved is
    *         not supported.
    * @throws java.lang.NullPointerException if the value passed is <code>null</code>.
    */
   MediaHeader extractHeader(InputStream content) throws MediaException;

   /**
    * Extracts a proxy from the given media content and returns it. The proxy
    * may be of any media format. For example, a key frame image may be
    * returned in case of video content, a waveform image in case of audio
    * content, or a thumbnail in case of image content. In case there's a
    * problem creating the surrogate, a default format specific proxy must be
    * returned - for example <code>GenericMediaFormat.GENERIC_PROXY</code>.
    * Please note that the given input stream is closed once the operation is
    * completed.
    * 
    * @param content the content to extract the proxy from.
    * @return the proxy.
    * @throws javax.emb.MediaException if the given media is not compatible
    *         with the receiver
    * @throws java.lang.NullPointerException if the argument passed is <code>null</code>.
    */
   Media extractProxy(InputStream content) throws MediaException;

   /**
    * Returns the default MIME type for the given media format as a String. If
    * there is no suitable MIME type, <code>Media.MIME_TYPE_UNKNOWN</code>
    * should be returned.
    * 
    * @return the default MIME type.
    */
   public String getDefaultMimeType();

   /**
    * Returns <code>false</code> if the media format allows links to external
    * media, or true otherwise. It can be used to determine if the media
    * content has to be examined and possibly altered when a persistent media
    * object is moved from one location to another while having child and/or
    * parent dependencies to other media objects.
    * 
    * @return <code>true</code> if the format is embedded, <code>false</code>
    *         if it is non-embedded.
    */
   public boolean isEmbedded();

   /**
    * Returns <code>true</code> if it is always desirable to stream media of
    * this format, or false otherwise. For example, it is not always desirable
    * to stream JPEG or GIF images, even given the possibility to stream them
    * with a Real player. Servlets can use this information to decide whether
    * they should try to stream content or transfer it using burst transfer
    * instead.
    * 
    * @return <code>true</code> if it desirable to stream the format, <code>false</code>
    *         otherwise.
    */
   public boolean isStreamingDesirable();
}