/*
 Copyright 2002-2006 The Members of the OSS through Java(TM) Initiative.
 All rights reserved. Use is subject to license terms.
 */

package javax.oss;

/**
 * Base interface from which all Value objects must be derived. Represents both
 * an attribute dirty marker and a generic attribute accessor. Classes
 * implementing a value interface provide several ways to access the attributes:
 * <UL>
 * <LI>Attributes can be accessed through standard JavaBeans get/set (is/set)
 * methods.
 * <LI>Attributes can be accessed through the generic methods:
 * <UL>
 * <LI><CODE>public Object getAttributeValue(String attributeName)</CODE>
 * <LI><CODE>public void setAttributeValue(String attributeName, Object
 * newValue)</CODE>
 * </UL>
 * </UL>
 * A client needs to know which attributes exist in order to provide correct
 * attributeNames. It can get this information with a call to <CODE>public
 * String[] getAttributeNames()</CODE>.
 * <P>
 * An attribute may or may not be populated with a value.
 * <p>
 * An attribute is populated by calling <CODE>public void
 * setAttributeValue(...)</CODE>.
 * <p>
 * A client can determine if an attribute is populated by calling <CODE>public
 * boolean isPopulated(String attributeName)</CODE>.
 *<p>
 * Note a bout the dirty marker:
 *<BR>
 * It is ortogonal to the "populated" marker and it is not define in this specification.
 *<BR>
 * The dirty marker of an attribute determine is the attribute is 
 * clean or not. For Example, an attribute that has been written 
 * by the application, but the change have not been replicated
 * into the persistent representation of this attribute. This 
 * "dirty" information will be mainly used by the implementation/application.
 * <p>
 * For example:
 * <PRE>
 * ServiceValue myService = serviceSession.getServiceValue(myServiceKey);
 * // All Populated attributes of myService will not be "dirty".
 * myService.setMandatory(true);
 * // "mandatory" attribute is now tag "dirty"
 * serviceSession.setService(myService);
 * // When the client is calling the setService method, 
 * // the session knows, that only the "mandatory" attribute has been changed, 
 * // and nothing else.
 *</PRE>
 * 
 * @author OSS through Java Initiative, Vincent Perrot Sun Microsystems Inc.
 * @version 1.3
 * @since March 2005
 */
public interface AttributeAccess extends java.io.Serializable, Cloneable {

	/**
	 * Gets multiple attribute values given an array of attribute names.
	 * 
	 * @param attributeNames
	 * @exception java.lang.IllegalArgumentException
	 *                (if null array is provided or if one of the attributes is
	 *                not recognized)
	 * @exception java.lang.IllegalStateException
	 *                (if one of the attributes is not populated)
	 * @exception javax.oss.OssUnsupportedAttributeException
	 *                (if one of the attributes is not supported)
	 */
	public java.util.Map getAttributeValues(String[] attributeNames)
			throws java.lang.IllegalArgumentException,
			java.lang.IllegalStateException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Sets multiple attribute values.
	 * 
	 * @param attributeNamesAndValuePairs
	 * @exception java.lang.IllegalArgumentException
	 *                (one of the attributes is not well formed or unrecognized)
	 * @exception javax.oss.OssUnsupportedAttributeException
	 *                (one of the attributes is optional and is not supported)
	 */

	public void setAttributeValues(java.util.Map attributeNamesAndValuePairs)
			throws java.lang.IllegalArgumentException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Get all populated attribute values. If no attributes are populated an
	 * empty Map is returned.
	 * 
	 * @return a map of all populated attributes ([name,value] pair)
	 */

	public java.util.Map getAllPopulatedAttributes();

