//******************************************************************************
//
// File:    PrinterDescriptionEntry.java
// Package: net.jini.print.lookup
// Unit:    Class net.jini.print.lookup.PrinterDescriptionEntry
//
//******************************************************************************

package net.jini.print.lookup;

import javax.print.attribute.Attribute;

import javax.print.attribute.standard.PrinterName;
import javax.print.attribute.standard.PrinterLocation;
import javax.print.attribute.standard.PrinterInfo;
import javax.print.attribute.standard.PrinterMoreInfo;
import javax.print.attribute.standard.PrinterMakeAndModel;
import javax.print.attribute.standard.PrinterMoreInfoManufacturer;
import javax.print.attribute.standard.ColorSupported;
import javax.print.attribute.standard.PDLOverrideSupported;
import javax.print.attribute.standard.PagesPerMinute;
import javax.print.attribute.standard.PagesPerMinuteColor;

import net.jini.entry.AbstractEntry;

import net.jini.lookup.entry.ServiceControlled;

/**
 * Class PrinterDescriptionEntry is a Jini service attribute a Jini Print 
 * Service instance includes in its service registration in the Jini Lookup 
 * Service (JLUS) to advertise general information about the printer. Clients 
 * can then specify this information when they search the JLUS for Jini Print 
 * Service instances.
 * <P>
 * A printer description entry consists of the following fields containing 
 * printer description attributes.
 * <UL>
 * <LI> {@link javax.print.attribute.standard.PrinterName PrinterName}
 * <LI> {@link javax.print.attribute.standard.PrinterLocation PrinterLocation}
 * <LI> {@link javax.print.attribute.standard.PrinterInfo PrinterInfo}
 * <LI> {@link javax.print.attribute.standard.PrinterMoreInfo PrinterMoreInfo}
 * <LI> {@link javax.print.attribute.standard.PrinterMakeAndModel PrinterMakeAndModel}
 * <LI> {@link javax.print.attribute.standard.PrinterMoreInfoManufacturer PrinterMoreInfoManufacturer}
 * <LI> {@link javax.print.attribute.standard.ColorSupported ColorSupported}
 * <LI> {@link javax.print.attribute.standard.PDLOverrideSupported PDLOverrideSupported}
 * <LI> {@link javax.print.attribute.standard.PagesPerMinute PagesPerMinute}
 * <LI> {@link javax.print.attribute.standard.PagesPerMinuteColor PagesPerMinuteColor}
 * </UL> 
 * <P>
 * In a printer description entry stored in a service registration in the JLUS, 
 * the {@link PrinterName PrinterName} and {@link PDLOverrideSupported 
 * PDLOverrideSupported} fields are mandatory and must always be set to non-null 
 * values. The remaining fields are optional and may be set to null to indicate 
 * "not specified." However, if the {@link PagesPerMinuteColor 
 * PagesPerMinuteColor} field is set to a non-null value, the {@link 
 * ColorSupported ColorSupported} field must be set to a value of SUPPORTED. 
 * <P>
 * As usual, when used to search the JLUS for matching printers, any printer 
 * description entry field may be set to null to match any value (wildcard) or 
 * may be set to a non-null value to match that attribute value. 
 * <P>
 * The above printer description attributes can also appear in a Jini Print 
 * Service instance's attribute set returned by the {@link 
 * net.jini.print.service.PrintService#getAttributes() 
 * <CODE>PrintService.getAttributes()</CODE>} method. Thus, a client can 
 * discover these information items either by querying the Print Service object 
 * or by examining the service registration in the JLUS. The above attributes 
 * rarely if ever change their values and hence are suitable to be included in 
 * the JLUS service registration. (If an administrator reconfigures the printer, 
 * these attributes might change.) The Print Service's attribute set includes 
 * additional printer description attributes whose values change dynamically as 
 * the printer operates; such attributes are not included in the printer 
 * description entry in the JLUS service registration. 
 * <P>
 * The items included in a PrinterDescriptionEntry are not printing attributes 
 * the client can specify when setting up a print job. Support for 
 * client-specifiable printing attributes is indicated using {@link 
 * AttributeEntry AttributeEntry} and {@link MediaEntry MediaEntry}. 
 * <P>
 * <B>DRAFT STANDARD VERSION 1.0 (23-MAY-2000)</B>
 *
 * @author  Alan Kaminsky
 * @version 11-May-2000
 */
