//******************************************************************************
//
// File:    Doc.java
// Package: net.jini.print.data
// Unit:    Interface net.jini.print.data.Doc
//
//******************************************************************************

package net.jini.print.data;

import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;

import javax.print.attribute.DocAttributeSet;

import javax.print.DocFlavor;

/**
 * Interface Doc specifies the interface for an object that supplies one piece 
 * of print data for a Print Job. "Doc" is a short, easy-to-pronounce term that 
 * means "a piece of print data." The client passes to the Print Job an object 
 * that implements interface Doc, and the Print Job calls methods on that object 
 * to obtain the print data. The Doc interface lets a Print Job: 
 * <UL>
 * <LI>
 * Determine the format, or "doc flavor" (class {@link 
 * javax.print.data.DocFlavor DocFlavor}), in which the print data is available. 
 * A doc flavor designates the print data format (a MIME type) and the 
 * representation class of the object from which the print data comes. 
 * <P>
 * <LI>
 * Obtain the print data representation object, which is an instance of the doc 
 * flavor's representation class. The Print Job can then obtain the actual print 
 * data from the representation object.
 * <P>
 * <LI>
 * Obtain the printing attributes that specify additional characteristics of the 
 * doc or that specify processing instructions to be applied to the doc. 
 * Printing attributes are defined in package {@link javax.print.attribute 
 * javax.print.attribute}. The doc returns its printing attributes stored in 
 * an {@link javax.print.attribute.AttributeSet AttributeSet}. 
 * </UL>
 * <P>
 * Interface net.jini.print.data.Doc extends interface {@link 
 * javax.print.data.Doc javax.print.data.Doc}. The superinterface {@link 
 * javax.print.data.Doc javax.print.data.Doc} defines doc semantics that 
 * pertains to both the Unified Printing API and the Jini Print Service API. The 
 * subinterface net.jini.print.data.Doc defines more restricted doc semantics 
 * that pertains to just the Jini Print Service API. In particular, a doc object 
 * used in the Jini Print Service API must be serializable, must take into 
 * account the possibility that the doc's methods are being called in a remote 
 * location, and must take into account the possibility that the print data is 
 * leased (see below for further information). 
 * <P>
 * Interface Doc extends interface {@link java.io.Serializable Serializable}, 
 * and all Doc implementations must be serializable objects. If a Doc 
 * implementation is not serializable -- for example, if it has a non-transient 
 * non-serializable field or fields -- then the Doc implementation has a defect. 
 * If a client passes such a defective Doc object to a print service proxy, the 
 * print service proxy's behavior is unspecified. For example, the print service 
 * proxy is permitted (but not required) to throw a NotSerializableException. 
 * <P>
 * An implementation of interface Doc must be serializable so that a Doc object 
 * will work properly even if it is serialized and sent to a remote location 
 * where its methods are called. In other words, when a client passes a Doc 
 * object to a Jini Print Service proxy object, either the print service proxy 
 * can extract the doc's information by calling the Doc object's methods in the 
 * client's local Java Virtual Machine (JVM), or the print service proxy can 
 * send the Doc object to a remote print service which extracts the doc's 
 * information by calling the Doc object's methods in the remote JVM. 
 * <P>
 * Nonetheless, interface Doc is not intended to be implemented as a remote 
 * object. An implementation of interface Doc is intended always to be just a 
 * container of the information needed to return the doc flavor, print data 
 * representation object, and attribute set when called for, and interface Doc's 
 * methods are intended always to execute locally in the caller's JVM (i.e., not 
 * make remote method calls). To allow a Print Job to obtain print data from a 
 * remote JVM, the doc object should be implemented so the {@link 
 * #getPrintData() <CODE>getPrintData()</CODE>} method returns a print data 
 * representation object that accesses the remote JVM; for example, the print 
 * data representation object is an RMI stub for a remote object exported by the 
 * remote JVM. 
 * <P>
 * Each method in an implementation of interface Doc is permitted always to 
 * return the same object each time the method is called. This has implications 
 * for a Print Job or other caller of a doc object whose print data 
 * representation object "consumes" the print data as the caller obtains the 
 * print data, such as a print data representation object which is a stream. 
 * Once the Print Job has called {@link #getPrintData() 
 * <CODE>getPrintData()</CODE>} and obtained the stream, any further calls to 
 * {@link #getPrintData() <CODE>getPrintData()</CODE>} will return the same 
 * stream object upon which reading may already be in progress, <I>not</I> a new 
 * stream object that will re-read the print data from the beginning. Specifying 
 * a doc object to behave this way simplifies the implementation of doc objects, 
 * and is justified on the grounds that a particular doc is intended to convey 
 * print data only to one Print Job, not to several different Print Jobs. (To 
 * convey the same print data to several different Print Jobs, you have to 
 * create several different doc objects on top of the same print data source.) 
 * <P>
 * Interface Doc affords considerable implementation flexibility. The print data 
 * might already be in existence when the doc object is constructed. In this 
 * case the objects returned by the doc's methods can be supplied to the doc's 
 * constructor, be stored in the doc ahead of time, and simply be returned when 
 * called for. Alternatively, the print data might not exist yet when the doc 
 * object is constructed. In this case the doc object might provide a "lazy" 
 * implementation that generates the print data representation object (and/or 
 * the print data) only when the Print Job calls for it (when the Print Job 
 * calls the {@link #getPrintData() <CODE>getPrintData()</CODE>} method). 
 * <P>
 * Some print data sources may allocate resources that need to be deallocated if 
 * there is a distributed failure of the Print Service printing the data. For 
 * example, the print data may be ephemeral and the print data source may need 
 * to release storage or other resources once the print data has been 
 * transferred to the Print Service. The print data source must be able 
 * eventually to release resources if the Print Service fails to obtain the 
 * print data. This is done using the standard Jini lease mechanism. A doc 
 * object can convey a lease on the print data by implementing the optional 
 * interface {@link LeasedDoc LeasedDoc}. See interface {@link LeasedDoc 
 * LeasedDoc} for further information. 
 * <P>
 * If a doc object is leased, the doc object's user (typically the printer) must 
 * get the lease object before doing anything else with the doc. Specifically, 
 * if a doc object implements interface {@link LeasedDoc LeasedDoc}, then the 
 * first method invoked on the doc object after it is created must be the {@link 
 * LeasedDoc#getLease() <CODE>getLease()</CODE>} method. Other Doc methods will 
 * throw an IllegalStateException until the user has obtained the doc's lease 
 * object. 
 * <P>
 * A print data source is permitted (but not required) to impose a restriction 
 * on how the multiple doc objects in a multidoc print job are accessed: that 
 * the printer must finish obtaining all the print data from one doc before 
 * going on to another doc. This is to accommodate the needs of low-end clients 
 * which may lack the resources to provide print data for more than one doc at a 
 * time. If the print data source imposes this restriction, the doc object's 
 * {@link #getPrintData() <CODE>getPrintData()</CODE>}, {@link 
 * #getReaderForText() <CODE>getReaderForText()</CODE>}, and {@link 
 * #getStreamForBytes() <CODE>getStreamForBytes()</CODE>} methods will throw an 
 * IllegalStateException if this restriction is violated. Since a printer 
 * doesn't know whether any particular print data source imposes this 
 * restriction, every Jini Print Service instance must be implemented assuming 
 * that <I>all</I> print data sources impose this restriction. 
 * <P>
 * There is no restriction on the number of client threads that may be 
 * simultaneously accessing the same doc. Therefore, all implementations of 
 * interface Doc must be designed to be multiple thread safe. 
 * <P>
 * <HR>
 * <H3>Design Rationale</H3>
 * <P>
 * A Doc object must be able to execute locally or remotely to afford more 
 * choice for implementing Jini Print Service instances and to enable greater 
 * flexibility for setting up distributed printing applications. Since a Doc 
 * object will work when executed either locally or remotely, a Jini Print 
 * Service client doesn't need to know whether a Jini Print Service instance is 
 * implemented locally or remotely; it just passes the Doc object to the Jini 
 * Print Service instance. In fact, a Doc object could be created in one place 
 * and passed from place to place through several intermediate services before 
 * finally ending up at a Jini Print Service instance. 
 * <P>
 * Interface Doc in package net.jini.print.data is similar to interface 
 * {@link java.awt.datatransfer.Transferable Transferable} in package {@link 
 * java.awt.datatransfer java.awt.datatransfer}, which is used for 
 * clipboard-style data transfers. Interface java.awt.datatransfer.Transferable 
 * is not used in the Jini Print Service API for four reasons: 
 * <OL TYPE=1>
 * <LI>
 * Since not all Java profiles include the AWT, the Jini Print Service should 
 * not depend on an AWT interface. 
 * <P>
 * <LI>
 * While a Transferable object indicates the data format using class {@link 
 * java.awt.datatransfer.DataFlavor java.awt.datatransfer.DataFlavor}, a Doc 
 * object needs to indicate the print data format using class {@link 
 * javax.print.data.DocFlavor DocFlavor}. See class {@link 
 * javax.print.data.DocFlavor DocFlavor} for further explanation. 
 * <P>
 * <LI>
 * Since clipboard-style data transfers typically make the same data available 
 * in several different formats, a Transferable object needs the capability to 
 * support multiple data flavors. However, print data is typically available in 
 * only one predetermined format. Interface Transferable's multiple data format 
 * capability would introduce unnecessary complexity to the Jini Print Service, 
 * so interface Doc provides the print data in just one doc flavor. 
 * <P>
 * <LI>
 * A Print Job needs additional information about the doc, namely the printing 
 * attributes, that a Transferable object can't supply. 
 * </OL>
 * <P>
 * <B>DRAFT STANDARD VERSION 1.0 (23-MAY-2000)</B>
 *
 * @author  Alan Kaminsky
 * @version 22-May-2000
 */