	/**
	 * Returns the value of the specified attribute.
	 * 
	 * @param attributeName
	 *            the attribute's name
	 * @return the attribute's value. Primitive types are wrapped in their
	 *         respective classes.
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized)
	 * @exception java.lang.IllegalStateException
	 *                (the attribute is not populated)
	 * @exception javax.oss.OssUnsupportedAttributeException
	 *                (the attribute is optional and not supported)
	 * 
	 */
	public Object getAttributeValue(String attributeName)
			throws java.lang.IllegalArgumentException,
			java.lang.IllegalStateException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Assign a new value to an attribute.
	 * <p>
	 * Even though some attributes may be read-only in the server
	 * implementation, they can be set here nonetheless. This is because value
	 * objects are also used as templates for a "query by template". To see
	 * which attributes can be set in the server implementation, the client
	 * needs to call <CODE>getSettableAttributeNames()</CODE>.
	 * 
	 * @param attributeName
	 *            The attribute's name which shall be changed
	 * @param value
	 *            The attribute's new value. This can either be:
	 *            <UL>
	 *            <LI>An object of the type associated with <CODE>attributeName</CODE>
	 *            <LI>A wrapper object for a primitive type, e.g. an <CODE>Integer</CODE>
	 *            wrapping an <CODE>int</CODE>
	 *            </UL>
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized, or the
	 *                value is bad)
	 * @exception javax.oss.OssUnsupportedAttributeException
	 *                (the attribute is optional and is not supported)
	 */
	public void setAttributeValue(String attributeName, Object value)
			throws java.lang.IllegalArgumentException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Returns all attribute names, which are available in this value object.
	 * <p>
	 * The returned names may be used as arguments to the generic methods <CODE>getAttributeValue(...)</CODE>
	 * and <CODE>setAttributeValue(...)</CODE>.
	 * <p>
	 * This method may be used by generic clients to obtain information on the
	 * attributes. It does not say anything about the state of an attribute,
	 * i.e. if it is populated or not.
	 * 
	 * @return an array containing all attribute names in no particular order.
	 */
	public String[] getAttributeNames();

	/**
	 * Gets the names of all populated attributes.
	 * <p>
	 * Although an attribute is populated, it can be <CODE>null</CODE>!
	 * 
	 * @return names of all poplulated attributes. When no attributes are
	 *         populated an <B>empty array</B> is returned. It is required to
	 *         return a subset of the array returned by <CODE>getAttributeNames()</CODE>.
	 */
	public String[] getPopulatedAttributeNames();

	/**
	 * Checks if a specific attribute is populated.
	 * 
	 * @param attributeName
	 *            the name of the attribute which is to be checked for
	 *            population.
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized, or the
	 *                value is bad)
	 * @exception javax.oss.OssUnsupportedAttributeException
	 *                (the attribute is optional and is not supported)
	 * @return true, if this attribute is populated, false otherwise.
	 * @see #isFullyPopulated()
	 */
	public boolean isPopulated(String attributeName)
			throws java.lang.IllegalArgumentException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Returns true, if all attributes in this value object are populated.
	 * 
	 * @return true, if all attributes are populated, false otherwise.
	 * @see #isPopulated(String attribute)
	 */
	public boolean isFullyPopulated();

	/**
	 * Reset all the attributes to unpopulated.
	 */
	public void unpopulateAllAttributes();

	/**
	 * Marks a single attribute as unpopulated. After this call getAttribute(
	 * String attributeName ) must raise the IllegalStateException.
	 * 
	 * @param attributeName
	 *            name of the attribute to be unpopulated.
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized, or the
	 *                value is bad)
	 * @exception javax.oss.UnsupportedAttributeException
	 *                (the attribute is optional and is not supported)
	 * @see #unpopulateAllAttributes()
	 */
	public void unpopulateAttribute(String attributeName)
			throws java.lang.IllegalArgumentException,
			javax.oss.OssUnsupportedAttributeException;

	/**
	 * Provides run-time support for the discovery of optional attributes.
	 * 
	 * @return the names of the optional attributes supported by the server.
	 */
	public String[] getSupportedOptionalAttributeNames();

	/**
	 * Returns the array of supported types of the given attribute name, or null if the attribute
	 * name is unknown. If the attribute is an enumeration based attribute like:
	 * <UL>
	 * <LI> *State
	 * <LI> *Status
	 * <LI> etc
	 * </UL>
	 * this method shall return the type of the definition instead of int or
	 * String.
	 * 
	 * @param attributeName
	 *            name of the attribute
	 * @return the array of supported types of the given attribute name
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized, or the
	 *                value is bad)
	 */
	public String[] attributeTypeFor(String attributeName)
			throws java.lang.IllegalArgumentException;

	/**
	 * Returns true if the given attribute is in a format of an enumeration. If
	 * true is returned, then a call to attributeTypeFor() method will return
	 * the type of the class that contains the possible value definitions rather
	 * than the proper type of the handle value.
	 * <p>
	 * For exemple: 
         * <PRE> if
	 * (troubleTicketValue.isEnumerationBased("troubleTicketState")){
	 * System.out.println("tt state type is
	 * "+troubeTicketValue.attributeTypeFor("troubleTicketState")); // displays
	 * javax.oss.cbe.trouble.TroubleTicketState instead of java.lang.String
	 * </PRE>
	 * <p>
	 * 
	 * @param attributeName
	 *            the name of the attribute to check
	 * @return true if the attribute is an enumeration type, false otherwise.
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is null or is not recognized, or the
	 *                value is bad)
	 */

	public boolean isEnumerationBased(String attributeName) throws java.lang.IllegalArgumentException;

	/**
	 * Generic factory method for supported types.
	 * 
	 * @param typeName the type of the object to be created
	 * @return the new created instance of the given type
	 * @exception java.lang.IllegalArgumentException
	 *                (the attribute name is not recognized, or the
	 *                value is bad)
	 */
	public Object make(String typeName) throws java.lang.IllegalArgumentException;

}
