//******************************************************************************
//
// File:    PrintDataEvent.java
// Package: net.jini.print.job
// Unit:    Class net.jini.print.job.PrintDataEvent
//
//******************************************************************************

package net.jini.print.job;

import java.io.IOException;

import java.rmi.MarshalledObject;

import net.jini.print.event.PrintEvent;

import net.jini.print.service.PrintService;

/**
 * Class PrintDataEvent encapsulates an event a Jini Print Service instance 
 * reports to let the client know that a Print Job has finished obtaining a 
 * piece of print data. The event reports whether the Print Job succeeded or 
 * failed to obtain the print data. In the case of failure, the event includes 
 * an exception object telling what went wrong. See the description of print job 
 * processing in interface {@link PrintJob PrintJob} for further information on 
 * when print data events are reported. 
 * <P>
 * The Jini Print Service is <I>not</I> required to guarantee that print data 
 * events are delivered reliably in sequence. In other words, print data events 
 * may be lost or delivered out of order due to processor or network failures. 
 * <H4>Design</H4>
 * A print data event object contains a Print Job object and possibly an 
 * exception object. These objects are stored inside the print data event object 
 * in marshalled form. This allows the print data event object to flow through 
 * intermediate event listeners without requiring those event listeners to 
 * download the Print Job object's or exception object's codebases. When the 
 * print data event object arrives at its ultimate destination, the {@link 
 * #getPrintJob() <CODE>getPrintJob()</CODE>} and {@link #getException() 
 * <CODE>getException()</CODE>} methods unmarshal their respective objects, 
 * downloading the codebases if necessary at that time. 
 * <P>
 * <B>DRAFT STANDARD VERSION 1.0 (23-MAY-2000)</B>
 *
 * @author  Alan Kaminsky
 * @version 10-Mar-2000
 */
public class PrintDataEvent
	extends PrintEvent
	{

// Hidden data members.

	/**
	 * Print Job object (in marshalled form) to which this event pertains.
	 * @serial
	 */
	private MarshalledObject printJob;

	/**
	 * Exception object (in marshalled form) telling what went wrong if the Jini 
	 * Print Service instance failed to obtain the print data, or null if the 
	 * print service successfully obtained the print data. 
	 * @serial
	 */
	private MarshalledObject exception;
 
// Exported constructors.

	/**
	 * Constructs a new print data event object. 
	 *
	 * @param  theSource          Event source, namely the print service that
	 *                            reported this event.
	 * @param  theEventID         Event identifier for this event.
	 * @param  theSequenceNumber  Sequence number for this event.
	 * @param  theHandbackObject  Handback object for this event, or null if
	 *                            there is no handback object.
	 * @param  thePrintJob        Print Job object to which this event pertains.
	 * @param  theException       An exception object telling what went wrong if
	 *                            the print service failed to obtain the print 
	 *                            data, or null if the print service 
	 *                            successfully obtained the print data. 
	 *
	 * @exception  NullPointerException
	 *     (unchecked exception) Thrown if <CODE>theSource</CODE> is null or 
	 *     <CODE>thePrintJob</CODE> is null. 
	 * @exception  IOException
	 *     Thrown if there was an I/O error while marshalling 
	 *     <CODE>thePrintJob</CODE> or <CODE>theException</CODE>, such as if one 
	 *     or both is not serializable. 
	 */
	public PrintDataEvent
		(PrintService theSource,
		 long theEventID,
		 long theSequenceNumber,
		 MarshalledObject theHandbackObject,
		 PrintJob thePrintJob,
		 Throwable theException)
		throws IOException
		{
		super (theSource, theEventID, theSequenceNumber, theHandbackObject);
		printJob = new MarshalledObject (verify (thePrintJob));
		exception =
			theException == null ?
				null :
				new MarshalledObject (theException);
		}

	private static PrintJob verify
		(PrintJob thePrintJob)
		{
		if (thePrintJob == null)
			{
			throw new NullPointerException
				("net.jini.print.job.PrintDataEvent.PrintDataEvent(): thePrintJob is null");
			}
		return thePrintJob;
		}

// Exported operations.

	/**
	 * Determine the Print Job to which this print data event pertains.
	 *
	 * @return  Print Job object.
	 *
	 * @exception  IOException
	 *     Thrown if there was an I/O error while unmarshalling the Print Job 
	 *     object. 
	 * @exception  ClassNotFoundException
	 *     Thrown if a class needed to unmarshal the Print Job object could not 
	 *     be found. 
	 */
	public PrintJob getPrintJob()
		throws IOException, ClassNotFoundException
		{
		return (PrintJob) printJob.get();
		}

	/**
	 * Determine whether the print service successfully obtained the print data. 
	 *
	 * @return  If this event is reporting that the print service successfully 
	 *          obtained the print data, true is returned. If this event is 
	 *          reporting that the print service failed to obtain the print 
	 *          data, false is returned. 
	 */
	public boolean succeeded()
		{
		return exception == null;
		}

	/**
	 * Determine what went wrong if the print service failed to obtain the print 
	 * data. 
	 *
	 * @return  If this event is reporting that the print service successfully 
	 *          obtained the print data, null is returned. If this event is 
	 *          reporting that the print service failed to obtain the print 
	 *          data, an exception object telling what went wrong is returned. 
	 *
	 * @exception  IOException
	 *     Thrown if there was an I/O error while unmarshalling the exception 
	 *     object. 
	 * @exception  ClassNotFoundException
	 *     Thrown if a class needed to unmarshal the exception object could not 
	 *     be found. 
	 */
	public Throwable getException()
		throws IOException, ClassNotFoundException
		{
		return exception == null ? null : (Throwable) exception.get();
		}

	}