public interface Doc
	extends javax.print.Doc, Serializable
	{

// Exported operations.

	/**
	 * Determine the doc flavor in which this doc object will supply its piece 
	 * of print data. 
	 * <P>
	 * If this doc object is leased and the lease has expired or been canceled, 
	 * the behavior of this method is undefined. 
	 *
	 * @return  Doc flavor.
	 *
	 * @exception  IllegalStateException
	 *     (unchecked exception) Thrown if this doc object is leased and its 
	 *     lease object has not yet been obtained (i.e., this doc object is an 
	 *     instance of the subinterface {@link LeasedDoc LeasedDoc} and its 
	 *     {@link LeasedDoc#getLease() <CODE>getLease()</CODE>} method has not 
	 *     yet been called). 
	 */
	public DocFlavor getDocFlavor();

	/**
	 * Obtain the print data representation object that contains this doc 
	 * object's piece of print data in the format corresponding to the supported 
	 * doc flavor. The <CODE>getPrintData()</CODE> method returns an instance of 
	 * the representation class whose name is given by <CODE>{@link 
	 * #getDocFlavor() getDocFlavor()}.{@link 
	 * javax.print.data.DocFlavor#getRepresentationClassName() 
	 * getRepresentationClassName()}</CODE>, and the return value can be cast 
	 * from class Object to that representation class. 
	 * <P>
	 * If this doc object is leased and the lease has expired or been canceled, 
	 * the behavior of this method is undefined. 
	 *
	 * @return  Print data representation object. 
	 *
	 * @exception  IOException
	 *     Thrown if the representation class is a stream and there was an I/O 
	 *     error while constructing the stream. 
	 * @exception  IllegalStateException
	 *     (unchecked exception) Thrown if this doc object is leased and its 
	 *     lease object has not yet been obtained (i.e., this doc object is an 
	 *     instance of the subinterface {@link LeasedDoc LeasedDoc} and its 
	 *     {@link LeasedDoc#getLease() <CODE>getLease()</CODE>} method has not 
	 *     yet been called). Also may be thrown (but is not required to be 
	 *     thrown) if the printer has not finished obtaining all the print data 
	 *     from a previous doc before requesting the print data from this doc. 
	 */
	public Object getPrintData()
		throws IOException;

	/**
	 * Obtain the set of printing attributes for this doc object. If the 
	 * returned attribute set includes an instance of a particular attribute 
	 * <I>X,</I> the printer must use that attribute value for this doc, 
	 * overriding any value of attribute <I>X</I> in the Print Request's 
	 * attribute set. If the returned attribute set does not include an instance 
	 * of a particular attribute <I>X</I> or if null is returned, the printer 
	 * must consult the Print Request's attribute set to obtain the value for 
	 * attribute <I>X,</I> and if not found there, the printer must use an 
	 * implementation-dependent default value. The returned attribute set is 
	 * unmodifiable. 
	 * <P>
	 * If this doc object is leased and the lease has expired or been canceled, 
	 * the behavior of this method is undefined. 
	 *
	 * @return  Unmodifiable set of printing attributes for this doc, or null to
	 *          obtain all attribute values from the Print Request's attribute 
	 *          set. 
	 * @exception  IllegalStateException
	 *     (unchecked exception) Thrown if this doc object is leased and its 
	 *     lease object has not yet been obtained (i.e., this doc object is an 
	 *     instance of the subinterface {@link LeasedDoc LeasedDoc} and its 
	 *     {@link LeasedDoc#getLease() <CODE>getLease()</CODE>} method has not 
	 *     yet been called). 
	 */
	public DocAttributeSet getAttributes();

	/**
	 * Obtain a reader for extracting character print data from this doc. For 
	 * this method to work, this doc's flavor must have one of the following 
	 * print data representation classes: 
	 * <UL>
	 * <LI> char[]
	 * <LI> java.lang.String
	 * <LI> java.io.Reader
	 * <LI> byte[]
	 * <LI> java.io.InputStream
	 * </UL>
	 * For a byte array or input stream, this doc's flavor must also have a MIME 
	 * media type of <CODE>"text"</CODE> with an optional <CODE>"charset"</CODE> 
	 * parameter; the default character set is UTF-8. This doc's print data 
	 * representation object is obtained, then a reader for reading the print 
	 * data from the print data representation object as a stream of characters 
	 * is created and returned. However, if the print data representation object 
	 * is itself a reader, then the print data representation object is simply
	 * returned. 
	 * <P>
	 * If this doc fulfills the above criteria, then this method is required to 
	 * return a valid non-null reader object for reading the print data 
	 * characters from this doc. If this doc does not fulfill the above 
	 * criteria, then this method returns null to indicate a reader cannot be 
	 * provided. 
	 * <P>
	 * Note that if a reader needs to be layered on top of this doc's print data 
	 * representation object, the reader will be created and will execute in the 
	 * caller's Java Virtual Machine (JVM). If this doc's print data 
	 * representation object is a remote input stream, be aware that this method 
	 * will return a local reader layered on top of the remote input stream. 
	 * <P>
	 * If this doc object is leased and the lease has expired or been canceled, 
	 * the behavior of this method is undefined. 
	 *
	 * @return  Reader for reading the print data characters from this doc. If a
	 *          reader cannot be provided because this doc does not meet the 
	 *          criteria stated above, null is returned. 
	 *
	 * @exception  UnsupportedEncodingException
	 *     Thrown if a plain text doc's character set is not supported.
	 * @exception  IOException
	 *     Thrown if there was an I/O error while creating the reader.
	 * @exception  IllegalStateException
	 *     (unchecked exception) Thrown if this doc object is leased and its 
	 *     lease object has not yet been obtained (i.e., this doc object is an 
	 *     instance of the subinterface {@link LeasedDoc LeasedDoc} and its 
	 *     {@link LeasedDoc#getLease() <CODE>getLease()</CODE>} method has not 
	 *     yet been called). Also may be thrown (but is not required to be 
	 *     thrown) if the printer has not finished obtaining all the print data 
	 *     from a previous doc before requesting the print data from this doc. 
	 */
	public Reader getReaderForText()
		throws UnsupportedEncodingException, IOException;

	/**
	 * Obtain an input stream for extracting byte print data from this doc. For 
	 * this method to work, this doc's flavor must have one of the following 
	 * print data representation classes: 
	 * <UL>
	 * <LI> byte[]
	 * <LI> java.io.InputStream
	 * </UL>
	 * This doc's print data representation object is obtained, then an input 
	 * stream for reading the print data from the print data representation 
	 * object as a stream of bytes is created and returned. However, if the 
	 * print data representation object is itself an input stream, then the 
	 * print data representation object is simply returned. 
	 * <P>
	 * If this doc fulfills the above criteria, then this method is required to 
	 * return a valid non-null input stream object for reading the print data 
	 * bytes from this doc. If this doc does not fulfill the above criteria, 
	 * then this method returns null to indicate an input stream cannot be 
	 * provided. 
	 * <P>
	 * Note that if an input stream needs to be layered on top of this doc's 
	 * print data representation object, the input stream will be created and 
	 * will execute in the caller's Java Virtual Machine (JVM). 
	 * <P>
	 * If this doc object is leased and the lease has expired or been canceled, 
	 * the behavior of this method is undefined. 
	 *
	 * @return  Input stream for reading the print data bytes from this doc. If
	 *          an input stream cannot be provided because this doc does not 
	 *          meet the criteria stated above, null is returned. 
	 *
	 * @exception  IOException
	 *     Thrown if there was an I/O error while creating the input stream.
	 * @exception  IllegalStateException
	 *     (unchecked exception) Thrown if this doc object is leased and its 
	 *     lease object has not yet been obtained (i.e., this doc object is an 
	 *     instance of the subinterface {@link LeasedDoc LeasedDoc} and its 
	 *     {@link LeasedDoc#getLease() <CODE>getLease()</CODE>} method has not 
	 *     yet been called). Also may be thrown (but is not required to be 
	 *     thrown) if the printer has not finished obtaining all the print data 
	 *     from a previous doc before requesting the print data from this doc. 
	 */
	public InputStream getStreamForBytes()
		throws IOException;

	}