public class PrinterDescriptionEntry
	extends AbstractEntry
	implements ServiceControlled
	{

// Exported fields.

	/**
	 * Printer name, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterName printerName = null;

	/**
	 * Printer location, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterLocation printerLocation = null;

	/**
	 * Printer info, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterInfo printerInfo = null;

	/**
	 * Printer more info, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterMoreInfo printerMoreInfo = null;

	/**
	 * Printer make and model, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterMakeAndModel printerMakeAndModel = null;

	/**
	 * Printer more info manufacturer, or null if not specified or wildcarded.
	 * @serial
	 */
	public PrinterMoreInfoManufacturer printerMoreInfoManufacturer = null;

	/**
	 * Color supported, or null if not specified or wildcarded.
	 * @serial
	 */
	public ColorSupported colorSupported = null;

	/**
	 * PDL override supported, or null if not specified or wildcarded.
	 * @serial
	 */
	public PDLOverrideSupported pdlOverrideSupported = null;

	/**
	 * Pages per minute, or null if not specified or wildcarded.
	 * @serial
	 */
	public PagesPerMinute pagesPerMinute = null;

	/**
	 * Pages per minute color, or null if not specified or wildcarded.
	 * @serial
	 */
	public PagesPerMinuteColor pagesPerMinuteColor = null;

// Exported constructors.

	/**
	 * Constructs a new printer description entry with all fields null 
	 * (unspecified or wildcarded). 
	 */
	public PrinterDescriptionEntry()
		{
		}

	/**
	 * Constructs a new printer description entry with the given printer 
	 * description attribute values. Any argument may be null to leave the 
	 * corresponding field unspecified (wildcarded). 
	 */
	public PrinterDescriptionEntry
		(PrinterName printerName,
		 PrinterLocation printerLocation,
		 PrinterInfo printerInfo,
		 PrinterMoreInfo printerMoreInfo,
		 PrinterMakeAndModel printerMakeAndModel,
		 PrinterMoreInfoManufacturer printerMoreInfoManufacturer,
		 ColorSupported colorSupported,
		 PDLOverrideSupported pdlOverrideSupported,
		 PagesPerMinute pagesPerMinute,
		 PagesPerMinuteColor pagesPerMinuteColor)
		{
		this.printerName = printerName;
		this.printerLocation = printerLocation;
		this.printerInfo = printerInfo;
		this.printerMoreInfo = printerMoreInfo;
		this.printerMakeAndModel = printerMakeAndModel;
		this.printerMoreInfoManufacturer = printerMoreInfoManufacturer;
		this.colorSupported = colorSupported;
		this.pdlOverrideSupported = pdlOverrideSupported;
		this.pagesPerMinute = pagesPerMinute;
		this.pagesPerMinuteColor = pagesPerMinuteColor;
		}

	/**
	 * Constructs a new printer description entry with the printer description 
	 * attribute values from the given array. All fields not present in the 
	 * given array are set to null (unspecified or wildcarded). 
	 *
	 * @param  theAttributes
	 *     Array of printer description attributes. Each element in the array 
	 *     must be an instance of one of the printer description attributes 
	 *     stored in a printer description entry. At most one instance of a 
	 *     particular printer description attribute may appear in the array. 
	 *     Null elements in the array are ignored. If <CODE>theAttributes</CODE> 
	 *     is null, a printer description entry with <I>all</I> fields null 
	 *     (unspecified or wildcarded) is constructed. 
	 *
	 * @exception  IllegalArgumentException
	 *     (unchecked exception) Thrown if an element in 
	 *     <CODE>theAttributes</CODE> is not an instance of one of the printer 
	 *     description attributes stored in a printer description entry, or if a 
	 *     particular printer description attribute appears more than once in 
	 *     <CODE>theAttributes</CODE>. 
	 */
	public PrinterDescriptionEntry
		(Attribute[] theAttributes)
		{
		int n = theAttributes == null ? 0 : theAttributes.length;
		for (int i = 0; i < n; ++ i)
			{
			Attribute theAttribute = theAttributes[i];
			if (theAttribute == null)
				{
				// Ignore it.
				}
			else if (theAttribute instanceof PrinterName)
				{
				printerName = (PrinterName)
					verifyNotDuplicated (printerName, theAttribute);
				}
			else if (theAttribute instanceof PrinterLocation)
				{
				printerLocation = (PrinterLocation)
					verifyNotDuplicated (printerLocation, theAttribute);
				}
			else if (theAttribute instanceof PrinterInfo)
				{
				printerInfo = (PrinterInfo)
					verifyNotDuplicated (printerInfo, theAttribute);
				}
			else if (theAttribute instanceof PrinterMoreInfo)
				{
				printerMoreInfo = (PrinterMoreInfo)
					verifyNotDuplicated (printerMoreInfo, theAttribute);
				}
			else if (theAttribute instanceof PrinterMakeAndModel)
				{
				printerMakeAndModel = (PrinterMakeAndModel)
					verifyNotDuplicated (printerMakeAndModel, theAttribute);
				}
			else if (theAttribute instanceof PrinterMoreInfoManufacturer)
				{
				printerMoreInfoManufacturer = (PrinterMoreInfoManufacturer)
					verifyNotDuplicated (printerMoreInfoManufacturer, theAttribute);
				}
			else if (theAttribute instanceof ColorSupported)
				{
				colorSupported = (ColorSupported)
					verifyNotDuplicated (colorSupported, theAttribute);
				}
			else if (theAttribute instanceof PDLOverrideSupported)
				{
				pdlOverrideSupported = (PDLOverrideSupported)
					verifyNotDuplicated (pdlOverrideSupported, theAttribute);
				}
			else if (theAttribute instanceof PagesPerMinute)
				{
				pagesPerMinute = (PagesPerMinute)
					verifyNotDuplicated (pagesPerMinute, theAttribute);
				}
			else if (theAttribute instanceof PagesPerMinuteColor)
				{
				pagesPerMinuteColor = (PagesPerMinuteColor)
					verifyNotDuplicated (pagesPerMinuteColor, theAttribute);
				}
			else
				{
				throw new IllegalArgumentException
					("net.jini.print.lookup.PrinterDescriptionEntry.PrinterDescriptionEntry(): Non-included attribute encountered");
				}
			}
		}

	private static Attribute verifyNotDuplicated
		(Attribute theField,
		 Attribute theAttribute)
		{
		if (theField != null)
			{
			throw new IllegalArgumentException
				("net.jini.print.lookup.PrinterDescriptionEntry.PrinterDescriptionEntry(): Duplicate attribute encountered");
			}
		return theAttribute;
		}

	}